From 5ed1045b8d4fc984fd10ceebeeb6b75df0a8d56f Mon Sep 17 00:00:00 2001 From: wolfpan Date: Sat, 31 Jul 2021 20:36:12 +0800 Subject: [PATCH 01/34] =?UTF-8?q?=E5=B0=86windows=E7=9A=84=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E6=A3=80=E6=9F=A5=E5=88=87=E6=8D=A2=E8=87=B3requireme?= =?UTF-8?q?nts.txt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- check_dependency.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/check_dependency.py b/check_dependency.py index 6544eae9..855ca3bd 100644 --- a/check_dependency.py +++ b/check_dependency.py @@ -235,7 +235,7 @@ def reinstall_requirements_with_gui(): def th_f(): if platform.system().lower() == "windows": - req_name = 'requirements_dev.txt' + req_name = 'requirements.txt' elif platform.system().lower().startswith("linux"): req_name = 'requirements_linux.txt' elif platform.system().lower().startswith("darwin"): -- Gitee From c6f7deacc5ff13906a07dc7c4211f3d809b66730 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Sat, 31 Jul 2021 22:47:06 +0800 Subject: [PATCH 02/34] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=BC=BA=E5=A4=B1?= =?UTF-8?q?=E7=9A=84chardet=E4=BD=9C=E4=B8=BA=E4=BE=9D=E8=B5=96=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E4=BF=AE=E6=AD=A3=E8=87=AA=E5=8A=A8=E5=AE=89=E8=A3=85?= =?UTF-8?q?=E6=97=B6=E5=AF=B9=E5=A4=A7=E9=87=8F=E4=BE=9D=E8=B5=96=E9=80=90?= =?UTF-8?q?=E4=B8=80=E8=BF=9B=E8=A1=8C=E6=A3=80=E6=9F=A5=E6=97=B6=E7=9A=84?= =?UTF-8?q?=E6=80=A7=E8=83=BD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- check_dependency.py | 47 +++++++++++++++++++-------------------------- requirements.txt | 3 +-- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/check_dependency.py b/check_dependency.py index 855ca3bd..833df7a4 100644 --- a/check_dependency.py +++ b/check_dependency.py @@ -223,17 +223,20 @@ def reinstall_requirements_with_gui(): text = tk.Text(root) text.pack() - class A(): - def read(self): - return - - def write(self, ch: str): - text.insert("end", ch) - return - - a = A() + def gui_print(line: str, end='\n'): + text.insert('end', f'{line}{end}') + text.see('end') def th_f(): + try: + import chardet + except: + gui_print('chardet not found, installing ...') + with subprocess.Popen(f'{sys.executable} -m pip install chardet', stdout=subprocess.PIPE) as p: + p.stdout.read() + gui_print('chardet installed') + import chardet + if platform.system().lower() == "windows": req_name = 'requirements.txt' elif platform.system().lower().startswith("linux"): @@ -243,24 +246,14 @@ def reinstall_requirements_with_gui(): else: raise SystemError('Platform not supported!') req_path = os.path.join(os.path.dirname(__file__), req_name) - with open(req_path, 'r') as f: - requirements = [line.strip() for line in f.readlines()] - print(requirements) - - for i, req in enumerate(requirements): - req = req.strip() - if req == "": - continue - text.insert("end", f"正在安装{i + 1}/{len(requirements)}:%s\n" % req) - if req.find('>') != -1 or req.find('<') != -1 or req.find('=') != -1: - ret = os.system( - f'{sys.executable} -m pip install {req} -i https://mirrors.cloud.tencent.com/pypi/simple') - else: - ret = os.system( - f'{sys.executable} -m pip install --upgrade {req} -i https://mirrors.cloud.tencent.com/pypi/simple') - - text.insert("end", "已安装:%s\n" % req) - text.see("end") + mirror = 'https://mirrors.cloud.tencent.com/pypi/simple' + cmd = f'{sys.executable} -m pip install -i {mirror} -r {req_path}' + + with subprocess.Popen(cmd, stdout=subprocess.PIPE) as p: + for line in p.stdout: + encoding = chardet.detect(line)['encoding'] + line = line.decode(encoding) + gui_print(line, end='') root.destroy() th = threading.Thread(target=th_f) diff --git a/requirements.txt b/requirements.txt index 45dd7f37..ca0dae25 100644 --- a/requirements.txt +++ b/requirements.txt @@ -58,5 +58,4 @@ pyminer_comm>=0.7.1 ipyparams pathspec codegen - - +chardet \ No newline at end of file -- Gitee From f5da24786dd55c08210a47004b0fb0084b1b2f7f Mon Sep 17 00:00:00 2001 From: wolfpan Date: Sun, 1 Aug 2021 00:47:48 +0800 Subject: [PATCH 03/34] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- features/extensions/extensionlib/extension_lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/extensions/extensionlib/extension_lib.py b/features/extensions/extensionlib/extension_lib.py index 90126d73..c8410e76 100644 --- a/features/extensions/extensionlib/extension_lib.py +++ b/features/extensions/extensionlib/extension_lib.py @@ -158,7 +158,7 @@ def wrapper(): dlg.setParent(win) dlg.exec_() - class Signal(): + class Signal: @staticmethod def get_close_signal() -> Signal: """ -- Gitee From b07b81cfa07a54568eec1d599ce428148a3c621f Mon Sep 17 00:00:00 2001 From: wolfpan Date: Sun, 1 Aug 2021 01:13:00 +0800 Subject: [PATCH 04/34] =?UTF-8?q?=E5=85=81=E8=AE=B8=E4=BB=85=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E6=8C=87=E5=AE=9A=E7=9A=84=E6=8F=92=E4=BB=B6=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BB=85=E5=8A=A0=E8=BD=BDcode=5Feditor?= =?UTF-8?q?=E7=9A=84=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app2.py | 41 +++++++++++++++++++++++------- tests/test_code_editor/__init__.py | 0 tests/test_code_editor/run_main.py | 5 ++++ 3 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 tests/test_code_editor/__init__.py create mode 100644 tests/test_code_editor/run_main.py diff --git a/app2.py b/app2.py index 902f4197..b62974b2 100644 --- a/app2.py +++ b/app2.py @@ -59,7 +59,7 @@ os.environ['QT_API'] = 'pyside2' os.environ['PYQTGRAPH_QT_LIB'] = 'PySide2' os.environ['FORCE_QT_API'] = "1" -from typing import List, Callable, Tuple, ClassVar +from typing import List, Callable, Tuple, ClassVar, Optional from PySide2.QtCore import Signal, QTimer, Qt, QCoreApplication from PySide2.QtGui import QCloseEvent, QTextCursor, QResizeEvent, QMoveEvent, QFont, QIcon, QPixmap from PySide2.QtWidgets import QApplication, QMessageBox, QSplashScreen, QStatusBar, QDialog, QVBoxLayout, QProgressBar @@ -128,14 +128,21 @@ class MainWindow(BaseMainWindow): settings_changed_signal = Signal() @classmethod - def __new__(cls, *args): + def __new__(cls, *args, **kwargs): if not hasattr(cls, 'instance'): - instance = super().__new__(cls) + instance = super().__new__(cls, *args, **kwargs) cls.instance = instance return cls.instance - def __init__(self, parent=None): + def __init__(self, parent=None, extensions: Optional[List[str]] = None): + """主程序 + + Args: + parent: 父窗口,由于是主程序,始终是None + extensions: 如果指定,则仅加载指定的插件,否则加载全部插件 + """ super().__init__(parent) + self.extension_names = extensions # 需要加载的插件名称 # settings = Settings() t00 = time.time() self.main_option_form = base.OptionForm() @@ -175,7 +182,11 @@ class MainWindow(BaseMainWindow): # 加载插件 self.extensions_manager = extensions_manager - self.extensions_manager.load_from_extension_folder(updateSplashMsg) + if self.extension_names is None: + self.extensions_manager.load_from_extension_folder(updateSplashMsg) + else: + for name in self.extension_names: + self.extensions_manager.load(name) self.ext_manager_widget = PMPageExt(self) dw = self.add_widget_on_dock( @@ -476,7 +487,18 @@ class MainWindow(BaseMainWindow): console.append(html) -def main(test_function: Callable[[MainWindow], None] = None): +def main( + test_function: Callable[[MainWindow], None] = None, + extensions: Optional[List[str]] = None, + show_welcome=True, +): + """启动主程序 + + Args: + test_function: 测试函数 + extensions: 需要加载的插件名 + show_welcome: 是否显示欢迎屏 + """ global t0 PMExceptions.get_instance().signal_exception_occured.connect(on_exception) @@ -504,7 +526,7 @@ def main(test_function: Callable[[MainWindow], None] = None): load_translator(app) # 启动主程序 - window = MainWindow() + window = MainWindow(extensions=extensions) t1 = time.time() @@ -513,8 +535,9 @@ def main(test_function: Callable[[MainWindow], None] = None): if test_function is None: # 展示快速启动窗口。只有在设置为True的情况下才显示起始页。 - if utils.get_settings_item_from_file("config.ini", "MAIN/SHOW_START_PAGE"): - window.first_form_display() + if show_welcome: + if utils.get_settings_item_from_file("config.ini", "MAIN/SHOW_START_PAGE"): + window.first_form_display() else: test_function(window) logging.info('boot time elapsed:%f s' % (t1 - t0)) diff --git a/tests/test_code_editor/__init__.py b/tests/test_code_editor/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_code_editor/run_main.py b/tests/test_code_editor/run_main.py new file mode 100644 index 00000000..05df9e8b --- /dev/null +++ b/tests/test_code_editor/run_main.py @@ -0,0 +1,5 @@ +from app2 import main + + +def test_main(): + main(extensions=['code_editor'], show_welcome=False) -- Gitee From c45122e9a99f0dce70d3abe59632daab59cab252 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Sun, 1 Aug 2021 01:42:37 +0800 Subject: [PATCH 05/34] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../code_editor/codeeditor/qtpyeditor/Utilities/autocomp.py | 6 +++--- tests/test_code_editor/run_main.py | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/code_editor/codeeditor/qtpyeditor/Utilities/autocomp.py b/packages/code_editor/codeeditor/qtpyeditor/Utilities/autocomp.py index 19459e43..76e41153 100644 --- a/packages/code_editor/codeeditor/qtpyeditor/Utilities/autocomp.py +++ b/packages/code_editor/codeeditor/qtpyeditor/Utilities/autocomp.py @@ -13,9 +13,9 @@ logger.setLevel(logging.DEBUG) class AutoCompThread(QThread): - ''' + """ 当一段时间没有补全需求之后,后台自动补全线程会进入休眠模式。下一次补全请求则会唤醒该后台线程。 - ''' + """ trigger = Signal(tuple, list) def __init__(self): @@ -33,7 +33,7 @@ class AutoCompThread(QThread): except ImportError: print('Jedi not installed.install jedi for better auto-completion!') return - while (1): + while 1: if self.stop_flag: return diff --git a/tests/test_code_editor/run_main.py b/tests/test_code_editor/run_main.py index 05df9e8b..dce1ce11 100644 --- a/tests/test_code_editor/run_main.py +++ b/tests/test_code_editor/run_main.py @@ -1,5 +1,4 @@ from app2 import main - -def test_main(): +if __name__ == '__main__': main(extensions=['code_editor'], show_welcome=False) -- Gitee From 0b0139128beb82cb4ef36276679c1011810ae820 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Sun, 1 Aug 2021 03:13:20 +0800 Subject: [PATCH 06/34] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../code_editor/codeeditor/qtpyeditor/codeedit/pythonedit.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/code_editor/codeeditor/qtpyeditor/codeedit/pythonedit.py b/packages/code_editor/codeeditor/qtpyeditor/codeedit/pythonedit.py index 61a4347e..78976dde 100644 --- a/packages/code_editor/codeeditor/qtpyeditor/codeedit/pythonedit.py +++ b/packages/code_editor/codeeditor/qtpyeditor/codeedit/pythonedit.py @@ -45,12 +45,12 @@ class PMPythonCodeEdit(PMBaseCodeEdit): self.hint_widget.setStyleSheet("background-color:#d8d8d8") def on_autocomp_signal_received(self, text_cursor_content: tuple, completions: List['jedi.api.Completion']): - ''' + """ 当收到自动补全提示信号时,执行的函数。 :param text_cursor_content:(row,col,hint_when_completion_triggered) :param completions: :return: - ''' + """ hint = self._get_hint() logger.debug('hint_when_completion_triggered:{0},current_hint:{1}'.format(text_cursor_content[2], hint)) -- Gitee From 161bf399126b03c439916952e4ef7a4a4ffbb73b Mon Sep 17 00:00:00 2001 From: wolfpan Date: Sun, 1 Aug 2021 03:26:06 +0800 Subject: [PATCH 07/34] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qtpyeditor/codeedit/basecodeedit.py | 20 ++---- .../codeeditor/qtpyeditor/syntaxana.py | 66 +++++++++---------- 2 files changed, 40 insertions(+), 46 deletions(-) diff --git a/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py b/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py index f477177b..b365d50b 100644 --- a/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py +++ b/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py @@ -9,21 +9,16 @@ import re import time from itertools import groupby from queue import Queue +from typing import List, Tuple, Dict, TYPE_CHECKING +from PySide2.QtCore import Qt, QModelIndex, Signal, QTimer, QUrl from PySide2.QtGui import QDropEvent, QPixmap - -from PySide2.QtWidgets import QAction -from PySide2.QtCore import QRegExp, Qt, QModelIndex, Signal, QThread, QCoreApplication, QTimer, QUrl, QSize -from PySide2.QtWidgets import QApplication, QFileDialog, QTextEdit, QTabWidget, \ - QMessageBox, QListWidget, QListWidgetItem, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QPlainTextEdit, QShortcut, \ - QTableWidget, QTableWidgetItem, QHeaderView -from PySide2.QtGui import QTextCursor, QKeyEvent, QMouseEvent, QIcon, QKeySequence, QFocusEvent, QColor, QTextFormat, \ - QPainter, QTextDocument, QTextBlock -from typing import List, Tuple, Dict, TYPE_CHECKING +from PySide2.QtGui import QTextCursor, QKeyEvent, QMouseEvent, QIcon, QFocusEvent +from PySide2.QtWidgets import QApplication, QWidget, QPlainTextEdit, QTableWidget, QTableWidgetItem, QHeaderView from packages.code_editor.codeeditor.qtpyeditor.highlighters.python import PythonHighlighter -from packages.code_editor.codeeditor.qtpyeditor.syntaxana import getIndent from packages.code_editor.codeeditor.qtpyeditor.linenumber import QCodeEditor +from packages.code_editor.codeeditor.qtpyeditor.syntaxana import getIndent # from pmgwidgets import create_icon @@ -69,7 +64,6 @@ class AutoCompList(QTableWidget): # self.horizontalHeader().setMinimumWidth(300) # self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) - def verticalHeader(self) -> QHeaderView: return super(AutoCompList, self).verticalHeader() @@ -379,10 +373,10 @@ class PMBaseCodeEdit(QCodeEditor): cursor.endEditBlock() def on_return_pressed(self): - ''' + """ 按回车换行的方法 :return: - ''' + """ cursor = self.textCursor() cursor.beginEditBlock() text = cursor.block().text() diff --git a/packages/code_editor/codeeditor/qtpyeditor/syntaxana.py b/packages/code_editor/codeeditor/qtpyeditor/syntaxana.py index d000b8ee..1fb4b922 100644 --- a/packages/code_editor/codeeditor/qtpyeditor/syntaxana.py +++ b/packages/code_editor/codeeditor/qtpyeditor/syntaxana.py @@ -4,16 +4,16 @@ # @Email: 1295752786@qq.com # @File: syntaxana.py # -*- coding: utf-8 -*- -''' +""" powered by NovalIDE 来自NovalIDE的词法分析模块 作者:侯展意 词法分析模块的重要组成单元、 依靠各种正则表达式进行特征的提取。 -''' -from typing import List, Tuple, Dict +""" import re +from typing import List, Tuple, Dict def getReplacingDic() -> Dict: @@ -22,10 +22,10 @@ def getReplacingDic() -> Dict: dic['。'] = '.' dic[';'] = ';' dic[':'] = ':' - dic['‘'] = '\'' - dic['’'] = '\'' - dic['“'] = '\"' - dic['”'] = '\"' + dic['‘'] = "'" + dic['’'] = "'" + dic['“'] = '"' + dic['”'] = '"' dic['【'] = '[' dic['】'] = ']' dic['('] = '(' @@ -36,9 +36,9 @@ def getReplacingDic() -> Dict: def getIndent(s: str) -> Tuple[str, int]: s = s.replace('\t', ' ') # tab替换成四个空格 s = s.rstrip() - if (len(s) > 0): + if len(s) > 0: for i, ch in enumerate(s): - if (ch != ' '): + if ch != ' ': return s[i:], i return "", i + 1 else: @@ -47,7 +47,7 @@ def getIndent(s: str) -> Tuple[str, int]: def removeComment(s: str) -> str: pos = s.find('#') - if (pos != -1): + if pos != -1: return s[:pos] else: return s @@ -59,7 +59,7 @@ def getStringContent(row): def removeStringContent(row: str) -> str: row = row.replace('\"', '\'') - if (row.count('\'') >= 2): + if row.count('\'') >= 2: s = getAllFromRegex(regex=r'[\'](.*?)[\']', st=row) for item in s: row = row.replace('\'%s\'' % item, '\'\'') # 带着分号一起换掉。 @@ -81,13 +81,13 @@ def getAllFromRegex(regex: str, st: str) -> List[str]: def getInfoFromRegex(regex: str, st: str) -> str: # 从正则表达式中获取信息的函数。如果没有任何结果则返回0。 foundList = re.findall(re.compile(regex, re.S), st) item = '' - if (foundList != []): + if foundList != []: item = foundList[0] return item def getWordsFromString(s: str) -> list: - if (s != ''): + if s != '': syms = s.split(',') # 用逗号分隔开。 for i in range(len(syms)): syms[i] = syms[i].strip() @@ -126,10 +126,10 @@ def getBracketedContent(row: str) -> Tuple[str, str, str]: # 获取任何类型 length = len(row) for i in range(len(lst)): lst[i] = row.find(symList[i]) - if (lst[i] == -1): + if lst[i] == -1: lst[i] = length minVal = min(lst) - if (minVal == length): # 说明根本没括号 + if minVal == length: # 说明根本没括号 return '', '', row[:minVal] # 所以返回值不仅没有括号,还没有括号中的内容(废话),只是返回括号前面的东西。 else: pos = lst.index(minVal) # 获取最小值的索引 @@ -143,13 +143,13 @@ def getFuncArgs(row: str) -> List[str]: # 获取函数的输入参数。 li = getWordsFromString(s) - if (len(li) > 0): - if (li[0] == 'self'): # 不允许函数的第一个参数名字叫self。 + if len(li) > 0: + if li[0] == 'self': # 不允许函数的第一个参数名字叫self。 li.pop(0) for i in range(len(li)): eqSymPos = li[i].find('=') - if (eqSymPos != -1): # 如果eqSymPos中有一个等号 + if eqSymPos != -1: # 如果eqSymPos中有一个等号 li[i] = li[i][:eqSymPos] # 那么将等号去除 colonSymPos = li[i].find(':') if colonSymPos != -1: @@ -168,7 +168,7 @@ def getLocalVarNames(row: str) -> List[str]: # 获取局部变量的名称。 words = getWordsFromString(li) result = [] for w in words: # 如果是函数的方法,则不可。 - if (w.find('.') == -1): + if w.find('.') == -1: result.append(w) return result @@ -182,36 +182,36 @@ def is_number(str_number: str) -> bool: def getForVariables(row: str) -> List[int]: - ''' + """ 获取for循环中定义的变量。 - ''' + """ s = getInfoFromRegex(r'for(.*?)in', row) s = s.strip() return getWordsFromString(s) def getVarType(row: str) -> str: - ''' + """ 获取变量的类型,比如集合,数字等等。 - ''' + """ bracket, content, outer = getBracketedContent(row) li = outer.split('=') - if (len(li) >= 1): + if len(li) >= 1: - if (li[1].strip() == ''): # 这种情况下为直接赋值的语句, - if (bracket == '('): + if li[1].strip() == '': # 这种情况下为直接赋值的语句, + if bracket == '(': return ':tuple' - elif (bracket == '['): + elif bracket == '[': return ':list' else: st = li[1].split(',')[0] - if (is_number(st)): + if is_number(st): return ':number' return '' -class Row(): +class Row: def __init__(self, pos: int, text: str, indent: int) -> None: self.pos = pos self.text = text @@ -239,7 +239,7 @@ def regularize(rawText: List[str]) -> List[Row]: l = removeStringContent(l) l = removeComment(l) - if (skipLine == False): + if skipLine == False: row, currentIndent = getIndent(l) # 获取当前的行名和缩进,同时修剪掉行首的空格 currentRow = Row(i, row, currentIndent) rowList.append(currentRow) @@ -250,12 +250,12 @@ def regularize(rawText: List[str]) -> List[Row]: cp = checkPar(currentRow.text) - if (cp == 0): # 如果括号不匹配,那么就再继续进行,直至寻找到符合要求的行为止。 + if cp == 0: # 如果括号不匹配,那么就再继续进行,直至寻找到符合要求的行为止。 skipLine = True - if (len(currentRow.text) >= 200): # 长度超出,强行退出。 + if len(currentRow.text) >= 200: # 长度超出,强行退出。 skipLine = False continue - elif (cp == -1): # 如果右边括号反倒更多,就跳出这种情况。 + elif cp == -1: # 如果右边括号反倒更多,就跳出这种情况。 skipLine = False continue else: -- Gitee From 9da9817952da36e10b7c4e655715c0ded9bcc25a Mon Sep 17 00:00:00 2001 From: wolfpan Date: Sun, 1 Aug 2021 13:12:08 +0800 Subject: [PATCH 08/34] =?UTF-8?q?=E4=BD=BF=E7=94=A8parso=E5=88=86=E6=9E=90?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=AE=9E=E7=8E=B0=E6=8B=AC=E5=8F=B7?= =?UTF-8?q?=E7=9A=84=E8=AF=86=E5=88=AB=E4=B8=8E=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeeditor/grammar_analyzer.py | 61 +++++++++++++ .../qtpyeditor/codeedit/basecodeedit.py | 31 ++++--- requirements.txt | 3 +- .../test_code_editor/test_grammer/__init__.py | 0 .../test_grammer/test_python/__init__.py | 0 .../test_grammer/test_python/test_bracket.py | 91 +++++++++++++++++++ 6 files changed, 170 insertions(+), 16 deletions(-) create mode 100644 packages/code_editor/codeeditor/grammar_analyzer.py create mode 100644 tests/test_code_editor/test_grammer/__init__.py create mode 100644 tests/test_code_editor/test_grammer/test_python/__init__.py create mode 100644 tests/test_code_editor/test_grammer/test_python/test_bracket.py diff --git a/packages/code_editor/codeeditor/grammar_analyzer.py b/packages/code_editor/codeeditor/grammar_analyzer.py new file mode 100644 index 00000000..b56bd021 --- /dev/null +++ b/packages/code_editor/codeeditor/grammar_analyzer.py @@ -0,0 +1,61 @@ +from typing import Tuple, List, Union + +import parso +from parso.tree import Leaf, Node + + +class GrammarAnalyzer: + def __init__(self): + """ + 代码静态分析工具,用于识别括号匹配等内容 + """ + self.__code = '' + self.__parsed_node_cache = None + + def feed(self, code: str): + self.__code = code + self.__parsed_node_cache = None + + @property + def __parsed_node(self) -> Node: + """使用parso进行解析后的代码""" + if self.__parsed_node_cache is None: + self.__parsed_node_cache = parso.parse(self.__code) + return self.__parsed_node_cache + + def _convert_position_to_row_col(self, position: int) -> Tuple[int, int]: + left_part = self.__code[:position] + row = left_part.count('\n') + 1 + col = position - left_part.rfind('\n') - 1 + return row, col + + __PAIRS = {'(': ')', '[': ']', '{': '}'} + + def is_not_matched(self, position: Union[Tuple[int, int], int], left='('): + """是否需要添加另一个配对项 + + 对于如下代码:``print(a, b, c#)`` ,在光标位于#处时,按下右括号键,是不需要再添加一个括号的。 + 本方法即是为了解决这个问题,识别是否需要添加额外的括号。 + + Args: + position: 匹配位置 + left: 配对的左侧一项 + + Returns: + bool, 是否需要添加 + """ + if isinstance(position, int): + position = self._convert_position_to_row_col(position) + position: Tuple[int, int] + right = self.__PAIRS[left] + leaf: Leaf = self.__parsed_node.get_leaf_for_position(position) + node: Node = leaf.parent + child: Node + leaves: List[Node] = [leaf] + while node is not None: + # print(node.children) + leaves.extend([child for child in node.children if child is not leaf and child.type == 'operator']) + node, leaf = node.parent, leaf.parent + characters: List[str] = [leaf.get_code().strip() for leaf in leaves] + # print(characters, characters.count(left), characters.count(right)) + return characters.count(left) - characters.count(right) > 0 diff --git a/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py b/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py index b365d50b..0cb28b2b 100644 --- a/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py +++ b/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py @@ -16,6 +16,7 @@ from PySide2.QtGui import QDropEvent, QPixmap from PySide2.QtGui import QTextCursor, QKeyEvent, QMouseEvent, QIcon, QFocusEvent from PySide2.QtWidgets import QApplication, QWidget, QPlainTextEdit, QTableWidget, QTableWidgetItem, QHeaderView +from packages.code_editor.codeeditor.grammar_analyzer import GrammarAnalyzer from packages.code_editor.codeeditor.qtpyeditor.highlighters.python import PythonHighlighter from packages.code_editor.codeeditor.qtpyeditor.linenumber import QCodeEditor from packages.code_editor.codeeditor.qtpyeditor.syntaxana import getIndent @@ -324,32 +325,32 @@ class PMBaseCodeEdit(QCodeEditor): self.on_backspace(event) event.accept() return - elif k == Qt.Key_ParenLeft: + elif k in (Qt.Key_ParenLeft, Qt.Key_BracketLeft, Qt.Key_BraceLeft): cursor = self.textCursor() cursor.beginEditBlock() - cursor.insertText('()') + string = {Qt.Key_ParenLeft: '()', Qt.Key_BracketLeft: '[]', Qt.Key_BraceLeft: '{}'}[k] + cursor.insertText(string) cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.MoveAnchor, 1) cursor.endEditBlock() self.setTextCursor(cursor) event.accept() return - elif k == Qt.Key_BracketLeft: + elif k in (Qt.Key_ParenRight, Qt.Key_BracketRight, Qt.Key_BraceRight): cursor = self.textCursor() + code = self.toPlainText() cursor.beginEditBlock() - cursor.insertText('[]') - cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.MoveAnchor, 1) - cursor.endEditBlock() - self.setTextCursor(cursor) - event.accept() - return - elif k == Qt.Key_BraceLeft: - cursor = self.textCursor() - cursor.beginEditBlock() - cursor.insertText('{}') - cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.MoveAnchor, 1) + position = cursor.position() + left, right = { + Qt.Key_ParenRight: ('(', ')'), Qt.Key_BracketRight: ('[', ']'), Qt.Key_BraceRight: ('{', '}')}[k] + analyzer = GrammarAnalyzer() + analyzer.feed(code) + length = len(code) + if position == length or analyzer.is_not_matched(position, left) or code[position] != right: + cursor.insertText(right) + else: + cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.MoveAnchor, 1) cursor.endEditBlock() self.setTextCursor(cursor) - event.accept() return super().keyPressEvent(event) diff --git a/requirements.txt b/requirements.txt index ca0dae25..078381d7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -58,4 +58,5 @@ pyminer_comm>=0.7.1 ipyparams pathspec codegen -chardet \ No newline at end of file +chardet +parso \ No newline at end of file diff --git a/tests/test_code_editor/test_grammer/__init__.py b/tests/test_code_editor/test_grammer/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_code_editor/test_grammer/test_python/__init__.py b/tests/test_code_editor/test_grammer/test_python/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_code_editor/test_grammer/test_python/test_bracket.py b/tests/test_code_editor/test_grammer/test_python/test_bracket.py new file mode 100644 index 00000000..2d5af053 --- /dev/null +++ b/tests/test_code_editor/test_grammer/test_python/test_bracket.py @@ -0,0 +1,91 @@ +from unittest import TestCase + +from packages.code_editor.codeeditor.grammar_analyzer import GrammarAnalyzer + +func_def_1 = """ +def add(x, y): + return x + y +print(add(3, 5) +""" + + +def test_convert_position_to_row_col(): + """ + PyQt得到的position是一个整数,需要将其进行转化,方可被parso识别。 + """ + analyzer = GrammarAnalyzer() + analyzer.feed(func_def_1) + assert analyzer._convert_position_to_row_col(22) == (3, 6) + assert analyzer._convert_position_to_row_col(46) == (4, 13) + assert analyzer._convert_position_to_row_col(47) == (4, 14) + + +class TestBracket(TestCase): + """ + 测试JEDI的括号识别功能 + """ + + def setUp(self) -> None: + self.analyzer = GrammarAnalyzer() + + def test_normal(self): + self.analyzer.feed(func_def_1) + assert self.analyzer.is_not_matched((4, 15)) + assert self.analyzer.is_not_matched((4, 14)) + assert self.analyzer.is_not_matched(47) + + def test_line_1(self): + line_1 = """print(a, b, c)""" + self.analyzer.feed(line_1) + assert not self.analyzer.is_not_matched((1, 13)) + + def test_line_2(self): + line_2 = """print(a, b, c""" + self.analyzer.feed(line_2) + assert self.analyzer.is_not_matched((1, 13)) + + def test_line_3(self): + # 这个用例有问题,parso无法识别,暂不处理 + line_3 = """[][]""" + self.analyzer.feed(line_3) + # assert not self.analyzer.is_not_matched((1, 3), left='[') + + def test_line_4(self): + line_4 = """[][""" + self.analyzer.feed(line_4) + assert self.analyzer.is_not_matched((1, 3), left='[') + + def test_code_5(self): + code = """ +a = [[1, 2, 3], [5, 6, 7]] +b = a[1][2] +""" + self.analyzer.feed(code) + assert not self.analyzer.is_not_matched((3, 8), left='[') + + def test_code_6(self): + code = """ +a = [[1, 2, 3], [5, 6, 7]] +b = a[1[2] +""" + self.analyzer.feed(code) + assert self.analyzer.is_not_matched((3, 8), left='[') + + def test_code_7(self): + code = """ +print(1, 2, +abc(), +""" + self.analyzer.feed(code) + assert self.analyzer.is_not_matched((3, 6)) + + def test_code_8(self): + code = """ +a = [1, 2, [ +3, 4, 5, [ +6, 7, [8, 9], +], +10, +""" + self.analyzer.feed(code) + assert self.analyzer.is_not_matched((6, 2), left='[') -- Gitee From 0c5e58095fd9f279c3ac100fa2db9913cad1f966 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Sun, 1 Aug 2021 14:55:35 +0800 Subject: [PATCH 09/34] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/code_editor/codeeditor/grammar_analyzer.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/code_editor/codeeditor/grammar_analyzer.py b/packages/code_editor/codeeditor/grammar_analyzer.py index b56bd021..3e380264 100644 --- a/packages/code_editor/codeeditor/grammar_analyzer.py +++ b/packages/code_editor/codeeditor/grammar_analyzer.py @@ -12,7 +12,12 @@ class GrammarAnalyzer: self.__code = '' self.__parsed_node_cache = None - def feed(self, code: str): + def feed(self, code: str) -> None: + """使用当前编辑器里面的代码替换之前分析器中的代码 + + Args: + code: 当前编辑器中的代码 + """ self.__code = code self.__parsed_node_cache = None -- Gitee From ec289461ce0004fb06005c0a10357a72003c3b52 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Sun, 1 Aug 2021 16:14:50 +0800 Subject: [PATCH 10/34] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app2.py | 6 ++++-- features/extensions/extensionlib/extension_lib.py | 2 +- features/ui/pmwidgets/dockwidget.py | 4 ++++ features/ui/pmwidgets/pmmainwindow.py | 7 ++++++- tests/test_jupyter_notebook_support/__init__.py | 0 .../run_jupyter_notebook_support.py | 4 ++++ 6 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 tests/test_jupyter_notebook_support/__init__.py create mode 100644 tests/test_jupyter_notebook_support/run_jupyter_notebook_support.py diff --git a/app2.py b/app2.py index b62974b2..86636766 100644 --- a/app2.py +++ b/app2.py @@ -107,7 +107,8 @@ def updateSplashMsg(ext_load_status: dict): def try_hide_terminal(): - if not '-d' in sys.argv: + # TODO 上面有一个地方判断的入参为 ``debug`` ,和这里的 ``d`` 应该是一样的吧? + if '-d' not in sys.argv: if platform.system().lower() == 'windows': whnd = ctypes.windll.kernel32.GetConsoleWindow() if whnd != 0: @@ -440,7 +441,8 @@ class MainWindow(BaseMainWindow): utils.open_url("http://www.pyminer.com") def main_markdown_display(self): - print("TODO 添加markdown编辑器代码") + pass + # TODO 添加markdown编辑器代码 def main_new_script_display(self): from features.extensions.extensionlib.extension_lib import extension_lib diff --git a/features/extensions/extensionlib/extension_lib.py b/features/extensions/extensionlib/extension_lib.py index c8410e76..be5cc052 100644 --- a/features/extensions/extensionlib/extension_lib.py +++ b/features/extensions/extensionlib/extension_lib.py @@ -61,7 +61,7 @@ def wrapper(): """ return utils.get_root_dir() - class UI(): + class UI: @staticmethod def widget_exists(widget_name: str) -> bool: if widget_name in get_main_window().dock_widgets.keys(): diff --git a/features/ui/pmwidgets/dockwidget.py b/features/ui/pmwidgets/dockwidget.py index 2ebaf7dc..052ffdf1 100644 --- a/features/ui/pmwidgets/dockwidget.py +++ b/features/ui/pmwidgets/dockwidget.py @@ -15,3 +15,7 @@ class PMDockWidget(PMGDockWidget): self.hide() event.accept() main_window.refresh_view_configs() + + def bind_events(self): + """绑定该控件的所有事件,会在主程序加载结束后自动执行,不需要在__init__里面手动执行""" + pass diff --git a/features/ui/pmwidgets/pmmainwindow.py b/features/ui/pmwidgets/pmmainwindow.py index f7438501..431baa7c 100644 --- a/features/ui/pmwidgets/pmmainwindow.py +++ b/features/ui/pmwidgets/pmmainwindow.py @@ -39,12 +39,17 @@ class BaseMainWindow(QMainWindow): dialog_classes: Dict[str, 'QDialog'] = {} toolbars: Dict[str, QToolBar] = {} _current_toolbar_name: str = '' # 当前的窗口标题栏选项卡 - dock_widgets: Dict[str, 'PMDockWidget'] = {} + __dock_widgets: Dict[str, 'PMDockWidget'] dock_places = {'left': Qt.LeftDockWidgetArea, 'right': Qt.RightDockWidgetArea, 'top': Qt.TopDockWidgetArea, 'bottom': Qt.BottomDockWidgetArea} + @property + def dock_widgets(self): + return self.__dock_widgets + def __init__(self, parent=None): super().__init__(parent) + self.__dock_widgets = {} self.setContextMenuPolicy(Qt.NoContextMenu) # 隐藏主界面的菜单栏。 def set_dock_titlebar_visible(self, show: bool): diff --git a/tests/test_jupyter_notebook_support/__init__.py b/tests/test_jupyter_notebook_support/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_jupyter_notebook_support/run_jupyter_notebook_support.py b/tests/test_jupyter_notebook_support/run_jupyter_notebook_support.py new file mode 100644 index 00000000..50ec6643 --- /dev/null +++ b/tests/test_jupyter_notebook_support/run_jupyter_notebook_support.py @@ -0,0 +1,4 @@ +from app2 import main + +if __name__ == '__main__': + main(extensions=['embedded_browser', 'code_editor'], show_welcome=False) -- Gitee From 267a85210b475a63725b9ddace288baa51efe415 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 00:07:03 +0800 Subject: [PATCH 11/34] =?UTF-8?q?=E5=B0=86code=5Feditor=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E4=BB=8Esys.path=E9=87=8C=E9=9D=A2=E7=A7=BB=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/code_editor/codeeditor/tabwidget.py | 9 ++++----- packages/code_editor/main.py | 3 --- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/code_editor/codeeditor/tabwidget.py b/packages/code_editor/codeeditor/tabwidget.py index fa0bbcc7..e38fded1 100644 --- a/packages/code_editor/codeeditor/tabwidget.py +++ b/packages/code_editor/codeeditor/tabwidget.py @@ -54,10 +54,10 @@ if TYPE_CHECKING or in_unit_test(): # from packages.code_editor.codeeditor.ui.findinpath import FindInPathWidget else: # from codeeditor.baseeditor import PMBaseEditor - from codeeditor.pythoneditor import PMPythonEditor + from .pythoneditor import PMPythonEditor # from codeeditor.cppeditor import PMCPPEditor # from codeeditor.cythoneditor import PMCythonEditor - from codeeditor.markdowneditor import PMMarkdownEditor + from .markdowneditor import PMMarkdownEditor EDITOR_TYPE = Optional[Union['PMBaseEditor', 'PMCythonEditor', 'PMPythonEditor', 'PMCPPEditor', 'PMMarkdownEditor']] logger = logging.getLogger(__name__) @@ -840,7 +840,8 @@ class PMCodeEditTabWidget(QTabWidget, PMDockObject): self._current_executable = sys.executable else: self._current_executable = \ - self.extension_lib.Program.get_settings_item_from_file("config.ini", 'RUN/EXTERNAL_INTERPRETERS')[interpreter_index - 1]['path'] + self.extension_lib.Program.get_settings_item_from_file("config.ini", 'RUN/EXTERNAL_INTERPRETERS')[ + interpreter_index - 1]['path'] def on_tab_switched(self, index: int) -> None: for i in range(self.count()): @@ -955,8 +956,6 @@ class PMCodeEditTabWidget(QTabWidget, PMDockObject): if __name__ == '__main__': - - cgitb.enable(format='text') logging.basicConfig(level=logging.INFO) diff --git a/packages/code_editor/main.py b/packages/code_editor/main.py index d5e1fb5f..53889aaa 100644 --- a/packages/code_editor/main.py +++ b/packages/code_editor/main.py @@ -1,5 +1,4 @@ import os -import sys from typing import Dict, Union from PySide2.QtCore import QLocale, QTranslator @@ -11,8 +10,6 @@ app.trans_editor_tb = trans_editor_tb trans_editor_tb.load(os.path.join(os.path.dirname(__file__), 'translations', 'qt_%s.qm' % QLocale.system().name())) app.installTranslator(trans_editor_tb) -sys.path.append(os.path.dirname(__file__)) - from features.extensions.extensionlib import BaseInterface, BaseExtension from .codeeditor.tabwidget import PMCodeEditTabWidget from .debugger import PMDebugConsoleTabWidget -- Gitee From af05cc886d3ea9b6afa303171dfe8a0f39ba39de Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 00:11:18 +0800 Subject: [PATCH 12/34] =?UTF-8?q?=E5=B0=86dist=E6=96=87=E4=BB=B6=E6=95=B4?= =?UTF-8?q?=E7=90=86=E4=B8=BA=E5=87=BD=E6=95=B0=EF=BC=8C=E5=B9=B6=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=5F=5Fmain=5F=5F=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dist.py | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/dist.py b/dist.py index 58f030d7..14c67b35 100644 --- a/dist.py +++ b/dist.py @@ -4,25 +4,31 @@ import os import shutil -DIST_PATH = r"C:\Users\12957\Desktop\pyminer_dist\dist2" -CONDA_PATH = r"C:\Users\12957\Desktop\pyminer_dist\Miniconda3-latest-Windows-x86_64.exe" -CODE_FOLDER = os.path.join(DIST_PATH, "bin") -ADDR = "https://gitee.com/py2cn/pyminer.git" -BRANCH = "master" -PACKUP_COMPONENTS_FOLDER = r"C:\Users\12957\Desktop\pyminer_dist\PyMiner打包组件" -# os.system("start /wait "f" {CONDA_PATH} /InstallationType=JustMe /RegisterPython=0 /S /D={DIST_PATH}") -if not os.path.exists(CODE_FOLDER): - pass -else: - shutil.rmtree(CODE_FOLDER) -# os.mkdir(CODE_FOLDER) -os.system(f"git clone {ADDR} -b {BRANCH} {CODE_FOLDER}") -for d in os.listdir(PACKUP_COMPONENTS_FOLDER): - src = os.path.join(PACKUP_COMPONENTS_FOLDER, d) - dest = os.path.join(DIST_PATH, d) - shutil.copy(src, dest) +def make_pyminer_installer(): + DIST_PATH = r"C:\Users\12957\Desktop\pyminer_dist\dist2" + CONDA_PATH = r"C:\Users\12957\Desktop\pyminer_dist\Miniconda3-latest-Windows-x86_64.exe" + CODE_FOLDER = os.path.join(DIST_PATH, "bin") + ADDR = "https://gitee.com/py2cn/pyminer.git" + BRANCH = "master" + PACKUP_COMPONENTS_FOLDER = r"C:\Users\12957\Desktop\pyminer_dist\PyMiner打包组件" + # os.system("start /wait "f" {CONDA_PATH} /InstallationType=JustMe /RegisterPython=0 /S /D={DIST_PATH}") + if not os.path.exists(CODE_FOLDER): + pass + else: + shutil.rmtree(CODE_FOLDER) -PYTHON_PATH = os.path.join(DIST_PATH, "python.exe") -os.system(f"{PYTHON_PATH} -m pip install -r {os.path.join(CODE_FOLDER, 'requirements.txt')} -i " - f"https://mirrors.cloud.tencent.com/pypi/simple") + # os.mkdir(CODE_FOLDER) + os.system(f"git clone {ADDR} -b {BRANCH} {CODE_FOLDER}") + for d in os.listdir(PACKUP_COMPONENTS_FOLDER): + src = os.path.join(PACKUP_COMPONENTS_FOLDER, d) + dest = os.path.join(DIST_PATH, d) + shutil.copy(src, dest) + + PYTHON_PATH = os.path.join(DIST_PATH, "python.exe") + os.system(f"{PYTHON_PATH} -m pip install -r {os.path.join(CODE_FOLDER, 'requirements.txt')} -i " + f"https://mirrors.cloud.tencent.com/pypi/simple") + + +if __name__ == '__main__': + make_pyminer_installer() -- Gitee From 5ca7be38591945225c3cd0dfd5977814aef4c87e Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 00:33:26 +0800 Subject: [PATCH 13/34] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/code_editor/main.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/code_editor/main.py b/packages/code_editor/main.py index 53889aaa..07a8b44d 100644 --- a/packages/code_editor/main.py +++ b/packages/code_editor/main.py @@ -1,5 +1,6 @@ +import logging import os -from typing import Dict, Union +from typing import Dict, Union, TYPE_CHECKING from PySide2.QtCore import QLocale, QTranslator from PySide2.QtWidgets import QApplication @@ -16,15 +17,19 @@ from .debugger import PMDebugConsoleTabWidget from .toolbar import PMEditorToolbar from pmgwidgets import PMGPanel, load_json, dump_json +if TYPE_CHECKING: + from packages.file_tree.main import Interface as FileTreeInterface _PMEditorToolbar = PMEditorToolbar # 这一行的目的是防止导入被编辑器自动优化。 +logger = logging.getLogger(__name__) class Extension(BaseExtension): + editor_widget: 'PMCodeEditTabWidget' + def __init__(self): super(Extension, self).__init__() self.settings: Dict[str, Union[int, str]] = {} - self.editor_widget: 'PMCodeEditTabWidget' = None def on_loading(self): self.load_settings() @@ -32,7 +37,6 @@ class Extension(BaseExtension): def on_load(self): self.widgets["PMCodeEditTabWidget"].set_extension_lib(self.extension_lib) self.editor_widget: 'PMCodeEditTabWidget' = self.widgets["PMCodeEditTabWidget"] - self.interface.editor_tab_widget = self.editor_widget self.editor_widget.settings = self.settings self.debuggers_widget: 'PMDebugConsoleTabWidget' = self.widgets['PMDebugConsoleTabWidget'] @@ -74,17 +78,14 @@ class Extension(BaseExtension): self.editor_widget.set_color_scheme('light') else: self.editor_widget.set_color_scheme('dark') - print(work_dir) + + logger.debug(f'Working directory: {work_dir}') self.editor_widget.on_work_dir_changed(work_dir) def bind_event(self): - - self.extension_lib.get_interface('file_tree').add_open_file_callback('.py', self.new_script) - self.extension_lib.get_interface('file_tree').add_open_file_callback('.c', self.new_script) - self.extension_lib.get_interface('file_tree').add_open_file_callback('.cpp', self.new_script) - self.extension_lib.get_interface('file_tree').add_open_file_callback('.h', self.new_script) - self.extension_lib.get_interface('file_tree').add_open_file_callback('.pyx', self.new_script) - self.extension_lib.get_interface('file_tree').add_open_file_callback('.md', self.new_script) + extensions = ('.py', '.c', '.cpp', '.h', '.pyx', '.md') + file_tree: 'FileTreeInterface' = self.extension_lib.get_interface('file_tree') + [file_tree.add_open_file_callback(ext, self.new_script) for ext in extensions] def load_settings(self): settings = {'encoding_declaration_text': '# coding = utf-8', @@ -147,8 +148,7 @@ class Extension(BaseExtension): class Interface(BaseInterface): - def __init__(self): - self.editor_tab_widget: 'PMCodeEditTabWidget' = None + editor_tab_widget: 'PMCodeEditTabWidget' def open_script(self, path: str): self.editor_tab_widget.slot_new_script(path) -- Gitee From cb5306c9ebdbb8088244e56415ce380fbdceb41d Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 00:33:58 +0800 Subject: [PATCH 14/34] =?UTF-8?q?=E5=B0=86=E5=A4=9A=E4=B8=AA=E8=99=9A?= =?UTF-8?q?=E6=8B=9F=E7=8E=AF=E5=A2=83=E5=9D=87=E6=B7=BB=E5=8A=A0=E8=87=B3?= =?UTF-8?q?gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index cb4f4db5..036221f6 100644 --- a/.gitignore +++ b/.gitignore @@ -79,7 +79,7 @@ __pycache__/ .env .venv env/ -venv/ +venv*/ ENV/ env.bak/ venv.bak/ -- Gitee From f87f22050686004f401dfd66d2757b5d2f27d330 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 00:42:52 +0800 Subject: [PATCH 15/34] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- features/extensions/extensionlib/baseext.py | 10 ++++----- .../extensions/extensionlib/extension_lib.py | 11 ++++++---- packages/code_editor/main.py | 22 +++++++++---------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/features/extensions/extensionlib/baseext.py b/features/extensions/extensionlib/baseext.py index 0e3c1bbd..b27f4315 100644 --- a/features/extensions/extensionlib/baseext.py +++ b/features/extensions/extensionlib/baseext.py @@ -1,14 +1,14 @@ -from typing import Dict, TYPE_CHECKING import logging - -logger = logging.getLogger(__name__) +from typing import Dict, TYPE_CHECKING if TYPE_CHECKING: from PySide2.QtWidgets import QWidget from features.extensions.extensionlib import extension_lib +logger = logging.getLogger(__name__) + -class BaseExtension(): +class BaseExtension: widget_classes: Dict[str, 'QWidget'] = None widgets: Dict[str, 'QWidget'] = None extension_lib: 'extension_lib' = None @@ -56,6 +56,6 @@ class BaseExtension(): pass -class BaseInterface(): +class BaseInterface: def _set_extension(self, extension): self.extension = extension diff --git a/features/extensions/extensionlib/extension_lib.py b/features/extensions/extensionlib/extension_lib.py index be5cc052..cccaf173 100644 --- a/features/extensions/extensionlib/extension_lib.py +++ b/features/extensions/extensionlib/extension_lib.py @@ -28,7 +28,8 @@ def wrapper(): BaseInterface = baseext.BaseInterface BaseExtension = baseext.BaseExtension - def get_interface(self, name: str) -> BaseInterface: + @staticmethod + def get_interface(name: str) -> BaseInterface: """ 获取名为`name`的插件的公共接口(由interface定义) Args: @@ -39,7 +40,8 @@ def wrapper(): """ return extensions_manager.get_extension(name).public_interface - def insert_widget(self, widget, insert_mode, config=None): + @staticmethod + def insert_widget(widget, insert_mode, config=None): """ 在主界面上插入一个控件。 Args: @@ -53,7 +55,8 @@ def wrapper(): return extensions_manager.ui_inserters[insert_mode]( widget, config) - def get_main_program_dir(self): + @staticmethod + def get_main_program_dir(): """ 获取主程序的根目录 Returns: @@ -219,7 +222,7 @@ def wrapper(): """ return get_main_window().settings_changed_signal - class Program(): + class Program: @staticmethod def add_settings_panel(text: str, panel_content: List[Tuple[str, str]]): """ diff --git a/packages/code_editor/main.py b/packages/code_editor/main.py index 07a8b44d..de57425f 100644 --- a/packages/code_editor/main.py +++ b/packages/code_editor/main.py @@ -5,10 +5,13 @@ from typing import Dict, Union, TYPE_CHECKING from PySide2.QtCore import QLocale, QTranslator from PySide2.QtWidgets import QApplication +if TYPE_CHECKING: + from packages.file_tree.main import Interface as FileTreeInterface + app = QApplication.instance() trans_editor_tb = QTranslator() app.trans_editor_tb = trans_editor_tb -trans_editor_tb.load(os.path.join(os.path.dirname(__file__), 'translations', 'qt_%s.qm' % QLocale.system().name())) +trans_editor_tb.load(os.path.join(os.path.dirname(__file__), 'translations', f'qt_{QLocale.system().name()}.qm')) app.installTranslator(trans_editor_tb) from features.extensions.extensionlib import BaseInterface, BaseExtension @@ -17,14 +20,13 @@ from .debugger import PMDebugConsoleTabWidget from .toolbar import PMEditorToolbar from pmgwidgets import PMGPanel, load_json, dump_json -if TYPE_CHECKING: - from packages.file_tree.main import Interface as FileTreeInterface -_PMEditorToolbar = PMEditorToolbar # 这一行的目的是防止导入被编辑器自动优化。 -logger = logging.getLogger(__name__) +__prevent_from_ide_optimization = PMEditorToolbar # 这一行的目的是防止导入被编辑器自动优化。 +logger = logging.getLogger('code_editor') class Extension(BaseExtension): editor_widget: 'PMCodeEditTabWidget' + debuggers_widget: 'PMDebugConsoleTabWidget' def __init__(self): super(Extension, self).__init__() @@ -36,10 +38,10 @@ class Extension(BaseExtension): def on_load(self): self.widgets["PMCodeEditTabWidget"].set_extension_lib(self.extension_lib) - self.editor_widget: 'PMCodeEditTabWidget' = self.widgets["PMCodeEditTabWidget"] + self.editor_widget = self.widgets["PMCodeEditTabWidget"] self.interface.editor_tab_widget = self.editor_widget self.editor_widget.settings = self.settings - self.debuggers_widget: 'PMDebugConsoleTabWidget' = self.widgets['PMDebugConsoleTabWidget'] + self.debuggers_widget = self.widgets['PMDebugConsoleTabWidget'] self.debuggers_widget.signal_goto_file.connect(self.on_gotoline_requested) self.debuggers_widget.extension_lib = self.extension_lib self.editor_widget.set_debug_widget(self.debuggers_widget) @@ -78,7 +80,6 @@ class Extension(BaseExtension): self.editor_widget.set_color_scheme('light') else: self.editor_widget.set_color_scheme('dark') - logger.debug(f'Working directory: {work_dir}') self.editor_widget.on_work_dir_changed(work_dir) @@ -106,10 +107,7 @@ class Extension(BaseExtension): self.settings = settings def add_settings_panel(self): - """ - 向主界面的设置面板插入一个设置页面,并且按照设置数据来更新设置。 - :return: - """ + """向主界面的设置面板插入一个设置页面,并且按照设置数据来更新设置。""" settings = self.settings new_settings = [ -- Gitee From 97bf9e83882132d32dcc4f263dc988400d002a09 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 00:52:24 +0800 Subject: [PATCH 16/34] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../extensions_manager/ExtensionLoader.py | 18 +++++++--------- packages/socket_server/main.py | 8 ++----- packages/socket_server/server_by_socket.py | 21 ++++++++----------- 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/features/extensions/extensions_manager/ExtensionLoader.py b/features/extensions/extensions_manager/ExtensionLoader.py index 59b7fab5..d4ab4655 100644 --- a/features/extensions/extensions_manager/ExtensionLoader.py +++ b/features/extensions/extensions_manager/ExtensionLoader.py @@ -1,21 +1,17 @@ -from features.io.exceptions import pyminer_exc_mgr - -import os -import sys import importlib import json -from collections import namedtuple -import copy -import traceback import logging +import os +import sys +from collections import namedtuple import utils +from features.io.exceptions import pyminer_exc_mgr logger = logging.getLogger('extensionmanager.extensionloader') # from features.extensions.extensions_manager import log - Info = namedtuple('Info', ['icon', 'name', @@ -38,7 +34,7 @@ class ExtensionLoader: self.import_path = os.path.join(utils.get_root_dir(), 'packages') sys.path.append(self.import_path) # 将模块导入路径设置为扩展文件夹,这样可以直接导入入口文件 self.extension_lib_path = os.path.join( - utils.get_root_dir(),'pyminer2', 'extensions', 'extensionlib') + utils.get_root_dir(), 'pyminer2', 'extensions', 'extensionlib') sys.path.append(self.extension_lib_path) def load(self, file, ui_inserters): @@ -54,7 +50,7 @@ class ExtensionLoader: 'group', '未知类型/未知分组').split('/') self.path = os.path.join( - utils.get_root_dir(),'packages', + utils.get_root_dir(), 'packages', self.name) # 扩展文件夹路径 main_config = self.package.get( @@ -159,7 +155,7 @@ class ExtensionLoader: module_path = f'{package_name}.{module_name}' module = None module = importlib.import_module(module_path) - + except Exception as e: logger.error(e, exc_info=True) module = None diff --git a/packages/socket_server/main.py b/packages/socket_server/main.py index 1915fb61..b01fd296 100644 --- a/packages/socket_server/main.py +++ b/packages/socket_server/main.py @@ -20,9 +20,7 @@ class Extension(BaseExtension): class Interface(BaseInterface): extension_lib = None - - def __init__(self): - self.app: Flask = None + app: Flask def add_handler(self, rule, callback: Callable[[], str]): """ @@ -41,8 +39,6 @@ class Interface(BaseInterface): self.app.add_url_rule(rule, callback.__name__, callback) except AssertionError as e: if "overwriting an existing endpoint function" in repr(e): - desc = 'Problem happened when trying register function {func} with rule {rule}'.format( - func=callback, rule=rule) - logger.error(desc) + logger.error(f'Problem happened when trying register function {callback} with rule {rule}') raise e # self.extension_lib.Program.show_exception_occured_panel(e, solution='') diff --git a/packages/socket_server/server_by_socket.py b/packages/socket_server/server_by_socket.py index 9975e4f2..d4a99491 100644 --- a/packages/socket_server/server_by_socket.py +++ b/packages/socket_server/server_by_socket.py @@ -48,7 +48,9 @@ def get_settings(): :return: """ global message_queue - return "['Warning this method was deprecated']" + msg = "['Warning this method was deprecated']" + logger.warning(msg) + return msg @app.route('/get_stylesheet') @@ -64,11 +66,7 @@ def get_stylesheet(): @app.route('/set_data') def modify_data_descs(): - """ - 将工作空间中设置为data_desc型变量 - Returns: - - """ + """将工作空间中设置为data_desc型变量""" global message_queue try: datadesc_dict = b64_to_dict(request.args.get('msg')) @@ -85,11 +83,7 @@ def modify_data_descs(): @app.route('/interface_call') def run_command(): - """ - 运行命令,调用接口函数。 - Returns: - - """ + """运行命令,调用接口函数。""" global message_queue try: settings = request.args.get('msg') @@ -232,7 +226,10 @@ def run_server(port: int = None, ext_lib=None): extension_lib = ext_lib server = PMGServer() - server_thread = threading.Thread(target=app.run, kwargs={'port': port}) + def wrapper(): + app.run(port=port) + + server_thread = threading.Thread(target=wrapper) server_thread.setDaemon(True) server_thread.start() -- Gitee From d8f340cf93106a3c76de0c05797b0e98807ed139 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 00:57:53 +0800 Subject: [PATCH 17/34] =?UTF-8?q?=E8=A7=A3=E5=86=B3calc=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E7=9A=84=E4=BE=9D=E8=B5=96=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/pm_calc/package.json | 31 ++++++++++++++++--------------- pmgwidgets/elements/toolbar.py | 4 ++-- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/packages/pm_calc/package.json b/packages/pm_calc/package.json index e232b796..61e8bb78 100644 --- a/packages/pm_calc/package.json +++ b/packages/pm_calc/package.json @@ -1,26 +1,27 @@ { - "name":"pm_calc", - "display_name":"计算", - "version":"0.1.0", - "description":"内置计算的菜单", - "icon":"ipython_console.jpg", - "interface":{ - "file":"main.py", - "interface":"CalcInterface" + "name": "pm_calc", + "display_name": "计算", + "version": "0.1.0", + "description": "内置计算的菜单", + "icon": "ipython_console.jpg", + "interface": { + "file": "main.py", + "interface": "CalcInterface" }, - "widgets":[ + "widgets": [ { - "file":"main.py", - "widget":"PMCalcToolBar", - "position":"new_toolbar", - "config":{ + "file": "main.py", + "widget": "PMCalcToolBar", + "position": "new_toolbar", + "config": { "message": "no", "name": "pm_calc", "text": "数据" } } ], - "requirements":[ - "workspace_inspector" + "requirements": [ + "workspace_inspector", + "applications_toolbar" ] } \ No newline at end of file diff --git a/pmgwidgets/elements/toolbar.py b/pmgwidgets/elements/toolbar.py index 27f6863c..2f91a758 100644 --- a/pmgwidgets/elements/toolbar.py +++ b/pmgwidgets/elements/toolbar.py @@ -40,7 +40,7 @@ class TopToolBar(QToolBar): pbtn.setObjectName('pmtopToolbarButton') pbtn.setProperty('stat', 'unselected') - assert insert_after in self.button_names + assert insert_after in self.button_names, f'{insert_after} do not in buttons: {self.button_names}' index = self.button_names.index(insert_after) self.button_names.insert(index + 1, name) self.buttonbar_widget.layout().insertWidget(index + 1, pbtn) @@ -93,7 +93,7 @@ class PMGToolBar(QToolBar): tb.setToolTip(tooltip) tb.setProperty('qssp', 'tooliconbtn') if icon is not None: - pixmap = icon.pixmap(QSize(40,40)) + pixmap = icon.pixmap(QSize(40, 40)) icon = QIcon(pixmap) tb.setIcon(icon) -- Gitee From 9355f70af3e08a70f40e7cce90fda2e4b3285929 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 02:04:59 +0800 Subject: [PATCH 18/34] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/dataio/sample.py | 3 --- pyminer_comm/__init__.py | 7 ++++++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/dataio/sample.py b/packages/dataio/sample.py index 4f207de6..8af5aed2 100644 --- a/packages/dataio/sample.py +++ b/packages/dataio/sample.py @@ -18,9 +18,6 @@ from pyminer_comm import set_var, run_command # 导入matlab加载模块 # 定义日志输出格式 -logging.basicConfig(format="%(asctime)s %(name)s:%(levelname)s:%(message)s", datefmt="%Y-%m-%d %H:%M:%S", - level=logging.INFO) - logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) diff --git a/pyminer_comm/__init__.py b/pyminer_comm/__init__.py index 5b0fd311..4d0432be 100644 --- a/pyminer_comm/__init__.py +++ b/pyminer_comm/__init__.py @@ -3,7 +3,12 @@ # @Author: Zhanyi Hou # @Email: 1295752786@qq.com # @File: __init__.py.py +import logging -from pyminer_comm.pyminer_client import * from pyminer_comm.data_client import * +from pyminer_comm.pyminer_client import * +logging.basicConfig( + format="%(asctime)-15s %(name)-40s %(levelname)-8s %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + level=logging.INFO) -- Gitee From ce75230c88f14ddf4a5eb6ec3a72e8e9ad532b29 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 02:07:51 +0800 Subject: [PATCH 19/34] =?UTF-8?q?=E5=B0=86=E5=85=A8=E5=B1=80=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E9=85=8D=E7=BD=AE=E6=95=B4=E7=90=86=E5=88=B0pyminer?= =?UTF-8?q?=5Fcomm=E9=87=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qtpyeditor/codeedit/basecodeedit.py | 1 - packages/code_editor/codeeditor/tabwidget.py | 2 - packages/file_tree/file_tree.py | 9 ++-- packages/pm_calc/preprocess.py | 45 ++++++++----------- packages/pm_preprocess/preprocess.py | 7 --- pmgwidgets/widgets/basic/others/console.py | 6 +-- pyminer_comm/__init__.py | 3 +- 7 files changed, 28 insertions(+), 45 deletions(-) diff --git a/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py b/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py index 0cb28b2b..5cc36578 100644 --- a/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py +++ b/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py @@ -27,7 +27,6 @@ if TYPE_CHECKING: from jedi.api import Completion logger = logging.getLogger(__name__) -logging.basicConfig(level=logging.DEBUG) logger.setLevel(logging.DEBUG) diff --git a/packages/code_editor/codeeditor/tabwidget.py b/packages/code_editor/codeeditor/tabwidget.py index e38fded1..76fd4e3e 100644 --- a/packages/code_editor/codeeditor/tabwidget.py +++ b/packages/code_editor/codeeditor/tabwidget.py @@ -957,8 +957,6 @@ class PMCodeEditTabWidget(QTabWidget, PMDockObject): if __name__ == '__main__': cgitb.enable(format='text') - logging.basicConfig(level=logging.INFO) - app = QApplication(sys.argv) # app.setStyleSheet(""" # PMBaseEditor { diff --git a/packages/file_tree/file_tree.py b/packages/file_tree/file_tree.py index d9f7e6ed..9b37739d 100644 --- a/packages/file_tree/file_tree.py +++ b/packages/file_tree/file_tree.py @@ -1,10 +1,12 @@ import os import platform from typing import Dict, Callable, List -from PySide2.QtCore import Qt, QModelIndex, QMimeData, QUrl -from PySide2.QtGui import QPixmap, QIcon, QCloseEvent, QKeyEvent + +from PySide2.QtCore import Qt, QModelIndex +from PySide2.QtGui import QPixmap, QIcon, QCloseEvent from PySide2.QtWidgets import QVBoxLayout, QWidget, QFileDialog, QPushButton, QHBoxLayout, QLineEdit, QToolButton, \ QApplication, QMessageBox + from pmgwidgets import PMGFilesTreeview, PMDockObject, in_unit_test, UndoManager @@ -259,11 +261,8 @@ class PMFilesTree(QWidget, PMDockObject): if __name__ == '__main__': import sys import cgitb - import logging cgitb.enable(format='text') - logging.basicConfig(level=logging.INFO) - app = QApplication(sys.argv) w = PMFilesTree() diff --git a/packages/pm_calc/preprocess.py b/packages/pm_calc/preprocess.py index abdb9e44..5a39a1eb 100644 --- a/packages/pm_calc/preprocess.py +++ b/packages/pm_calc/preprocess.py @@ -1,40 +1,36 @@ -import os import sys -import logging import datetime +import logging +import sys import webbrowser + import numpy as np import pandas as pd -from pandas.api.types import is_numeric_dtype +# # 导入Qt模块 +from PySide2.QtCore import Qt, Signal +from PySide2.QtWidgets import QWidget, QMessageBox, \ + QFileDialog, QDesktopWidget, QDialog, QTableWidgetItem, QInputDialog, QAbstractItemView, QLineEdit, \ + QApplication from pandas.api.types import is_float_dtype +from pandas.api.types import is_numeric_dtype from pandas.api.types import is_string_dtype -# # 导入Qt模块 -from PySide2.QtCore import QSize, Qt, Signal -from PySide2.QtGui import QPixmap -from PySide2.QtWidgets import QHBoxLayout, QWidget, QSpacerItem, QToolButton, QSizePolicy, QWizard, QMessageBox, \ - QFileDialog, QFrame, QDesktopWidget, QDialog, QTableWidgetItem, QInputDialog, QAbstractItemView, QLineEdit, \ - QApplication -# 导入数据相关操作模块 -from packages.pm_preprocess.ui.data_role import Ui_Form as DataRole_Ui_Form # 数据角色 -from packages.pm_preprocess.ui.data_info import Ui_Form as DataInfo_Ui_Form # 数据信息 from packages.pm_preprocess.ui.data_column_desc import Ui_Form as Columns_desc_Ui_Form # 数据列描述 -from packages.pm_preprocess.ui.data_delete_row import Ui_Form as DataDeleteRow_Ui_Form # 数据删除行 +from packages.pm_preprocess.ui.data_column_encode import Ui_Form as DataColumnEncode_Ui_Form +from packages.pm_preprocess.ui.data_column_name import Ui_Form as DataColumnName_Ui_Form from packages.pm_preprocess.ui.data_delete_column import Ui_Form as DataDeleteColumn_Ui_Form -from packages.pm_preprocess.ui.data_merge_vertical import Ui_Form as DataMergeVertical_Ui_Form +from packages.pm_preprocess.ui.data_delete_row import Ui_Form as DataDeleteRow_Ui_Form # 数据删除行 +from packages.pm_preprocess.ui.data_info import Ui_Form as DataInfo_Ui_Form # 数据信息 from packages.pm_preprocess.ui.data_merge_horizontal import Ui_Form as DataMergeHorizontal_Ui_Form -from packages.pm_preprocess.ui.data_partition import Ui_Form as DataPartition_Ui_Form +from packages.pm_preprocess.ui.data_merge_vertical import Ui_Form as DataMergeVertical_Ui_Form from packages.pm_preprocess.ui.data_new_column import Ui_Form as DataNewColumn_Ui_Form -from packages.pm_preprocess.ui.data_sort import Ui_Form as DataSort_Ui_Form -from packages.pm_preprocess.ui.data_transpose import Ui_Form as DataTranspose_Ui_Form +from packages.pm_preprocess.ui.data_partition import Ui_Form as DataPartition_Ui_Form +# 导入数据相关操作模块 +from packages.pm_preprocess.ui.data_role import Ui_Form as DataRole_Ui_Form # 数据角色 from packages.pm_preprocess.ui.data_sample import Ui_Form as DataSample_Ui_Form +from packages.pm_preprocess.ui.data_sort import Ui_Form as DataSort_Ui_Form from packages.pm_preprocess.ui.data_standard import Ui_Form as DataStandard_Ui_Form -from packages.pm_preprocess.ui.data_column_encode import Ui_Form as DataColumnEncode_Ui_Form -from packages.pm_preprocess.ui.data_column_name import Ui_Form as DataColumnName_Ui_Form - -# 定义日志输出格式 -logging.basicConfig(format="%(asctime)s %(name)s:%(levelname)s:%(message)s", datefmt="%Y-%m-%d %H:%M:%S", - level=logging.INFO) +from packages.pm_preprocess.ui.data_transpose import Ui_Form as DataTranspose_Ui_Form class DataInfoForm(QDialog, DataInfo_Ui_Form): @@ -1087,9 +1083,6 @@ class DataNewColumnForm(QWidget, DataNewColumn_Ui_Form): self.move(int((screen.width() - size.width()) / 2), int((screen.height() - size.height()) / 2)) - - - class DataSortForm(QWidget, DataSort_Ui_Form): """ 打开"从sas导入"窗口 diff --git a/packages/pm_preprocess/preprocess.py b/packages/pm_preprocess/preprocess.py index abdb9e44..ef1a21ae 100644 --- a/packages/pm_preprocess/preprocess.py +++ b/packages/pm_preprocess/preprocess.py @@ -32,10 +32,6 @@ from packages.pm_preprocess.ui.data_standard import Ui_Form as DataStandard_Ui_F from packages.pm_preprocess.ui.data_column_encode import Ui_Form as DataColumnEncode_Ui_Form from packages.pm_preprocess.ui.data_column_name import Ui_Form as DataColumnName_Ui_Form -# 定义日志输出格式 -logging.basicConfig(format="%(asctime)s %(name)s:%(levelname)s:%(message)s", datefmt="%Y-%m-%d %H:%M:%S", - level=logging.INFO) - class DataInfoForm(QDialog, DataInfo_Ui_Form): """ @@ -1087,9 +1083,6 @@ class DataNewColumnForm(QWidget, DataNewColumn_Ui_Form): self.move(int((screen.width() - size.width()) / 2), int((screen.height() - size.height()) / 2)) - - - class DataSortForm(QWidget, DataSort_Ui_Form): """ 打开"从sas导入"窗口 diff --git a/pmgwidgets/widgets/basic/others/console.py b/pmgwidgets/widgets/basic/others/console.py index 591f5e90..9d13ea35 100644 --- a/pmgwidgets/widgets/basic/others/console.py +++ b/pmgwidgets/widgets/basic/others/console.py @@ -8,10 +8,9 @@ Created on 2020/8/24 @file: console.py @description: Console Widget """ +import json import logging import os -import sys -import json from typing import Tuple, Dict, Callable from PySide2.QtCore import QObject, Signal, QThread, QWaitCondition, QMutex, QPoint, QCoreApplication, QTranslator, \ @@ -22,6 +21,7 @@ from qtconsole import styles from qtconsole.manager import QtKernelManager from qtconsole.rich_jupyter_widget import RichJupyterWidget from qtconsole.styles import default_light_syntax_style, default_light_style_sheet + from features.io import settings default_dark_style_template = styles.default_template + """\ @@ -32,7 +32,6 @@ default_dark_style_sheet = default_dark_style_template % dict( bgcolor='#19232d', fgcolor='white', select="#ccc") default_dark_syntax_style = 'monokai' # 'default' -logging.basicConfig(stream=sys.stderr) logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) @@ -359,6 +358,7 @@ class PMGIpythonConsole(RichJupyterWidget): with open(self.history_path, 'w') as f: json.dump(history, f) + if __name__ == '__main__': import sys import cgitb diff --git a/pyminer_comm/__init__.py b/pyminer_comm/__init__.py index 4d0432be..a611c6a4 100644 --- a/pyminer_comm/__init__.py +++ b/pyminer_comm/__init__.py @@ -11,4 +11,5 @@ from pyminer_comm.pyminer_client import * logging.basicConfig( format="%(asctime)-15s %(name)-40s %(levelname)-8s %(message)s", datefmt="%Y-%m-%d %H:%M:%S", - level=logging.INFO) + level=logging.INFO, +) -- Gitee From 057f31b55b4d526182c5848d169d96ddc1e800e0 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 02:13:42 +0800 Subject: [PATCH 20/34] =?UTF-8?q?=E5=B0=86=E5=85=A8=E5=B1=80=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E9=85=8D=E7=BD=AE=E6=95=B4=E7=90=86=E5=88=B0pyminer?= =?UTF-8?q?=5Fcomm=E9=87=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jupyter_notebook_support/scripts/pyminer_ipython_node.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/jupyter_notebook_support/scripts/pyminer_ipython_node.py b/packages/jupyter_notebook_support/scripts/pyminer_ipython_node.py index a1e03fab..1f20d9dc 100644 --- a/packages/jupyter_notebook_support/scripts/pyminer_ipython_node.py +++ b/packages/jupyter_notebook_support/scripts/pyminer_ipython_node.py @@ -14,10 +14,6 @@ import sys, os import typing from IPython.core.magic import register_line_magic, register_cell_magic, register_line_cell_magic -# logging.basicConfig(format="%(asctime)s %(name)s:%(levelname)s:%(message)s", -# datefmt="%Y-%m-%d %H:%M:%S", -# level=logging.INFO, -# filename=r"c:\users\12957\Desktop\123.txt") __logger = logging.getLogger() __logger.info("Env variable-- IPYTHON_AS_PYMINER_NODE: %s" % os.environ.get('IPYTHON_AS_PYMINER_NODE')) if (os.environ.get('IPYTHON_AS_PYMINER_NODE') is not None) and (int(os.environ.get('IPYTHON_AS_PYMINER_NODE')) >= 1): -- Gitee From a7c6586cadd68b02c5cf474cd93fed7fb24551d1 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 02:14:17 +0800 Subject: [PATCH 21/34] =?UTF-8?q?=E4=B8=8D=E6=98=BE=E7=A4=BAflask=E7=9A=84?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/socket_server/main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/socket_server/main.py b/packages/socket_server/main.py index b01fd296..bad80c71 100644 --- a/packages/socket_server/main.py +++ b/packages/socket_server/main.py @@ -2,11 +2,14 @@ import inspect import logging from typing import Callable +import flask.cli from flask import Flask from features.extensions.extensionlib import BaseExtension, BaseInterface from .server_by_socket import run, app +# 不显示flask的启动日志 +flask.cli.show_server_banner = lambda *_, **__: None logger = logging.getLogger(__name__) -- Gitee From 1aabd2f2488d0c4fc5029fca2b13708074ef673a Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 02:15:53 +0800 Subject: [PATCH 22/34] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/algorithms/calculation/digits.py | 1 - 1 file changed, 1 deletion(-) diff --git a/core/algorithms/calculation/digits.py b/core/algorithms/calculation/digits.py index fb0273fb..b459e334 100644 --- a/core/algorithms/calculation/digits.py +++ b/core/algorithms/calculation/digits.py @@ -59,5 +59,4 @@ def ConvertToFloat(floatingPoint): mantissa = floatingPointString[floatingPointString.find('1') + 1:] # 获得尾数 mantissa = mantissa[:23] + '0' * (23 - len(mantissa)) floatingPointString = '0b' + sign + exponet + mantissa - print(floatingPointString) return hex(int(floatingPointString, 2)) -- Gitee From 0d517643a3b3ed78ad21269acc8154e185f150ea Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 02:22:53 +0800 Subject: [PATCH 23/34] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pmlocalserver/server.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pmlocalserver/server.py b/pmlocalserver/server.py index 745325d7..876e0f65 100644 --- a/pmlocalserver/server.py +++ b/pmlocalserver/server.py @@ -1,11 +1,9 @@ import threading +from multiprocessing import shared_memory from flask import Flask from flask_cors import CORS -import threading -from multiprocessing import shared_memory - server = Flask(__name__, static_folder='static', static_url_path='/static') CORS(server, supports_credentials=True) # 解决跨域 -- Gitee From 6dcb2c6d052aa1292da10b11484937e0de61ac5c Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 02:27:15 +0800 Subject: [PATCH 24/34] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app2.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app2.py b/app2.py index 86636766..bb3d1258 100644 --- a/app2.py +++ b/app2.py @@ -237,11 +237,7 @@ class MainWindow(BaseMainWindow): self.window_geometry_changed_signal.emit() def start_pmlocalserver(self): - """ - 启动本地flask服务器pmlocalserver - Returns:None - - """ + """启动本地flask服务器pmlocalserver""" server.server_thread.start() def clear_workspace(self): -- Gitee From 6aa243ee2963d18d1393ea2e759e8f9f2561deca Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 02:35:36 +0800 Subject: [PATCH 25/34] =?UTF-8?q?=E5=B0=86ExtensionLib=E4=BB=8Ewrapper?= =?UTF-8?q?=E9=87=8C=E9=9D=A2=E7=A7=BB=E5=87=BA=E4=BB=A5=E8=8E=B7=E5=BE=97?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E8=A1=A5=E5=85=A8=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- features/extensions/extensionlib/baseext.py | 4 +- .../extensions/extensionlib/extension_lib.py | 868 +++++++++--------- packages/code_editor/main.py | 1 - 3 files changed, 432 insertions(+), 441 deletions(-) diff --git a/features/extensions/extensionlib/baseext.py b/features/extensions/extensionlib/baseext.py index b27f4315..8b3f3598 100644 --- a/features/extensions/extensionlib/baseext.py +++ b/features/extensions/extensionlib/baseext.py @@ -3,7 +3,7 @@ from typing import Dict, TYPE_CHECKING if TYPE_CHECKING: from PySide2.QtWidgets import QWidget - from features.extensions.extensionlib import extension_lib + from features.extensions.extensionlib.extension_lib import ExtensionLib logger = logging.getLogger(__name__) @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) class BaseExtension: widget_classes: Dict[str, 'QWidget'] = None widgets: Dict[str, 'QWidget'] = None - extension_lib: 'extension_lib' = None + extension_lib: 'ExtensionLib' = None public_interface: 'BaseInterface' = None settings: Dict[str, object] = None interface: 'BaseInterface' diff --git a/features/extensions/extensionlib/extension_lib.py b/features/extensions/extensionlib/extension_lib.py index cccaf173..15663e75 100644 --- a/features/extensions/extensionlib/extension_lib.py +++ b/features/extensions/extensionlib/extension_lib.py @@ -6,556 +6,548 @@ from PySide2.QtCore import QRect, Signal from PySide2.QtWidgets import QWidget, QDialog import utils +from features.extensions.extensionlib import baseext +from features.extensions.extensions_manager.manager import extensions_manager +from features.io.exceptions import PMExceptions +from features.ui import pmwidgets from features.workspace.data_adapter import UniversalAdapter +from features.workspace.data_manager import data_manager +from features.workspace_old.datamanager.datamanager import data_manager as data_manager_old +from pyminer_comm.base import DataDesc +from utils import get_main_window if TYPE_CHECKING: from pmgwidgets import PMGToolBar -def wrapper(): - from features.extensions.extensions_manager.manager import extensions_manager - from features.workspace.data_manager import data_manager +class ExtensionLib: + pm_widgets = pmwidgets + BaseInterface = baseext.BaseInterface + BaseExtension = baseext.BaseExtension - from features.workspace_old.datamanager.datamanager import data_manager as data_manager_old - from utils import get_main_window - from features.ui import pmwidgets - from features.extensions.extensionlib import baseext - from features.io.exceptions import PMExceptions - from pyminer_comm.base import DataDesc + @staticmethod + def get_interface(name: str) -> BaseInterface: + """获取名为 ``name`` 的插件的公共接口(由interface定义) - class ExtensionLib: - pm_widgets = pmwidgets - BaseInterface = baseext.BaseInterface - BaseExtension = baseext.BaseExtension + Args: + name: 插件名称 + """ + return extensions_manager.get_extension(name).public_interface + + @staticmethod + def insert_widget(widget, insert_mode, config=None): + """ + 在主界面上插入一个控件。 + Args: + widget: + insert_mode: + config: + + Returns: + + """ + return extensions_manager.ui_inserters[insert_mode]( + widget, config) + + @staticmethod + def get_main_program_dir(): + """ + 获取主程序的根目录 + Returns: + + """ + return utils.get_root_dir() + + class UI: + @staticmethod + def widget_exists(widget_name: str) -> bool: + if widget_name in get_main_window().dock_widgets.keys(): + return True + else: + return False @staticmethod - def get_interface(name: str) -> BaseInterface: + def get_toolbar(toolbar_name: str) -> 'PMGToolBar': """ - 获取名为`name`的插件的公共接口(由interface定义) + 获取工具栏 + Args: - name: + toolbar_name:工具栏名称 Returns: """ - return extensions_manager.get_extension(name).public_interface + tb = get_main_window().toolbars.get(toolbar_name) + + return tb @staticmethod - def insert_widget(widget, insert_mode, config=None): + def get_toolbar_widget(toolbar_name: str, widget_name: str) -> Optional['QWidget']: """ - 在主界面上插入一个控件。 + 获取工具栏上的控件(按钮等) + Args: - widget: - insert_mode: - config: + toolbar_name:工具栏名称 + widget_name:工具栏上的控件名称 Returns: """ - return extensions_manager.ui_inserters[insert_mode]( - widget, config) + toolbar = ExtensionLib.UI.get_toolbar(toolbar_name) + if toolbar is not None: + widget = toolbar.get_control_widget(widget_name) + return widget + return None @staticmethod - def get_main_program_dir(): + def get_main_window_geometry() -> 'QRect': """ - 获取主程序的根目录 + 获取主界面的尺寸 + Returns: """ - return utils.get_root_dir() + return get_main_window().geometry() - class UI: - @staticmethod - def widget_exists(widget_name: str) -> bool: - if widget_name in get_main_window().dock_widgets.keys(): - return True - else: - return False + @staticmethod + def raise_dock_into_view(dock_widget_name: str) -> None: + """ + 将界面上的控件提升到可视的位置 - @staticmethod - def get_toolbar(toolbar_name: str) -> 'PMGToolBar': - """ - 获取工具栏 + Args: + dock_widget_name: - Args: - toolbar_name:工具栏名称 + Returns: - Returns: + """ + return get_main_window().raise_dock_into_view(dock_widget_name) - """ - tb = get_main_window().toolbars.get(toolbar_name) + @staticmethod + def get_default_font() -> str: + """ + 获取默认字体文件 - return tb + Returns: Filepath of font. - @staticmethod - def get_toolbar_widget(toolbar_name: str, widget_name: str) -> Optional['QWidget']: - """ - 获取工具栏上的控件(按钮等) + """ + app = get_main_window() + return os.path.join(app.font_dir, app.default_font) - Args: - toolbar_name:工具栏名称 - widget_name:工具栏上的控件名称 + @staticmethod + def switch_toolbar(toolbar_name: str, switch_only: bool = True): + """ + 切换工具栏 - Returns: + Args: + toolbar_name: + switch_only: - """ - toolbar = ExtensionLib.UI.get_toolbar(toolbar_name) - if toolbar is not None: - widget = toolbar.get_control_widget(widget_name) - return widget - return None + Returns: - @staticmethod - def get_main_window_geometry() -> 'QRect': - """ - 获取主界面的尺寸 + """ + app = get_main_window() + app.switch_toolbar(toolbar_name, switch_only) - Returns: + @staticmethod + def exec_dialog(dlg: QDialog): + assert isinstance(dlg, QDialog) + win = get_main_window() + dlg.setParent(win) + dlg.exec_() - """ - return get_main_window().geometry() + class Signal: + @staticmethod + def get_close_signal() -> Signal: + """ + 获取关闭信号 - @staticmethod - def raise_dock_into_view(dock_widget_name: str) -> None: - """ - 将界面上的控件提升到可视的位置 + Returns: - Args: - dock_widget_name: + """ + return get_main_window().close_signal - Returns: + @staticmethod + def get_window_geometry_changed_signal(): + """ + 获取窗口位置和尺寸变化的事件 - """ - return get_main_window().raise_dock_into_view(dock_widget_name) + Returns: - @staticmethod - def get_default_font() -> str: - """ - 获取默认字体文件 + """ + return get_main_window().window_geometry_changed_signal - Returns: Filepath of font. + @staticmethod + def get_layouts_ready_signal(): + """ + 获取布局加载完毕的事件 - """ - app = get_main_window() - return os.path.join(app.font_dir, app.default_font) + Returns: - @staticmethod - def switch_toolbar(toolbar_name: str, switch_only: bool = True): - """ - 切换工具栏 + """ + return get_main_window().layouts_ready_signal - Args: - toolbar_name: - switch_only: + @staticmethod + def get_widgets_ready_signal(): + """ + 获取控件加载完毕的事件 - Returns: + Returns: - """ - app = get_main_window() - app.switch_toolbar(toolbar_name, switch_only) + """ + return get_main_window().widgets_ready_signal - @staticmethod - def exec_dialog(dlg: QDialog): - assert isinstance(dlg, QDialog) - win = get_main_window() - dlg.setParent(win) - dlg.exec_() + @staticmethod + def get_events_ready_signal(): + """ + 获取界面信号和事件绑定完毕的事件。 - class Signal: - @staticmethod - def get_close_signal() -> Signal: - """ - 获取关闭信号 + Returns: - Returns: + """ + return get_main_window().events_ready_signal - """ - return get_main_window().close_signal + @staticmethod + def get_settings_changed_signal() -> 'Signal': + """ + 获取设置发生变化时的事件。 - @staticmethod - def get_window_geometry_changed_signal(): - """ - 获取窗口位置和尺寸变化的事件 + Returns: - Returns: + """ + return get_main_window().settings_changed_signal - """ - return get_main_window().window_geometry_changed_signal + class Program: + @staticmethod + def add_settings_panel(text: str, panel_content: List[Tuple[str, str]]): + """ + 添加设置面板 - @staticmethod - def get_layouts_ready_signal(): - """ - 获取布局加载完毕的事件 + Args: + text: + panel_content: - Returns: + Returns: - """ - return get_main_window().layouts_ready_signal + """ - @staticmethod - def get_widgets_ready_signal(): - """ - 获取控件加载完毕的事件 + return get_main_window().main_option_form.add_settings_panel(text, panel_content) - Returns: + @staticmethod + def show_log(level: str, module: str, content: str) -> None: + """ + 调用——PluginInterface.show_log('info','CodeEditor','新建文件') + 输出——2020-08-29 23:43:10 hzy INFO [CodeEditor]:新建文件 + Args: + level: 类型,比如‘info’ + module: 模块。比如'Jupyter' + content: 内容。自定义的字符串 - """ - return get_main_window().widgets_ready_signal + Returns: + """ + get_main_window().slot_flush_console(level, module, content) - @staticmethod - def get_events_ready_signal(): - """ - 获取界面信号和事件绑定完毕的事件。 + @staticmethod + def get_main_program_dir(): + """ + 获取主程序路径 - Returns: + Returns: - """ - return get_main_window().events_ready_signal + """ + return utils.get_root_dir() - @staticmethod - def get_settings_changed_signal() -> 'Signal': - """ - 获取设置发生变化时的事件。 + @staticmethod + def get_settings_item_from_file(file: str, item: str, mode: str = "user"): + """ + 从设置文件中获取设置项 + Args: + file: + item: + mode: - Returns: + Returns: - """ - return get_main_window().settings_changed_signal + """ + return utils.get_settings_item_from_file(file, item, mode) - class Program: - @staticmethod - def add_settings_panel(text: str, panel_content: List[Tuple[str, str]]): - """ - 添加设置面板 + @staticmethod + def write_settings_item_to_file(file: str, item: str, value: Any): + """ + 将配置项写入设置文件中 + Args: + file: + item: + value: - Args: - text: - panel_content: + Returns: - Returns: + """ + utils.write_settings_item_to_file(file, item, value) + get_main_window().settings_changed_signal.emit() - """ + @staticmethod + def set_work_dir(work_dir: str) -> None: + """ + 设置当前工作路径 - return get_main_window().main_option_form.add_settings_panel(text, panel_content) + Args: + work_dir: - @staticmethod - def show_log(level: str, module: str, content: str) -> None: - """ - 调用——PluginInterface.show_log('info','CodeEditor','新建文件') - 输出——2020-08-29 23:43:10 hzy INFO [CodeEditor]:新建文件 - Args: - level: 类型,比如‘info’ - module: 模块。比如'Jupyter' - content: 内容。自定义的字符串 + Returns: - Returns: - """ - get_main_window().slot_flush_console(level, module, content) + """ + utils.write_settings_item_to_file("config.ini", "MAIN/PATH_WORKDIR", work_dir) + get_main_window().settings_changed_signal.emit() - @staticmethod - def get_main_program_dir(): - """ - 获取主程序路径 + @staticmethod + def get_work_dir() -> str: + """ + 获取当前工作路径 - Returns: + Returns: - """ - return utils.get_root_dir() + """ - @staticmethod - def get_settings_item_from_file(file: str, item: str, mode: str = "user"): - """ - 从设置文件中获取设置项 - Args: - file: - item: - mode: + dir = utils.get_settings_item_from_file("config.ini", "MAIN/PATH_WORKDIR") + if (not isinstance(dir, str)) or (not os.path.exists(dir)): + dir = os.path.join(os.path.expanduser("~"), "Desktop") + utils.write_settings_item_to_file("config.ini", "MAIN/PATH_WORKDIR", dir) + return dir - Returns: - - """ - return utils.get_settings_item_from_file(file, item, mode) + @staticmethod + def get_theme() -> str: + """ + 获取主题 + Returns: - @staticmethod - def write_settings_item_to_file(file: str, item: str, value: Any): - """ - 将配置项写入设置文件中 - Args: - file: - item: - value: - - Returns: - - """ - utils.write_settings_item_to_file(file, item, value) - get_main_window().settings_changed_signal.emit() - - @staticmethod - def set_work_dir(work_dir: str) -> None: - """ - 设置当前工作路径 - - Args: - work_dir: - - Returns: - - """ - utils.write_settings_item_to_file("config.ini", "MAIN/PATH_WORKDIR", work_dir) - get_main_window().settings_changed_signal.emit() - - @staticmethod - def get_work_dir() -> str: - """ - 获取当前工作路径 - - Returns: - - """ - - dir = utils.get_settings_item_from_file("config.ini", "MAIN/PATH_WORKDIR") - if (not isinstance(dir, str)) or (not os.path.exists(dir)): - dir = os.path.join(os.path.expanduser("~"), "Desktop") - utils.write_settings_item_to_file("config.ini", "MAIN/PATH_WORKDIR", dir) - return dir - - @staticmethod - def get_theme() -> str: - """ - 获取主题 - Returns: - - """ - return utils.get_settings_item_from_file("config.ini", "MAIN/THEME") - - @staticmethod - def run_python_file(file_path: str, interpreter_path: str): - """ - 运行Python文件命令 - TODO: Write a shell console into pyminer. - - Args: - file_path: - - Returns: - - """ - raise DeprecationWarning - - @staticmethod - def get_plugin_data_path(plugins_name: str) -> str: - """ - 获取插件的数据文件路径 - Args: - plugins_name: - - Returns:str,文件夹路径。 - - """ - ext = extensions_manager.get_extension(plugins_name) - # assert ext is not None, 'Extension named %s isn\'t exist!' % plugins_name - path = os.path.join(os.path.expanduser('~'), '.pyminer', 'packages') - if not os.path.exists(path): - os.mkdir(path) - plugin_data_path = os.path.join(path, plugins_name) - if not os.path.exists(plugin_data_path): - os.mkdir(plugin_data_path) - return plugin_data_path - - @staticmethod - def show_exception_occured_panel(error: BaseException, solution: str, solution_command: str = ''): - """ - - :param error: - :param solution: - :param solution_command: - :return: - """ - PMExceptions.get_instance().emit_exception_occured_signal(error, solution, solution_command) - - class Data: - @staticmethod - def get_adapter(key: str) -> UniversalAdapter: - return data_manager[key] - - @staticmethod - def clear(): - data_manager_old.clear() - - @staticmethod - def delete_variable(var_name: str, provider: str = 'unknown'): - """ - 删除变量 - Args: - var_name: - provider: - - Returns: - - """ - data_manager_old.delete_data(var_name, provider) - - @staticmethod - def get_all_variable_names() -> List[str]: - """ - 获取所有的变量名 - - Returns: - - """ - return list(data_manager.container.keys()) - - @staticmethod - def get_all_public_variable_names() -> List[str]: - """ - 获取所有非保留的变量的名称 - - Returns: - - """ - return list(data_manager_old.get_all_public_var().keys()) - - @staticmethod - def get_all_variables() -> Dict[str, object]: - """ - 获取全部变量(包含保留类型,可能返回结果比较乱,需要审慎使用) - - Returns: - """ - return data_manager_old.get_all_var() - - @staticmethod - def get_all_public_variables() -> Dict[str, object]: - """ - 获取所有的外部可访问变量。 - - Returns: - """ - return data_manager_old.get_all_public_var() - - @staticmethod - def add_data_changed_callback(callback: Callable[[str, Any, str], None]) -> None: - """ - 添加数据改变时触发的回调函数 - - Args: - callback: - - Returns:None - """ - assert callable(callback) - assert len( - list(inspect.signature(callback).parameters.keys())) == 3, 'Function args should be 3' - data_manager_old.on_modification(callback) - - @staticmethod - def remove_data_changed_callback(callback: Callable): - if callback in data_manager_old.modification_callback_actions: - data_manager_old.modification_callback_actions.remove(callback) - print('removed callback!') - - @staticmethod - def add_data_deleted_callback(deletion_callback: Callable[[str, str], None]): - """ - 绑定的函数,要求其输入的函数参数为两个。 + """ + return utils.get_settings_item_from_file("config.ini", "MAIN/THEME") - Args: - deletion_callback: + @staticmethod + def run_python_file(file_path: str, interpreter_path: str): + """ + 运行Python文件命令 + TODO: Write a shell console into pyminer. - Returns: + Args: + file_path: - """ - assert callable(deletion_callback) - assert len( - list(inspect.signature(deletion_callback).parameters.keys())) == 2, 'Function args should be 2' - data_manager_old.on_deletion(deletion_callback) + Returns: - @staticmethod - def var_exists(var_name: str): - """ - 判断var_name对应的变量是否存在 - Args: - var_name: + """ + raise DeprecationWarning - Returns: + @staticmethod + def get_plugin_data_path(plugins_name: str) -> str: + """ + 获取插件的数据文件路径 + Args: + plugins_name: + + Returns:str,文件夹路径。 + + """ + ext = extensions_manager.get_extension(plugins_name) + # assert ext is not None, 'Extension named %s isn\'t exist!' % plugins_name + path = os.path.join(os.path.expanduser('~'), '.pyminer', 'packages') + if not os.path.exists(path): + os.mkdir(path) + plugin_data_path = os.path.join(path, plugins_name) + if not os.path.exists(plugin_data_path): + os.mkdir(plugin_data_path) + return plugin_data_path + + @staticmethod + def show_exception_occured_panel(error: BaseException, solution: str, solution_command: str = ''): + """ + + :param error: + :param solution: + :param solution_command: + :return: + """ + PMExceptions.get_instance().emit_exception_occured_signal(error, solution, solution_command) + + class Data: + @staticmethod + def get_adapter(key: str) -> UniversalAdapter: + return data_manager[key] + + @staticmethod + def clear(): + data_manager_old.clear() + + @staticmethod + def delete_variable(var_name: str, provider: str = 'unknown'): + """ + 删除变量 + Args: + var_name: + provider: + + Returns: + + """ + data_manager_old.delete_data(var_name, provider) + + @staticmethod + def get_all_variable_names() -> List[str]: + """ + 获取所有的变量名 + + Returns: + + """ + return list(data_manager.container.keys()) + + @staticmethod + def get_all_public_variable_names() -> List[str]: + """ + 获取所有非保留的变量的名称 + + Returns: + + """ + return list(data_manager_old.get_all_public_var().keys()) + + @staticmethod + def get_all_variables() -> Dict[str, object]: + """ + 获取全部变量(包含保留类型,可能返回结果比较乱,需要审慎使用) + + Returns: + """ + return data_manager_old.get_all_var() + + @staticmethod + def get_all_public_variables() -> Dict[str, object]: + """ + 获取所有的外部可访问变量。 + + Returns: + """ + return data_manager_old.get_all_public_var() + + @staticmethod + def add_data_changed_callback(callback: Callable[[str, Any, str], None]) -> None: + """ + 添加数据改变时触发的回调函数 + + Args: + callback: + + Returns:None + """ + assert callable(callback) + assert len( + list(inspect.signature(callback).parameters.keys())) == 3, 'Function args should be 3' + data_manager_old.on_modification(callback) + + @staticmethod + def remove_data_changed_callback(callback: Callable): + if callback in data_manager_old.modification_callback_actions: + data_manager_old.modification_callback_actions.remove(callback) + print('removed callback!') + + @staticmethod + def add_data_deleted_callback(deletion_callback: Callable[[str, str], None]): + """ + 绑定的函数,要求其输入的函数参数为两个。 + + Args: + deletion_callback: + + Returns: + + """ + assert callable(deletion_callback) + assert len( + list(inspect.signature(deletion_callback).parameters.keys())) == 2, 'Function args should be 2' + data_manager_old.on_deletion(deletion_callback) + + @staticmethod + def var_exists(var_name: str): + """ + 判断var_name对应的变量是否存在 + Args: + var_name: - """ - return var_name in data_manager + Returns: - @staticmethod - def set_var(varname: str, variable, provider='unknown', **info): - """ + """ + return var_name in data_manager - Args: - varname: - variable: - provider: - **info: + @staticmethod + def set_var(varname: str, variable, provider='unknown', **info): + """ - Returns: + Args: + varname: + variable: + provider: + **info: - """ - assert isinstance(variable, DataDesc), \ - 'variable name %s ,%s is not type DataDesc' % (varname, variable) - data_manager_old.set_var(varname, variable, provider) + Returns: - @staticmethod - def get_var(var_name: str) -> object: - """ + """ + assert isinstance(variable, DataDesc), \ + 'variable name %s ,%s is not type DataDesc' % (varname, variable) + data_manager_old.set_var(varname, variable, provider) - Args: - var_name: + @staticmethod + def get_var(var_name: str) -> object: + """ - Returns: + Args: + var_name: - """ - raise DeprecationWarning - # return get_var(var_name) + Returns: - @staticmethod - def get_data_desc(var_name) -> DataDesc: - desc = data_manager_old.get_var(var_name) - assert isinstance(desc, DataDesc), repr(desc) - return desc + """ + raise DeprecationWarning + # return get_var(var_name) - @staticmethod - def update_var_dic(var_dic: dict, provider: str, metadata_dic: dict = None): - """ + @staticmethod + def get_data_desc(var_name) -> DataDesc: + desc = data_manager_old.get_var(var_name) + assert isinstance(desc, DataDesc), repr(desc) + return desc - Args: - var_dic: - provider: - metadata_dic: + @staticmethod + def update_var_dic(var_dic: dict, provider: str, metadata_dic: dict = None): + """ - Returns: + Args: + var_dic: + provider: + metadata_dic: - """ - raise DeprecationWarning + Returns: - @staticmethod - def get_metadata(varname: str) -> dict: - """ + """ + raise DeprecationWarning - Args: - varname: + @staticmethod + def get_metadata(varname: str) -> dict: + """ - Returns: + Args: + varname: - """ - return data_manager_old.get_data_info(varname) + Returns: - @staticmethod - def get_all_metadata() -> dict: - """ + """ + return data_manager_old.get_data_info(varname) - Returns: + @staticmethod + def get_all_metadata() -> dict: + """ - """ - d = {k: v for k, v in data_manager_old.metadataset.items()} - return d + Returns: - return ExtensionLib() + """ + d = {k: v for k, v in data_manager_old.metadataset.items()} + return d -extension_lib = wrapper() +extension_lib = ExtensionLib() diff --git a/packages/code_editor/main.py b/packages/code_editor/main.py index de57425f..5346fd4c 100644 --- a/packages/code_editor/main.py +++ b/packages/code_editor/main.py @@ -30,7 +30,6 @@ class Extension(BaseExtension): def __init__(self): super(Extension, self).__init__() - self.settings: Dict[str, Union[int, str]] = {} def on_loading(self): -- Gitee From 4d4a70232b8f81fee18f6e5e6484b6b7f73094a8 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 02:52:04 +0800 Subject: [PATCH 26/34] =?UTF-8?q?=E4=BF=AE=E6=AD=A3ipython=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E6=98=BE=E7=A4=BA=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pmgwidgets/widgets/basic/others/console.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmgwidgets/widgets/basic/others/console.py b/pmgwidgets/widgets/basic/others/console.py index 9d13ea35..15d074ac 100644 --- a/pmgwidgets/widgets/basic/others/console.py +++ b/pmgwidgets/widgets/basic/others/console.py @@ -11,6 +11,7 @@ Created on 2020/8/24 import json import logging import os +import sys from typing import Tuple, Dict, Callable from PySide2.QtCore import QObject, Signal, QThread, QWaitCondition, QMutex, QPoint, QCoreApplication, QTranslator, \ @@ -360,7 +361,6 @@ class PMGIpythonConsole(RichJupyterWidget): if __name__ == '__main__': - import sys import cgitb cgitb.enable(format='text') -- Gitee From 71a333e6188e2b9b1691b395c3bc8d8d8f67b5b0 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 03:00:15 +0800 Subject: [PATCH 27/34] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E5=B0=86print=E6=94=B9=E4=B8=BAlogger?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/code_editor/codeeditor/autocomplete.py | 4 ++-- packages/code_editor/codeeditor/pythoneditor.py | 2 +- .../codeeditor/qtpyeditor/codeedit/basecodeedit.py | 4 +--- .../codeeditor/qtpyeditor/codeeditor/pythoneditor.py | 12 ++++++++---- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/code_editor/codeeditor/autocomplete.py b/packages/code_editor/codeeditor/autocomplete.py index 2d4a2eb6..e9079c51 100644 --- a/packages/code_editor/codeeditor/autocomplete.py +++ b/packages/code_editor/codeeditor/autocomplete.py @@ -3,7 +3,7 @@ import sys import time import logging from PySide2.QtWidgets import QApplication, QMainWindow -from PySide2.QtCore import QObject, Signal, QThread +from PySide2.QtCore import QObject, Signal, QThread, SignalInstance from pmgwidgets import PMQThreadObject logger = logging.getLogger(__name__) @@ -30,7 +30,7 @@ a class PMAutoCompWorker(QObject): - signal_autocomp_parsed = Signal(list, int, int) + signal_autocomp_parsed: SignalInstance = Signal(list, int, int) def __init__(self): super(PMAutoCompWorker, self).__init__() diff --git a/packages/code_editor/codeeditor/pythoneditor.py b/packages/code_editor/codeeditor/pythoneditor.py index 3fcf3e6d..bd865c7c 100644 --- a/packages/code_editor/codeeditor/pythoneditor.py +++ b/packages/code_editor/codeeditor/pythoneditor.py @@ -486,7 +486,7 @@ class PMPythonEditor(PMGPythonEditor): pass def create_context_menu(self) -> 'QMenu': - print('create_context_menu') + logger.info('create_context_menu') menu = super().create_context_menu() menu.addAction(self._action_help) menu.addAction(self._action_help_in_console) diff --git a/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py b/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py index 5cc36578..85ccb4ac 100644 --- a/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py +++ b/packages/code_editor/codeeditor/qtpyeditor/codeedit/basecodeedit.py @@ -592,19 +592,17 @@ class PMBaseCodeEdit(QCodeEditor): """ eols = re.findall(r'\r\n|\r|\n', self.toPlainText()) if not eols: - print('\\n') # self.label_status_eol.setText('Unix(LF)') # self.textEdit.setEolMode(QsciScintilla.EolUnix) # \n换行 return grouped = [(len(list(group)), key) for key, group in groupby(sorted(eols))] eol = sorted(grouped, reverse=True)[0][1] if eol == '\r\n': - print('\\r\\n') + return # self.label_status_eol.setText('Windows(CR LF)') # self.textEdit.setEolMode(QsciScintilla.EolWindows) # \r\n换行 # return QsciScintilla.EolWindows if eol == '\r': - print('\\r') # self.label_status_eol.setText('Mac(CR)') # self.textEdit.setEolMode(QsciScintilla.EolMac) # \r换行 return diff --git a/packages/code_editor/codeeditor/qtpyeditor/codeeditor/pythoneditor.py b/packages/code_editor/codeeditor/qtpyeditor/codeeditor/pythoneditor.py index 140c6f69..b9ac422a 100644 --- a/packages/code_editor/codeeditor/qtpyeditor/codeeditor/pythoneditor.py +++ b/packages/code_editor/codeeditor/qtpyeditor/codeeditor/pythoneditor.py @@ -13,11 +13,15 @@ # @Author: Zhanyi Hou # @Email: 1295752786@qq.com # @File: editor.py - -from PySide2.QtWidgets import QApplication, QListWidgetItem, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QTextBrowser +import logging from typing import Dict + +from PySide2.QtWidgets import QApplication + +from packages.code_editor.codeeditor.qtpyeditor.codeedit import PMPythonCodeEdit from packages.code_editor.codeeditor.qtpyeditor.codeeditor import PMGBaseEditor -from packages.code_editor.codeeditor.qtpyeditor.codeedit import PMBaseCodeEdit, PMPythonCodeEdit + +logger = logging.getLogger('code_editor.pythoneditor') class PMGPythonEditor(PMGBaseEditor): @@ -33,7 +37,7 @@ class PMGPythonEditor(PMGBaseEditor): pass def autocomp_stop(self): - print('autocomp stopped') + logger.info('autocomp stopped') self.text_edit.autocomp_thread.on_exit() -- Gitee From 51f5c37a1b5a048aabd4c57fc36fa4cfeaeb6d15 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 03:02:04 +0800 Subject: [PATCH 28/34] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../extensions/extensions_manager/manager.py | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/features/extensions/extensions_manager/manager.py b/features/extensions/extensions_manager/manager.py index 24c2e8bb..14fb3bf1 100644 --- a/features/extensions/extensions_manager/manager.py +++ b/features/extensions/extensions_manager/manager.py @@ -1,17 +1,17 @@ -from features.extensions.extensions_manager.UIInserter import ui_inserters -from features.extensions.extensions_manager.ExtensionLoader import ExtensionLoader -from .vermanager import VersionsManager, Module +import importlib +import json +import json.decoder +import logging import os import shutil import sys import time -import json -import json.decoder import zipfile -import importlib -import traceback -import logging + import utils +from features.extensions.extensions_manager.ExtensionLoader import ExtensionLoader +from features.extensions.extensions_manager.UIInserter import ui_inserters +from .vermanager import VersionsManager logger = logging.getLogger('extensionmanager') logger.setLevel(logging.DEBUG) @@ -27,7 +27,7 @@ class ExtensionsManager: self.ui_inserters = ui_inserters self.id_ = 0 # 扩展id,动态分配的 self.setting_path = os.path.join( - utils.get_root_dir(), 'configuration','extensions.json') # 扩展配置文件位置 + utils.get_root_dir(), 'configuration', 'extensions.json') # 扩展配置文件位置 if not os.path.exists(self.setting_path): raise FileNotFoundError(self.setting_path) try: @@ -103,8 +103,7 @@ class ExtensionsManager: if callable(callback): callback(ext_load_status) t1 = time.time() - logger.info('boot time elapsed for %s : %f s' % - (str(package), t1 - t0)) + logger.info(f'boot time elapsed for {str(package)} : {t1 - t0:f} s') def get_extension(self, name): """通过名称获取扩展""" -- Gitee From ae96c429c816c618a6cf5a84b695cabca17b6ff1 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 03:05:11 +0800 Subject: [PATCH 29/34] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pmgwidgets/utilities/network/generalclient.py | 5 ++--- pmgwidgets/utilities/network/util.py | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pmgwidgets/utilities/network/generalclient.py b/pmgwidgets/utilities/network/generalclient.py index d19ab5fe..d9655f3a 100644 --- a/pmgwidgets/utilities/network/generalclient.py +++ b/pmgwidgets/utilities/network/generalclient.py @@ -1,14 +1,13 @@ # coding=utf-8 -''' +""" client端 长连接,短连接,心跳 -''' +""" import json import threading import zlib from typing import List - import time from .util import timeit, receive diff --git a/pmgwidgets/utilities/network/util.py b/pmgwidgets/utilities/network/util.py index bf1e8ab0..7c9fface 100644 --- a/pmgwidgets/utilities/network/util.py +++ b/pmgwidgets/utilities/network/util.py @@ -89,7 +89,7 @@ def timeit(func): def wrapper(*args, **kwargs): t0 = time.time() r = func(*args, **kwargs) - print('time_elapsed', time.time() - t0) + logger.debug('time_elapsed', time.time() - t0) return r return wrapper -- Gitee From e3c4da3f420e548290c3823a114a2e1f641d153c Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 03:14:40 +0800 Subject: [PATCH 30/34] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeeditor/errors_translation/translate.py | 2 +- .../qtpyeditor/highlighters/python.py | 12 +++++++----- packages/code_editor/codeeditor/tabwidget.py | 2 +- .../display/dynamicgraph/base/basetimeseries.py | 13 +++++++++---- pmgwidgets/flowchart/core/flowchart_scene.py | 13 ++++++------- pmgwidgets/utilities/network/qtclient.py | 17 +++++++---------- pmgwidgets/utilities/network/server.py | 9 ++++----- 7 files changed, 35 insertions(+), 33 deletions(-) diff --git a/packages/code_editor/codeeditor/errors_translation/translate.py b/packages/code_editor/codeeditor/errors_translation/translate.py index 154e6bf3..2d57d4a2 100644 --- a/packages/code_editor/codeeditor/errors_translation/translate.py +++ b/packages/code_editor/codeeditor/errors_translation/translate.py @@ -2,7 +2,7 @@ import json import os d = {} -with open('translations.txt', 'r',encoding='utf-8') as f: +with open('translations.txt', 'r', encoding='utf-8') as f: for l in f.read().split('\n'): if l.startswith(('E', 'W', 'C', 'F')): try: diff --git a/packages/code_editor/codeeditor/qtpyeditor/highlighters/python.py b/packages/code_editor/codeeditor/qtpyeditor/highlighters/python.py index ba91ee8c..232e7035 100644 --- a/packages/code_editor/codeeditor/qtpyeditor/highlighters/python.py +++ b/packages/code_editor/codeeditor/qtpyeditor/highlighters/python.py @@ -4,6 +4,7 @@ # @Email: 1295752786@qq.com # @File: python.py import builtins +import logging import sys import time from typing import Dict, Tuple, List, Set @@ -12,6 +13,7 @@ from PySide2.QtCore import QRegExp, Qt from PySide2.QtWidgets import QApplication from PySide2.QtGui import QSyntaxHighlighter, QTextCharFormat, QColor, QFont, QCursor, QBrush, QTextBlock +logger = logging.getLogger('code_editor.highlighters.python') color_scheme_intellij = {'keyword': '#101e96'} color_scheme_dark = {'keyword': '#b7602f'} @@ -93,10 +95,10 @@ class PythonHighlighter(BaseHighlighter): self._rehighlight_hint = True self._rehighlight_syntax = True self.KEYWORDS = ["and", "as", "assert", 'async', 'await', "break", "class", - "continue", "def", "del", "elif", "else", "except", - "exec", "finally", "for", "from", "global", "if", - "import", "in", "is", "lambda", "not", "or", "pass", - "raise", "return", "try", "while", "with", "yield"] + "continue", "def", "del", "elif", "else", "except", + "exec", "finally", "for", "from", "global", "if", + "import", "in", "is", "lambda", "not", "or", "pass", + "raise", "return", "try", "while", "with", "yield"] BUILTINS = list(builtins.__dict__.keys()) CONSTANTS = ["False", "True", "None", "NotImplemented", "Ellipsis"] @@ -250,7 +252,7 @@ class PythonHighlighter(BaseHighlighter): QSyntaxHighlighter.rehighlight(self) QApplication.restoreOverrideCursor() t1 = time.time() - print(t1 - t0, 'time.time,elapsed for rendering code', self.counter) + logger.debug(t1 - t0, 'time.time,elapsed for rendering code', self.counter) def registerHighlight(self, line_no: int, start: int, length: int, marker: int, hint: str): """ diff --git a/packages/code_editor/codeeditor/tabwidget.py b/packages/code_editor/codeeditor/tabwidget.py index 76fd4e3e..d909d4a4 100644 --- a/packages/code_editor/codeeditor/tabwidget.py +++ b/packages/code_editor/codeeditor/tabwidget.py @@ -576,7 +576,7 @@ class PMCodeEditTabWidget(QTabWidget, PMDockObject): current_widget.goto_line(row) logger.warning('goto file %s ,line %d' % (path, row)) t1 = time.time() - print('time elapsed:', t1 - t0) + logger.debug('time elapsed:', t1 - t0) def slot_goto(self): """ diff --git a/pmgwidgets/display/dynamicgraph/base/basetimeseries.py b/pmgwidgets/display/dynamicgraph/base/basetimeseries.py index d00a7e04..d50643aa 100644 --- a/pmgwidgets/display/dynamicgraph/base/basetimeseries.py +++ b/pmgwidgets/display/dynamicgraph/base/basetimeseries.py @@ -1,3 +1,4 @@ +import logging import sys import time @@ -7,6 +8,8 @@ import numpy as np from typing import List, Dict, Tuple from pmgwidgets.display.matplotlib.qt5agg import PMMatplotlibQt5Widget +logger = logging.getLogger('display.basetimeseries') + class PMBaseTimeSeriesWidget(QWidget): def __init__(self, parent: 'QWidget' = None, recent_samples: int = 100, show_mode: str = '', @@ -137,7 +140,7 @@ class PMTimeSeriesPGWidget(PMBaseTimeSeriesWidget): def __init__(self, max_samples: int = 10000, recent_samples: int = 100): super(PMTimeSeriesPGWidget, self).__init__(max_samples=max_samples, recent_samples=recent_samples) import pyqtgraph - self.curves:Dict ={} + self.curves: Dict = {} self.setLayout(QVBoxLayout()) self.plot_widget = pyqtgraph.plot() # PMMatplotlibQt5Widget(self) self.layout().addWidget(self.plot_widget) @@ -146,7 +149,7 @@ class PMTimeSeriesPGWidget(PMBaseTimeSeriesWidget): self.ax = None def add_data(self, data_name, data_type): - super().add_data(data_name,data_type) + super().add_data(data_name, data_type) self.curves[data_name] = self.plot_widget.plot() # def plot(self, t, y): @@ -154,7 +157,8 @@ class PMTimeSeriesPGWidget(PMBaseTimeSeriesWidget): def refresh(self): for k in self.time.keys(): t, y = self.get_recent_data(k) - self.curves[k].setData(t,y) + self.curves[k].setData(t, y) + def clear(self): pass @@ -165,7 +169,7 @@ def time_out(): i += 1 graphics.add_sample('a', value=np.random.randint(100)) t1 = time.time() - print(i, 'time elapsed :', t1 - t0) + logger.debug(i, 'time elapsed :', t1 - t0) if __name__ == '__main__': @@ -193,6 +197,7 @@ if __name__ == '__main__': graphics.add_data('a', np.float) + timer = QTimer() timer.timeout.connect(time_out) diff --git a/pmgwidgets/flowchart/core/flowchart_scene.py b/pmgwidgets/flowchart/core/flowchart_scene.py index 6c1137d2..fe408083 100644 --- a/pmgwidgets/flowchart/core/flowchart_scene.py +++ b/pmgwidgets/flowchart/core/flowchart_scene.py @@ -12,8 +12,8 @@ type:str params:List[str] """ import json +import logging import os -import sys import time from typing import List, Dict, TYPE_CHECKING @@ -22,14 +22,13 @@ if TYPE_CHECKING: from pmgwidgets.flowchart.core.flow_content import FlowContentForFunction, flowcontent_types from pmgwidgets.flowchart.core.flow_items import CustomPort, CustomLine, CustomMidPoint, CustomRect from pmgwidgets.flowchart.core.flow_node import Node -from pmgwidgets.flowchart.core.nodemanager import NodeManagerWidget from pmgwidgets.utilities.uilogics.undomanager import UndoManager -from PySide2.QtCore import QSize, QCoreApplication, QLineF, Qt, QPointF, QThread, Signal -from PySide2.QtGui import QPen, QColor, QKeyEvent, QWheelEvent, QCloseEvent -from PySide2.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QToolButton, QSpacerItem, QSizePolicy, QGraphicsView, \ - QFrame, QApplication, QGraphicsScene, QGraphicsSceneMouseEvent, QMenu, QGraphicsSceneContextMenuEvent, QFileDialog, \ - QMessageBox +from PySide2.QtCore import QLineF, Qt, QPointF, Signal +from PySide2.QtGui import QPen, QColor, QKeyEvent +from PySide2.QtWidgets import QGraphicsView, \ + QGraphicsScene, QGraphicsSceneMouseEvent, QMenu, QGraphicsSceneContextMenuEvent +logger = logging.getLogger(__name__) COLOR_NORMAL = QColor(212, 227, 242) COLOR_HOVER = QColor(255, 200, 00) COLOR_HOVER_PORT = QColor(0, 0, 50) diff --git a/pmgwidgets/utilities/network/qtclient.py b/pmgwidgets/utilities/network/qtclient.py index 35047ed3..c177b3da 100644 --- a/pmgwidgets/utilities/network/qtclient.py +++ b/pmgwidgets/utilities/network/qtclient.py @@ -1,24 +1,21 @@ # coding=utf-8 __author__ = '侯展意' -import base64 import json +import logging +import socket +import sys import warnings import zlib from typing import List -import logging -import sys -import cloudpickle -import time -import socket - -logger = logging.getLogger(__name__) -from PySide2.QtWidgets import QApplication from PySide2.QtCore import QObject, QThread, Signal, QTimer +from PySide2.QtWidgets import QApplication -from .util import timeit, receive from .baseclient import BaseClient +from .util import timeit, receive + +logger = logging.getLogger(__name__) def parse_splicing_packets(packet_bytes: bytes) -> List[bytes]: diff --git a/pmgwidgets/utilities/network/server.py b/pmgwidgets/utilities/network/server.py index d6ebf377..f69a0dc0 100644 --- a/pmgwidgets/utilities/network/server.py +++ b/pmgwidgets/utilities/network/server.py @@ -5,14 +5,14 @@ """ import json -import time +import logging import socket import sys -import logging +import time from typing import List, Tuple, Dict, Union -from PySide2.QtWidgets import QApplication from PySide2.QtCore import QObject, QThread, QTimer +from PySide2.QtWidgets import QApplication from .util import receive, strip_byte_end @@ -93,8 +93,7 @@ class LoopWork(QObject): t0 = time.time() self.handle_packet(sock, b) t1 = time.time() - logger.info( - "Message handled!\nThe message was:%s" % (message) + '\nTime elapsed %f s\n' % (t1 - t0)) + logger.info(f"Message handled!\nThe message was:{message}\nTime elapsed {t1 - t0:f} s\n") except: import traceback -- Gitee From 23708174feb107e6bfbebd6c3af826382e9c2a5d Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 03:23:51 +0800 Subject: [PATCH 31/34] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qtpyeditor/codeeditor/baseeditor.py | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/packages/code_editor/codeeditor/qtpyeditor/codeeditor/baseeditor.py b/packages/code_editor/codeeditor/qtpyeditor/codeeditor/baseeditor.py index bbf58f66..4305e25c 100644 --- a/packages/code_editor/codeeditor/qtpyeditor/codeeditor/baseeditor.py +++ b/packages/code_editor/codeeditor/qtpyeditor/codeeditor/baseeditor.py @@ -42,7 +42,7 @@ import time from itertools import groupby from typing import TYPE_CHECKING, List, Iterable, Dict, Set, Tuple, Any from PySide2.QtGui import QIcon, QKeySequence, QTextDocument, QTextCursor, QTextBlock, QDropEvent -from PySide2.QtCore import QDir, QCoreApplication, Qt, QPoint, Signal, QTranslator, QLocale, QUrl +from PySide2.QtCore import QDir, QCoreApplication, Qt, QPoint, Signal, QTranslator, QLocale, QUrl, SignalInstance from PySide2.QtWidgets import QWidget, QMessageBox, QFileDialog, QAction, QShortcut, QDialog, QVBoxLayout, QPushButton, \ QHBoxLayout, QApplication, QLabel @@ -189,10 +189,13 @@ class FindDialog(QDialog): class PMGBaseEditor(PMAbstractEditor): - signal_focused_in: Signal = None - signal_new_requested: Signal = Signal(str, int) # 文件路径;文件的打开模式(目前都是0) - signal_save_requested: Signal = Signal() - signal_request_find_in_path: Signal = Signal(str) + signal_focused_in: SignalInstance = None + signal_new_requested: SignalInstance = Signal(str, int) # 文件路径;文件的打开模式(目前都是0) + signal_save_requested: SignalInstance = Signal() + signal_request_find_in_path: SignalInstance = Signal(str) + text_edit: 'PMBaseCodeEdit' + find_dialog: 'FindDialog' + goto_line_dialog: 'GotoLineDialog' def __init__(self, parent): app = QApplication.instance() @@ -203,12 +206,9 @@ class PMGBaseEditor(PMAbstractEditor): app.installTranslator(trans_editor_tb) super().__init__(parent) - self.find_dialog: 'FindDialog' = None - self.goto_line_dialog: 'GotoLineDialog' = None self.last_save_time = 0 self._path = '' self._modified = False - self.text_edit: 'PMBaseCodeEdit' = None self._extension_names: List[str] = [] # 该编辑器支持的文件名 self._indicator_dict: Dict[str, str] = {} @@ -245,8 +245,7 @@ class PMGBaseEditor(PMAbstractEditor): def show_cursor_pos(self): row = self.text_edit.textCursor().block().blockNumber() col = self.text_edit.textCursor().columnNumber() - self.status_label.setText( - '行:{row},列:{col}'.format(row=row + 1, col=col + 1)) + self.status_label.setText(f'行:{row + 1},列:{col + 1}') def set_shortcut(self): pass @@ -258,10 +257,7 @@ class PMGBaseEditor(PMAbstractEditor): pass def goto_line(self, line_no: int): - """ - 跳转到对应行列 - :return: - """ + """跳转到对应行列""" doc: QTextDocument = self.text_edit.document() lines = doc.blockCount() assert 1 <= line_no <= lines -- Gitee From 5b8b1f9727a561fb8fef5f9b53fb86ed563e937a Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 03:28:37 +0800 Subject: [PATCH 32/34] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/code_editor/codeeditor/pythoneditor.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/code_editor/codeeditor/pythoneditor.py b/packages/code_editor/codeeditor/pythoneditor.py index bd865c7c..8bbee810 100644 --- a/packages/code_editor/codeeditor/pythoneditor.py +++ b/packages/code_editor/codeeditor/pythoneditor.py @@ -24,18 +24,19 @@ from PySide2.QtGui import QCloseEvent, QKeySequence from PySide2.QtWidgets import QMessageBox, QMenu, QAction, QShortcut from yapf.yapflib import py3compat, yapf_api -# from .baseeditor import PMBaseEditor, PMAPI from packages.code_editor.codeeditor.qtpyeditor import PMGPythonEditor, PythonHighlighter +from pmgwidgets import in_unit_test, PMGPanelDialog, parse_simplified_pmgjson, run_python_file_in_terminal, \ + PMGOneShotThreadRunner with open(os.path.join(os.path.dirname(__file__), 'flake8_trans.json'), 'rb') as f: # 打开flake8提示信息的文件翻译。 flake8_translations = json.load(f) + show_as_errors = {'E999'} show_as_warnings = set() show_as_infos = {'F841', 'F401', 'F403', 'F405', 'E303'} # 分别是变量导入未使用、定义未使用、使用*导入以及无法推断可能由*导入的类型。 + logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) -from pmgwidgets import in_unit_test, PMGPanelDialog, parse_simplified_pmgjson, \ - run_python_file_in_terminal, PMGOneShotThreadRunner class PMPythonEditor(PMGPythonEditor): -- Gitee From c65cd2781504b8a6f61dd00412704a879e2ceb7e Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 03:31:31 +0800 Subject: [PATCH 33/34] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/code_editor/codeeditor/pythoneditor.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/code_editor/codeeditor/pythoneditor.py b/packages/code_editor/codeeditor/pythoneditor.py index 8bbee810..0b0f33d1 100644 --- a/packages/code_editor/codeeditor/pythoneditor.py +++ b/packages/code_editor/codeeditor/pythoneditor.py @@ -19,7 +19,7 @@ import os import re from typing import List, Tuple, Optional -from PySide2.QtCore import QDir, Qt, Signal +from PySide2.QtCore import QDir, Qt, Signal, SignalInstance from PySide2.QtGui import QCloseEvent, QKeySequence from PySide2.QtWidgets import QMessageBox, QMenu, QAction, QShortcut from yapf.yapflib import py3compat, yapf_api @@ -43,7 +43,8 @@ class PMPythonEditor(PMGPythonEditor): """ 自定义编辑器控件 """ - signal_goto_definition = Signal(str, int, int) + signal_goto_definition: SignalInstance = Signal(str, int, int) + help_runner: 'PMGOneShotThreadRunner' def __init__(self, parent=None): super(PMPythonEditor, self).__init__(parent) # , comment_string='# ') @@ -57,7 +58,6 @@ class PMPythonEditor(PMGPythonEditor): # self.slot_set_theme(self._theme) self.extension_lib = None self.last_hint = '' - self.help_runner: 'PMGOneShotThreadRunner' = None self.prepare_actions() # self.marker_update_timer = QTimer() @@ -75,11 +75,7 @@ class PMPythonEditor(PMGPythonEditor): self.extension_lib = lib def _init_actions(self) -> None: - """ - 初始化事件 - - :return: - """ + """初始化事件""" super(PMPythonEditor, self)._init_actions() self._action_help = QAction(self.tr('Function Help'), self.text_edit) self._shortcut_help = QShortcut(QKeySequence('F1'), self.text_edit, context=Qt.WidgetShortcut) @@ -98,10 +94,9 @@ class PMPythonEditor(PMGPythonEditor): self._action_remove_breakpoint.setVisible(False) def _init_signals(self) -> None: - """ - 初始化信号绑定 + """初始化信号绑定。 + 无需super,因为基类已经初始化过了。 - :return: None """ super(PMPythonEditor, self)._init_signals() self._shortcut_help.activated.connect(self.get_help) -- Gitee From bac11527a10c6ae3e024f279dc244040701d5749 Mon Sep 17 00:00:00 2001 From: wolfpan Date: Mon, 2 Aug 2021 03:32:59 +0800 Subject: [PATCH 34/34] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/code_editor/codeeditor/pythoneditor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/code_editor/codeeditor/pythoneditor.py b/packages/code_editor/codeeditor/pythoneditor.py index 0b0f33d1..df3bcd3e 100644 --- a/packages/code_editor/codeeditor/pythoneditor.py +++ b/packages/code_editor/codeeditor/pythoneditor.py @@ -368,6 +368,7 @@ class PMPythonEditor(PMGPythonEditor): style_config=os.path.join(os.path.dirname(__file__), 'config', '.style.yapf') ) self.set_text(reformatted_source) + # TODO 重构代码后需要保证光标的位置不动,可以考虑使用parso实现,这里目前的bug有些多 self.goto_line(first_line + 1) # 跳转回开始时的行 # self.text_edit.goToLine(first_line) except Exception as e: -- Gitee