abstract-ide 0.0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. abstract_ide-0.0.0.1/PKG-INFO +36 -0
  2. abstract_ide-0.0.0.1/README.md +2 -0
  3. abstract_ide-0.0.0.1/pyproject.toml +3 -0
  4. abstract_ide-0.0.0.1/setup.cfg +4 -0
  5. abstract_ide-0.0.0.1/setup.py +39 -0
  6. abstract_ide-0.0.0.1/src/abstract_ide/__init__.py +1 -0
  7. abstract_ide-0.0.0.1/src/abstract_ide/imports/__init__.py +1 -0
  8. abstract_ide-0.0.0.1/src/abstract_ide/imports/imports.py +0 -0
  9. abstract_ide-0.0.0.1/src/abstract_ide/utils/__init__.py +13 -0
  10. abstract_ide-0.0.0.1/src/abstract_ide/utils/imports/__init__.py +1 -0
  11. abstract_ide-0.0.0.1/src/abstract_ide/utils/imports/imports/__init__.py +2 -0
  12. abstract_ide-0.0.0.1/src/abstract_ide/utils/imports/imports/constants.py +31 -0
  13. abstract_ide-0.0.0.1/src/abstract_ide/utils/imports/imports/imports.py +18 -0
  14. abstract_ide-0.0.0.1/src/abstract_ide/utils/imports/utils/__init__.py +2 -0
  15. abstract_ide-0.0.0.1/src/abstract_ide/utils/imports/utils/file_utils.py +31 -0
  16. abstract_ide-0.0.0.1/src/abstract_ide/utils/imports/utils/utils.py +184 -0
  17. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/__init__.py +1 -0
  18. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/imports/__init__.py +2 -0
  19. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/imports/imports.py +1 -0
  20. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/imports/widget_funcs.py +38 -0
  21. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/__init__.py +3 -0
  22. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/get_modules.py +436 -0
  23. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/importGraphWorker.py +29 -0
  24. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/imports.py +1 -0
  25. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/__init__.py +1 -0
  26. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/__init__.py +2 -0
  27. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/clickHandlers/__init__.py +1 -0
  28. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/clickHandlers/clickHandlers.py +44 -0
  29. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/clickHandlers/imports.py +1 -0
  30. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/imports.py +1 -0
  31. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/init_tabs/__init__.py +9 -0
  32. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/init_tabs/apigui.py +270 -0
  33. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/init_tabs/finder/__init__.py +1 -0
  34. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/init_tabs/finder/clickfinder.py +266 -0
  35. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/init_tabs/finder/finder.py +698 -0
  36. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/init_tabs/finder/finder_back.py +266 -0
  37. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/init_tabs/functions_page/__init__.py +1 -0
  38. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/init_tabs/functions_page/functions_page.py +70 -0
  39. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/init_tabs/imports.py +1 -0
  40. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/init_tabs/initialize_init/__init__.py +1 -0
  41. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/init_tabs/initialize_init/initialize_init.py +40 -0
  42. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/init_tabs/runner/__init__.py +1 -0
  43. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/functions/init_tabs/runner/runner.py +59 -0
  44. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/imports.py +4 -0
  45. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/mainWindow/mainWindow.py +394 -0
  46. abstract_ide-0.0.0.1/src/abstract_ide/utils/managers/utils/worker.py +70 -0
  47. abstract_ide-0.0.0.1/src/abstract_ide/utils/widgets/__init__.py +1 -0
  48. abstract_ide-0.0.0.1/src/abstract_ide/utils/widgets/imports/__init__.py +1 -0
  49. abstract_ide-0.0.0.1/src/abstract_ide/utils/widgets/imports/imports.py +1 -0
  50. abstract_ide-0.0.0.1/src/abstract_ide/utils/widgets/utils/__init__.py +1 -0
  51. abstract_ide-0.0.0.1/src/abstract_ide/utils/widgets/utils/kwargs_utils.py +103 -0
  52. abstract_ide-0.0.0.1/src/abstract_ide/utils/widgets/utils/utils.py +22 -0
  53. abstract_ide-0.0.0.1/src/abstract_ide/utils/widgets/utils/widgets.py +42 -0
  54. abstract_ide-0.0.0.1/src/abstract_ide.egg-info/PKG-INFO +36 -0
  55. abstract_ide-0.0.0.1/src/abstract_ide.egg-info/SOURCES.txt +57 -0
  56. abstract_ide-0.0.0.1/src/abstract_ide.egg-info/dependency_links.txt +1 -0
  57. abstract_ide-0.0.0.1/src/abstract_ide.egg-info/requires.txt +10 -0
  58. abstract_ide-0.0.0.1/src/abstract_ide.egg-info/top_level.txt +1 -0
@@ -0,0 +1,36 @@
1
+ Metadata-Version: 2.4
2
+ Name: abstract_ide
3
+ Version: 0.0.0.1
4
+ Summary: abstract_ide
5
+ Home-page: https://github.com/AbstractEndeavors/abstract_ide
6
+ Author: putkoff
7
+ Author-email: partners@abstractendeavors.com
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Requires-Python: >=3.6
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: abstract_apis
16
+ Requires-Dist: PyQt5
17
+ Requires-Dist: abstract_webtools
18
+ Requires-Dist: abstract_utilities
19
+ Requires-Dist: abstract_gui
20
+ Requires-Dist: pydot
21
+ Requires-Dist: abstract_clipit
22
+ Requires-Dist: flask
23
+ Requires-Dist: abstract_paths
24
+ Requires-Dist: PyQt6
25
+ Dynamic: author
26
+ Dynamic: author-email
27
+ Dynamic: classifier
28
+ Dynamic: description
29
+ Dynamic: description-content-type
30
+ Dynamic: home-page
31
+ Dynamic: requires-dist
32
+ Dynamic: requires-python
33
+ Dynamic: summary
34
+
35
+ # abstract_ide
36
+
@@ -0,0 +1,2 @@
1
+ # abstract_ide
2
+
@@ -0,0 +1,3 @@
1
+ [build-system]
2
+ requires = ["setuptools>=42", "wheel"]
3
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,39 @@
1
+ from time import time
2
+ import setuptools
3
+ with open("README.md", "r", encoding="utf-8") as fh:
4
+ long_description = fh.read()
5
+ setuptools.setup(
6
+ name='abstract_ide',
7
+ version='0.0.0.001',
8
+ author='putkoff',
9
+ author_email='partners@abstractendeavors.com',
10
+ description='abstract_ide',
11
+ long_description=long_description,
12
+ long_description_content_type='text/markdown',
13
+ url='https://github.com/AbstractEndeavors/abstract_ide',
14
+ classifiers=[
15
+ 'Development Status :: 3 - Alpha',
16
+ 'Intended Audience :: Developers',
17
+ 'License :: OSI Approved :: MIT License',
18
+ 'Programming Language :: Python :: 3',
19
+ 'Programming Language :: Python :: 3.11',
20
+ ],
21
+ install_requires=[
22
+ 'abstract_apis',
23
+ 'PyQt5',
24
+ 'abstract_webtools',
25
+ 'abstract_utilities',
26
+ 'abstract_gui',
27
+ 'pydot',
28
+ 'abstract_clipit',
29
+ 'flask',
30
+ 'abstract_paths',
31
+ 'PyQt6'
32
+ ]
33
+ ,
34
+ package_dir={"": "src"},
35
+ packages=setuptools.find_packages(where="src"),
36
+ python_requires=">=3.6",
37
+
38
+
39
+ )
@@ -0,0 +1 @@
1
+ from .utils import *
@@ -0,0 +1 @@
1
+ from .imports import *
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env python3
2
+ from .managers import *
3
+
4
+ def startGui():
5
+ try:
6
+ app = QApplication(sys.argv)
7
+ win = MainWindow()
8
+ win.show()
9
+ sys.exit(app.exec_())
10
+ except Exception:
11
+ print(traceback.format_exc())
12
+
13
+
@@ -0,0 +1 @@
1
+ from .utils import *
@@ -0,0 +1,2 @@
1
+ from .imports import *
2
+ from .constants import *
@@ -0,0 +1,31 @@
1
+ import re
2
+ # ─────────────────────────────────────────────────────────────────────────────
3
+ # Command with markers (no log files on disk needed)
4
+ COMMAND = r"""
5
+ set -e
6
+ echo "__TSC_BEGIN__"
7
+ npx tsc --noEmit || true
8
+ echo "__TSC_END__"
9
+ echo "__BUILD_BEGIN__"
10
+ CI=true yarn build || true
11
+ echo "__BUILD_END__"
12
+ """
13
+
14
+ ANSI_RE = re.compile(r'\x1b\[[0-9;]*m')
15
+ FILE_REGEX = re.compile(r'([^\s:()]+\.(?:ts|tsx|js|jsx))\((\d+),(\d+)\)')
16
+ FILE_FILE_REGEX = re.compile(
17
+ r'(?P<file>[^\s:()]+\.(?:ts|tsx|js|jsx))'
18
+ r'(?:\((?P<l1>\d+),(?P<c1>\d+)\)|:(?P<l2>\d+):(?P<c2>\d+))'
19
+ )
20
+
21
+ GREP_REGEX = r"import\s+[^;]*\buse[^;]*from\s+['\"]react['\"]"
22
+ SEV_ERR = re.compile(r'(^|\b)(ERROR|error)\b|error TS\d+', re.IGNORECASE)
23
+ SEV_WRN = re.compile(r'(^|\b)(WARNING|warning)\b|warning TS\d+', re.IGNORECASE)
24
+
25
+ # Prefer targets left→right when hunting alternates
26
+ EXT_SWAP = {
27
+ ".ts": [".tsx"],
28
+ ".tsx": [".ts"],
29
+ ".js": [".jsx"],
30
+ ".jsx": [".js"],
31
+ }
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env python3
2
+ import os,re,subprocess,sys,re,traceback,pydot
3
+ from pathlib import Path
4
+ from PyQt5.QtCore import (
5
+ QThread, pyqtSignal,
6
+ Qt
7
+ )
8
+ from PyQt5.QtGui import QTextCursor
9
+ from PyQt5.QtWidgets import (
10
+ QApplication, QVBoxLayout, QHBoxLayout,
11
+ QLabel, QLineEdit, QPushButton, QTextEdit,
12
+ QListWidgetItem, QMessageBox, QRadioButton,
13
+ QButtonGroup, QCheckBox,QWidget,QTabWidget,
14
+ QScrollArea, QGroupBox, QComboBox, QLayout,
15
+ QWidget, QVBoxLayout, QLabel, QListWidget
16
+ )
17
+ from abstract_utilities import make_list,safe_read_from_json,read_from_file,make_dirs
18
+ from abstract_paths import invert_to_function_map,start_analyzer
@@ -0,0 +1,2 @@
1
+ from .utils import *
2
+ from .file_utils import *
@@ -0,0 +1,31 @@
1
+ from ..imports import start_analyzer,pydot,os,safe_read_from_json,make_dirs
2
+ BASE_DIRECTORY = '/var/www/html/clownworld/bolshevid'
3
+ DATA_DIR = make_dirs(BASE_DIRECTORY,"data")
4
+ IMPORT_MAP_DIR = make_dirs(DATA_DIR,"import_tools")
5
+
6
+ def get_dot_path():
7
+ return os.path.join(IMPORT_MAP_DIR,'graph.dot')
8
+ def get_import_graph_path():
9
+ return os.path.join(IMPORT_MAP_DIR,'import-graph.json')
10
+ def read_from_dot_file(path = None):
11
+ path = get_dot_path()
12
+ graphs, = pydot.graph_from_dot_file(path)
13
+ return graphs
14
+ def get_dot_data():
15
+ dot_path = get_dot_path()
16
+ ensure_import_creation(dot_path)
17
+ return read_from_dot_file()
18
+ def get_import_graph_data():
19
+ graph_path = get_import_graph_path()
20
+ ensure_import_creation(graph_path)
21
+ return safe_read_from_json(graph_path)
22
+ def ensure_import_creation(path):
23
+ if not os.path.isfile(path):
24
+ create_import_maps()
25
+ def create_import_maps():
26
+ root = BASE_DIRECTORY
27
+ directory = os.getcwd()
28
+ entries = 'index,main'
29
+ out = get_import_graph_path()
30
+ dot = get_dot_path()
31
+ start_analyzer(root=root,entries=entries,out=out,dot=dot)
@@ -0,0 +1,184 @@
1
+ from ..imports import *
2
+ def read_from_dot_file(path):
3
+ graphs, = pydot.graph_from_dot_file(path)
4
+ return graphs
5
+
6
+ def sh_quote(s: str) -> str:
7
+ return "'" + (s or "").replace("'", "'\\''") + "'"
8
+
9
+ def strip_ansi(text: str) -> str:
10
+ return ANSI_RE.sub('', text or "")
11
+
12
+ def get_trailing_number(file_path):
13
+ return_js = {"chars":'',"file_path":file_path}
14
+ for i in range(1,len(file_path)+1):
15
+ char = file_path[-i]
16
+ if is_number(char) or char == ':':
17
+ return_js["chars"] = str(char)+ str(chars)
18
+ else:
19
+ file_path = file_path[:-i]
20
+ return return_js
21
+
22
+ def resolve_alt_ext(path: str, project_root: str) -> str:
23
+ """
24
+ If 'path' doesn't exist, try sibling files with alternate extensions
25
+ (ts<->tsx, js<->jsx). Also tries case-insensitive match and glob
26
+ for same basename with any extension in the same folder.
27
+ Returns the best existing path, or the original if none found.
28
+ """
29
+ if not path:
30
+ return path
31
+ if os.path.exists(path):
32
+ return path
33
+
34
+ folder, base = os.path.dirname(path), os.path.basename(path)
35
+ stem, ext = os.path.splitext(base)
36
+
37
+ # 1) explicit swap candidates
38
+ for alt in EXT_SWAP.get(ext, []):
39
+ cand = os.path.join(folder, stem + alt)
40
+ if os.path.exists(cand):
41
+ return cand
42
+
43
+ # 2) case-insensitive lookup (useful on case-sensitive FS when log had case mismatch)
44
+ try:
45
+ for name in os.listdir(folder or "."):
46
+ if name.lower() == (stem + ext).lower():
47
+ cand = os.path.join(folder, name)
48
+ if os.path.exists(cand):
49
+ return cand
50
+ except Exception:
51
+ pass
52
+
53
+ # 3) any sibling with same stem (e.g., foo.*)
54
+ try:
55
+ for name in os.listdir(folder or "."):
56
+ nstem, next_ = os.path.splitext(name)
57
+ if nstem == stem and os.path.isfile(os.path.join(folder, name)):
58
+ # prefer our known alternates order
59
+ if next_ in sum(EXT_SWAP.values(), []):
60
+ return os.path.join(folder, name)
61
+ # fallback: first file with same stem
62
+ for name in os.listdir(folder or "."):
63
+ nstem, _ = os.path.splitext(name)
64
+ if nstem == stem:
65
+ return os.path.join(folder, name)
66
+ except Exception:
67
+ pass
68
+
69
+ return path
70
+
71
+
72
+
73
+ #split funcs
74
+ def split_sections(raw: str):
75
+ """Return (tsc_text, build_text) from the full captured output."""
76
+ raw = strip_ansi(raw)
77
+ tsc = ""
78
+ build = ""
79
+ try:
80
+ tsc = raw.split("__TSC_BEGIN__", 1)[1].split("__TSC_END__", 1)[0]
81
+ except Exception:
82
+ pass
83
+ try:
84
+ build = raw.split("__BUILD_BEGIN__", 1)[1].split("__BUILD_END__", 1)[0]
85
+ except Exception:
86
+ pass
87
+ return tsc.strip(), build.strip()
88
+
89
+ def split_by_severity(text: str):
90
+ """Return (errors_text, warnings_text) based on simple, robust heuristics."""
91
+ errs, warns = [], []
92
+ for ln in (text or "").splitlines():
93
+ # webpack/CRA often prints 'WARNING in ...' / 'ERROR in ...'
94
+ if ln.startswith('WARNING in '):
95
+ warns.append(ln)
96
+ continue
97
+ if ln.startswith('ERROR in '):
98
+ errs.append(ln)
99
+ continue
100
+
101
+ lnl = ln.lower()
102
+ if 'error' in lnl:
103
+ errs.append(ln)
104
+ elif 'warning' in lnl:
105
+ warns.append(ln)
106
+ return "\n".join(errs), "\n".join(warns)
107
+
108
+ #entries
109
+ def get_error_entries(log_text: str, project_path: str):
110
+ """Find file(line,col) triplets."""
111
+ entries = []
112
+ if not log_text:
113
+ return entries
114
+ for match in FILE_REGEX.finditer(log_text):
115
+ rel, line, col = match.groups()
116
+ full = rel if os.path.isabs(rel) else os.path.normpath(os.path.join(project_path, rel))
117
+ try:
118
+ entries.append((full, int(line), int(col)))
119
+ except Exception:
120
+ continue
121
+ return entries
122
+
123
+ def get_file_error_entries(log_text: str, project_path: str):
124
+ entries = []
125
+ if not log_text:
126
+ return entries
127
+ for m in FILE_FILE_REGEX.finditer(log_text):
128
+ rel = m.group('file')
129
+ line = m.group('l1') or m.group('l2')
130
+ col = m.group('c1') or m.group('c2')
131
+ full = rel if os.path.isabs(rel) else os.path.normpath(os.path.join(project_path, rel))
132
+ try:
133
+ entries.append((full, int(line), int(col)))
134
+ except Exception:
135
+ continue
136
+ return entries
137
+
138
+ def get_entries_for(text: str, project_path: str):
139
+ """Use file(line,col) extractor on a subset."""
140
+ return get_error_entries(text, project_path)
141
+
142
+ #imports
143
+ def grep_use_imports(project_path: str):
144
+ """Fallback: grep for suspect 'use' imports in src. Returns list[(path,line,1)]."""
145
+ results = []
146
+ try:
147
+ proc = subprocess.run(
148
+ ["grep", "-RnE", GREP_REGEX, "src"],
149
+ cwd=project_path,
150
+ capture_output=True, text=True
151
+ )
152
+ for ln in proc.stdout.splitlines():
153
+ try:
154
+ file, lineno, _ = ln.split(':', 2)
155
+ results.append((os.path.join(project_path, file), int(lineno), 1))
156
+ except Exception:
157
+ continue
158
+ except Exception:
159
+ pass
160
+ return results
161
+
162
+ #cmd utils
163
+ def run_ssh_cmd(user_at_host: str, cmd: str, path: str) -> str:
164
+ """Run on remote via SSH and return stdout+stderr."""
165
+ try:
166
+ full = f"ssh {user_at_host} 'cd {path} && bash -lc {sh_quote(cmd)}'"
167
+ proc = subprocess.run(full, shell=True, capture_output=True, text=True)
168
+ return (proc.stdout or "") + (proc.stderr or "")
169
+ except Exception as e:
170
+ return f"❌ run_ssh_cmd error: {e}\n"
171
+
172
+
173
+ def run_local_cmd(cmd: str, path: str) -> str:
174
+ """Run locally in cwd=path and return stdout+stderr."""
175
+ try:
176
+ proc = subprocess.run(["bash", "-lc", cmd], cwd=path, capture_output=True, text=True)
177
+ return (proc.stdout or "") + (proc.stderr or "")
178
+ except Exception as e:
179
+ return f"❌ run_local_cmd error: {e}\n"
180
+
181
+
182
+
183
+
184
+
@@ -0,0 +1 @@
1
+ from .utils import *
@@ -0,0 +1,2 @@
1
+ from .imports import *
2
+ from .widget_funcs import *
@@ -0,0 +1 @@
1
+ from ...widgets import *
@@ -0,0 +1,38 @@
1
+ from ..imports import *
2
+ def get_args_kwargs(*args,**kwargs):
3
+ return args,kwargs
4
+ def addWidgets(layout,addFunc, *args, **kwargs):
5
+ addFunc = getattr(layout, addFunc)
6
+ for arg in args:
7
+ if isinstance(arg, tuple) and len(arg) == 2 and isinstance(arg[1], dict):
8
+ widget, options = arg
9
+ if isinstance(widget, str):
10
+ widget = QLabel(widget)
11
+ addFunc(widget, **options)
12
+ elif isinstance(arg, str):
13
+ widget = QLabel(arg)
14
+ addFunc(widget, **kwargs)
15
+ else:
16
+ addFunc(arg, **kwargs)
17
+ def createLayout(label,widgetFunc,addFunc,*args,**kwargs):
18
+ layout = widgetFunc()
19
+ label = QLabel(label)
20
+ args = (label,*args)
21
+ addWidgets(layout,addFunc,*args,**kwargs)
22
+ return layout
23
+
24
+ def createWidget(layout, label, widgetFunc, addFunc, getLayout, widgets, addSubFunc='addLayout'):
25
+ sublayout = createLayout(label, widgetFunc, addFunc, **getLayout)
26
+ addWidgets(sublayout, addFunc, *widgets)
27
+ if layout is not None:
28
+ add_sub_method = getattr(layout, addSubFunc)
29
+ add_sub_method(sublayout)
30
+ return sublayout
31
+
32
+ def add_func(tabs,addFunc,*args,**kwargs):
33
+ add_sub_method = getattr(tabs, addFunc)
34
+ add_sub_method(*args,**kwargs)
35
+ def add_tab(tabs,**kwargs):
36
+ tabs.addTab(**kwargs)
37
+ def add_layout(layout,*args,**kwargs):
38
+ add_func(layout,'addLayout',*args,**kwargs)
@@ -0,0 +1,3 @@
1
+ from .importGraphWorker import *
2
+ from .mainWindow import *
3
+ from .worker import *