test-pioneer-dev 0.0.36__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.
- test_pioneer_dev-0.0.36/LICENSE +21 -0
- test_pioneer_dev-0.0.36/PKG-INFO +28 -0
- test_pioneer_dev-0.0.36/README.md +2 -0
- test_pioneer_dev-0.0.36/pyproject.toml +43 -0
- test_pioneer_dev-0.0.36/setup.cfg +4 -0
- test_pioneer_dev-0.0.36/test_pioneer/__init__.py +3 -0
- test_pioneer_dev-0.0.36/test_pioneer/__main__.py +19 -0
- test_pioneer_dev-0.0.36/test_pioneer/exception/__init__.py +0 -0
- test_pioneer_dev-0.0.36/test_pioneer/exception/exceptions.py +14 -0
- test_pioneer_dev-0.0.36/test_pioneer/exception/tags.py +3 -0
- test_pioneer_dev-0.0.36/test_pioneer/executor/__init__.py +0 -0
- test_pioneer_dev-0.0.36/test_pioneer/executor/pioneer_executor.py +228 -0
- test_pioneer_dev-0.0.36/test_pioneer/logging/__init__.py +0 -0
- test_pioneer_dev-0.0.36/test_pioneer/logging/loggin_instance.py +28 -0
- test_pioneer_dev-0.0.36/test_pioneer/process/__init__.py +0 -0
- test_pioneer_dev-0.0.36/test_pioneer/process/execute_process.py +48 -0
- test_pioneer_dev-0.0.36/test_pioneer/process/process_manager.py +25 -0
- test_pioneer_dev-0.0.36/test_pioneer/project/__init__.py +0 -0
- test_pioneer_dev-0.0.36/test_pioneer/project/create_project_structure.py +42 -0
- test_pioneer_dev-0.0.36/test_pioneer/project/template/__init__.py +0 -0
- test_pioneer_dev-0.0.36/test_pioneer/project/template/template.py +14 -0
- test_pioneer_dev-0.0.36/test_pioneer_dev.egg-info/PKG-INFO +28 -0
- test_pioneer_dev-0.0.36/test_pioneer_dev.egg-info/SOURCES.txt +24 -0
- test_pioneer_dev-0.0.36/test_pioneer_dev.egg-info/dependency_links.txt +1 -0
- test_pioneer_dev-0.0.36/test_pioneer_dev.egg-info/requires.txt +7 -0
- test_pioneer_dev-0.0.36/test_pioneer_dev.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 JE-Chen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: test_pioneer_dev
|
|
3
|
+
Version: 0.0.36
|
|
4
|
+
Summary: AutomationEditor for multi automation
|
|
5
|
+
Author-email: JE-Chen <jechenmailman@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Integration-Automation/TestPioneer
|
|
8
|
+
Project-URL: Code, https://github.com/Integration-Automation/TestPioneer
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
11
|
+
Classifier: Environment :: Win32 (MS Windows)
|
|
12
|
+
Classifier: Environment :: MacOS X
|
|
13
|
+
Classifier: Environment :: X11 Applications
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: je_auto_control
|
|
20
|
+
Requires-Dist: je_web_runner
|
|
21
|
+
Requires-Dist: je_load_density
|
|
22
|
+
Requires-Dist: je_api_testka
|
|
23
|
+
Requires-Dist: je-mail-thunder
|
|
24
|
+
Requires-Dist: automation-file
|
|
25
|
+
Requires-Dist: psutil
|
|
26
|
+
|
|
27
|
+
# TestPioneer
|
|
28
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Rename to build stable version
|
|
2
|
+
# This is stable version
|
|
3
|
+
[build-system]
|
|
4
|
+
requires = ["setuptools>=61.0"]
|
|
5
|
+
build-backend = "setuptools.build_meta"
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "test_pioneer_dev"
|
|
9
|
+
version = "0.0.36"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "JE-Chen", email = "jechenmailman@gmail.com" },
|
|
12
|
+
]
|
|
13
|
+
description = "AutomationEditor for multi automation"
|
|
14
|
+
requires-python = ">=3.9"
|
|
15
|
+
license = { text = "MIT" }
|
|
16
|
+
dependencies = [
|
|
17
|
+
"je_auto_control", "je_web_runner",
|
|
18
|
+
"je_load_density", "je_api_testka", "je-mail-thunder",
|
|
19
|
+
"automation-file", "psutil"
|
|
20
|
+
]
|
|
21
|
+
classifiers = [
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
24
|
+
"Environment :: Win32 (MS Windows)",
|
|
25
|
+
"Environment :: MacOS X",
|
|
26
|
+
"Environment :: X11 Applications",
|
|
27
|
+
"License :: OSI Approved :: MIT License",
|
|
28
|
+
"Operating System :: OS Independent"
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/Integration-Automation/TestPioneer"
|
|
33
|
+
Code = "https://github.com/Integration-Automation/TestPioneer"
|
|
34
|
+
|
|
35
|
+
[project.readme]
|
|
36
|
+
file = "README.md"
|
|
37
|
+
content-type = "text/markdown"
|
|
38
|
+
|
|
39
|
+
[tool.setuptools]
|
|
40
|
+
license-files = ["LICENSE"]
|
|
41
|
+
|
|
42
|
+
[tool.setuptools.packages]
|
|
43
|
+
find = { namespaces = false }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
from test_pioneer import execute_yaml
|
|
4
|
+
from test_pioneer.exception.exceptions import ExecutorException
|
|
5
|
+
|
|
6
|
+
if __name__ == "__main__":
|
|
7
|
+
parser = argparse.ArgumentParser()
|
|
8
|
+
|
|
9
|
+
parser.add_argument(
|
|
10
|
+
"-e", "--execute_yaml",
|
|
11
|
+
type=str, help="choose yaml file to execute"
|
|
12
|
+
)
|
|
13
|
+
args = parser.parse_args()
|
|
14
|
+
args = vars(args)
|
|
15
|
+
if args.get("execute_yaml"):
|
|
16
|
+
execute_yaml(args.get("execute_yaml"))
|
|
17
|
+
else:
|
|
18
|
+
raise ExecutorException(
|
|
19
|
+
f"execute_yaml have no argument right way to use: python -m test_pioneer. -e filepath")
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import time
|
|
3
|
+
import webbrowser
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Union, Tuple
|
|
6
|
+
|
|
7
|
+
import je_load_density
|
|
8
|
+
import je_api_testka
|
|
9
|
+
import je_auto_control
|
|
10
|
+
import je_web_runner
|
|
11
|
+
import yaml
|
|
12
|
+
|
|
13
|
+
from test_pioneer.exception.exceptions import WrongInputException, YamlException, ExecutorException
|
|
14
|
+
from test_pioneer.logging.loggin_instance import TestPioneerHandler, step_log_check, test_pioneer_logger
|
|
15
|
+
from test_pioneer.process.execute_process import ExecuteProcess
|
|
16
|
+
from test_pioneer.process.process_manager import process_manager_instance
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def check_with(step: dict, enable_logging: bool) -> Tuple[bool,
|
|
20
|
+
Union[je_auto_control.execute_files, je_web_runner.execute_files,
|
|
21
|
+
je_api_testka.execute_files, je_load_density.execute_files, None]]:
|
|
22
|
+
if step.get("with", None) is None:
|
|
23
|
+
step_log_check(
|
|
24
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
25
|
+
message=f"Step need with tag")
|
|
26
|
+
return False, None
|
|
27
|
+
with_tag = step.get("with")
|
|
28
|
+
if not isinstance(with_tag, str):
|
|
29
|
+
step_log_check(
|
|
30
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
31
|
+
message=f"The 'with' parameter is not an str type: {with_tag}")
|
|
32
|
+
return False, None
|
|
33
|
+
try:
|
|
34
|
+
step_log_check(
|
|
35
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="info",
|
|
36
|
+
message=f"Run with: {step.get('with')}, path: {step.get('run')}")
|
|
37
|
+
execute_with = {
|
|
38
|
+
"gui-runner": je_auto_control.execute_files,
|
|
39
|
+
"web-runner": je_web_runner.execute_files,
|
|
40
|
+
"api-runner": je_api_testka.execute_files,
|
|
41
|
+
"load-runner": je_load_density.execute_files
|
|
42
|
+
}.get(with_tag)
|
|
43
|
+
if execute_with is None:
|
|
44
|
+
step_log_check(
|
|
45
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
46
|
+
message=f"with using the wrong runner tag: {step.get('with')}")
|
|
47
|
+
return False, None
|
|
48
|
+
except ExecutorException as error:
|
|
49
|
+
step_log_check(
|
|
50
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
51
|
+
message=f"Run with: {step.get('with')}, path: {step.get('run')}, error: {repr(error)}")
|
|
52
|
+
return False, None
|
|
53
|
+
return True, execute_with
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def execute_yaml(stream: str, yaml_type: str = "File"):
|
|
57
|
+
if yaml_type == "File":
|
|
58
|
+
file = open(stream, "r").read()
|
|
59
|
+
yaml_data = yaml.safe_load(stream=file)
|
|
60
|
+
elif yaml_type == "String":
|
|
61
|
+
yaml_data = yaml.safe_load(stream=stream)
|
|
62
|
+
else:
|
|
63
|
+
raise WrongInputException("Wrong input: " + repr(stream))
|
|
64
|
+
# Variable
|
|
65
|
+
enable_logging: bool = False
|
|
66
|
+
# Pre check
|
|
67
|
+
if isinstance(yaml_data, dict) is False:
|
|
68
|
+
raise YamlException(f"Not a dict: {yaml_data}")
|
|
69
|
+
if "pioneer_log" in yaml_data.keys():
|
|
70
|
+
enable_logging = True
|
|
71
|
+
filename = yaml_data.get("pioneer_log")
|
|
72
|
+
file_handler = TestPioneerHandler(filename=filename)
|
|
73
|
+
test_pioneer_logger.addHandler(file_handler)
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
|
|
77
|
+
if "jobs" not in yaml_data.keys():
|
|
78
|
+
raise YamlException("No jobs tag")
|
|
79
|
+
if isinstance(yaml_data.get("jobs"), dict) is False:
|
|
80
|
+
raise YamlException("jobs not a dict")
|
|
81
|
+
steps = yaml_data.get("jobs").get("steps", None)
|
|
82
|
+
if steps is None or len(steps) <= 0:
|
|
83
|
+
raise YamlException("Steps tag is empty")
|
|
84
|
+
|
|
85
|
+
pre_check_failed: bool = False
|
|
86
|
+
|
|
87
|
+
# Pre-check name have duplicate or not
|
|
88
|
+
for step in steps:
|
|
89
|
+
if step.get("name", None) is None:
|
|
90
|
+
step_log_check(
|
|
91
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
92
|
+
message=f"Step need name tag")
|
|
93
|
+
break
|
|
94
|
+
name = step.get("name")
|
|
95
|
+
if name in process_manager_instance.name_set:
|
|
96
|
+
step_log_check(
|
|
97
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
98
|
+
message=f"job name duplicated: {name}")
|
|
99
|
+
pre_check_failed = True
|
|
100
|
+
break
|
|
101
|
+
else:
|
|
102
|
+
process_manager_instance.name_set.add(name)
|
|
103
|
+
|
|
104
|
+
for step in steps:
|
|
105
|
+
if pre_check_failed:
|
|
106
|
+
break
|
|
107
|
+
name = step.get("name")
|
|
108
|
+
|
|
109
|
+
if "run" in step.keys():
|
|
110
|
+
check_with_data = check_with(step, enable_logging=enable_logging)
|
|
111
|
+
if check_with_data[0] is False:
|
|
112
|
+
break
|
|
113
|
+
else:
|
|
114
|
+
execute_with = check_with_data[1]
|
|
115
|
+
file = step.get("run")
|
|
116
|
+
if file is None:
|
|
117
|
+
step_log_check(
|
|
118
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
119
|
+
message=f"run param need file path: {step.get('run')}")
|
|
120
|
+
break
|
|
121
|
+
if Path(file).is_file() is False and Path(file).is_dir() is False:
|
|
122
|
+
step_log_check(
|
|
123
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
124
|
+
message=f"not file path or dir: {step.get('run')}")
|
|
125
|
+
break
|
|
126
|
+
execute_with(file)
|
|
127
|
+
|
|
128
|
+
if "open_url" in step.keys():
|
|
129
|
+
if not isinstance(step.get("open_url"), str):
|
|
130
|
+
step_log_check(
|
|
131
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
132
|
+
message=f"The 'open_url' parameter is not an str type: {step.get('open_url')}")
|
|
133
|
+
break
|
|
134
|
+
step_log_check(
|
|
135
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="info",
|
|
136
|
+
message=f"Open url: {step.get('open_url')}")
|
|
137
|
+
try:
|
|
138
|
+
open_url = step.get("open_url")
|
|
139
|
+
url_open_method = step.get("url_open_method")
|
|
140
|
+
url_open_method = {
|
|
141
|
+
"open": webbrowser.open,
|
|
142
|
+
"open_new": webbrowser.open_new,
|
|
143
|
+
"open_new_tab": webbrowser.open_new_tab,
|
|
144
|
+
}.get(url_open_method)
|
|
145
|
+
if url_open_method is None:
|
|
146
|
+
step_log_check(
|
|
147
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
148
|
+
message=f"Using wrong url_open_method tag: {step.get('with')}")
|
|
149
|
+
break
|
|
150
|
+
url_open_method(url=open_url)
|
|
151
|
+
except ExecutorException as error:
|
|
152
|
+
step_log_check(
|
|
153
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
154
|
+
message=f"Open URL {step.get('open_url')}, error: {repr(error)}")
|
|
155
|
+
|
|
156
|
+
if "wait" in step.keys():
|
|
157
|
+
if not isinstance(step.get("wait"), int):
|
|
158
|
+
step_log_check(
|
|
159
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="info",
|
|
160
|
+
message=f"The 'wait' parameter is not an int type: {step.get('wait')}")
|
|
161
|
+
break
|
|
162
|
+
step_log_check(
|
|
163
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="info",
|
|
164
|
+
message=f"Wait seconds: {step.get('wait')}")
|
|
165
|
+
time.sleep((step.get("wait")))
|
|
166
|
+
|
|
167
|
+
if "open_program" in step.keys():
|
|
168
|
+
if not isinstance(step.get("open_program"), str):
|
|
169
|
+
step_log_check(
|
|
170
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
171
|
+
message=f"The 'open_program' parameter is not an str type: {step.get('open_program')}")
|
|
172
|
+
break
|
|
173
|
+
step_log_check(
|
|
174
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="info",
|
|
175
|
+
message=f"Open program: {step.get('open_program')}")
|
|
176
|
+
|
|
177
|
+
redirect_stdout = None
|
|
178
|
+
redirect_error = None
|
|
179
|
+
|
|
180
|
+
if "redirect_stdout" in step.keys():
|
|
181
|
+
if not isinstance(step.get("redirect_stdout"), str):
|
|
182
|
+
step_log_check(
|
|
183
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
184
|
+
message=f"The 'redirect_stdout' parameter is not an str type: {step.get('redirect_stdout')}")
|
|
185
|
+
break
|
|
186
|
+
step_log_check(
|
|
187
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="info",
|
|
188
|
+
message=f"Redirect stdout to: {step.get('redirect_stdout')}")
|
|
189
|
+
redirect_stdout = step.get("redirect_stdout")
|
|
190
|
+
|
|
191
|
+
if "redirect_stderr" in step.keys():
|
|
192
|
+
if not isinstance(step.get("redirect_stderr"), str):
|
|
193
|
+
step_log_check(
|
|
194
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
195
|
+
message=f"The 'redirect_stderr' parameter is not an str type: {step.get('redirect_stderr')}")
|
|
196
|
+
break
|
|
197
|
+
step_log_check(
|
|
198
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="info",
|
|
199
|
+
message=f"Redirect stderr to: {step.get('redirect_stderr')}")
|
|
200
|
+
redirect_error = step.get("redirect_stdout")
|
|
201
|
+
|
|
202
|
+
execute_process = ExecuteProcess()
|
|
203
|
+
process_manager_instance.process_dict.update({name: execute_process})
|
|
204
|
+
|
|
205
|
+
if redirect_error:
|
|
206
|
+
execute_process.redirect_stdout = redirect_stdout
|
|
207
|
+
|
|
208
|
+
if redirect_error:
|
|
209
|
+
execute_process.redirect_stderr = redirect_error
|
|
210
|
+
|
|
211
|
+
execute_process.start_process(step.get("open_program"))
|
|
212
|
+
|
|
213
|
+
if "close_program" in step.keys():
|
|
214
|
+
if not isinstance(step.get("close_program"), str):
|
|
215
|
+
step_log_check(
|
|
216
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
217
|
+
message=f"The 'close_program' parameter is not an str type: {step.get('close_program')}")
|
|
218
|
+
break
|
|
219
|
+
step_log_check(
|
|
220
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="info",
|
|
221
|
+
message=f"Close program: {step.get('close_program')}")
|
|
222
|
+
close_program = step.get("close_program")
|
|
223
|
+
process_manager_instance.close_process(close_program)
|
|
224
|
+
except Exception as error:
|
|
225
|
+
step_log_check(
|
|
226
|
+
enable_logging=enable_logging, logger=test_pioneer_logger, level="error",
|
|
227
|
+
message=f"Error: {repr(error)}")
|
|
228
|
+
raise error
|
|
File without changes
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from logging.handlers import RotatingFileHandler
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class TestPioneerHandler(RotatingFileHandler):
|
|
6
|
+
|
|
7
|
+
def __init__(self, filename: str = "TestPioneer.log", mode="w",
|
|
8
|
+
maxBytes: int = 1073741824, backupCount: int = 0):
|
|
9
|
+
super().__init__(filename=filename, mode=mode, maxBytes=maxBytes, backupCount=backupCount)
|
|
10
|
+
self.formatter = logging.Formatter('%(asctime)s | %(name)s | %(levelname)s | %(message)s')
|
|
11
|
+
self.setLevel(logging.DEBUG)
|
|
12
|
+
logging.root.setLevel(logging.DEBUG)
|
|
13
|
+
|
|
14
|
+
def emit(self, record: logging.LogRecord) -> None:
|
|
15
|
+
super().emit(record)
|
|
16
|
+
|
|
17
|
+
test_pioneer_logger = logging.getLogger("TestPioneer")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def step_log_check(enable_logging: bool = False, logger: logging.Logger = None,
|
|
21
|
+
level: str = "info", message: str = None):
|
|
22
|
+
if enable_logging and logger:
|
|
23
|
+
logger_level = {
|
|
24
|
+
"info": logger.info,
|
|
25
|
+
"error": logger.error,
|
|
26
|
+
}.get(level, None)
|
|
27
|
+
if logger_level is not None:
|
|
28
|
+
logger_level(message)
|
|
File without changes
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import shlex
|
|
2
|
+
import subprocess
|
|
3
|
+
import sys
|
|
4
|
+
from typing import Union
|
|
5
|
+
|
|
6
|
+
import psutil
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ExecuteProcess(object):
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
redirect_stdout: Union[str, subprocess.PIPE] = subprocess.PIPE,
|
|
13
|
+
redirect_stderr: Union[str, subprocess.PIPE] = subprocess.PIPE,
|
|
14
|
+
):
|
|
15
|
+
super().__init__()
|
|
16
|
+
self.process: [subprocess.Popen, None] = None
|
|
17
|
+
self.redirect_stdout: str = redirect_stdout
|
|
18
|
+
self.redirect_stderr: str = redirect_stderr
|
|
19
|
+
|
|
20
|
+
def start_process(self, shell_command):
|
|
21
|
+
if sys.platform in ["win32", "cygwin", "msys"]:
|
|
22
|
+
args = shell_command
|
|
23
|
+
else:
|
|
24
|
+
args = shlex.split(shell_command)
|
|
25
|
+
if self.redirect_stdout:
|
|
26
|
+
stdout_file = open(self.redirect_stdout, "w")
|
|
27
|
+
else:
|
|
28
|
+
stdout_file = subprocess.PIPE
|
|
29
|
+
if self.redirect_stderr:
|
|
30
|
+
stderr_file = open(self.redirect_stderr, "w")
|
|
31
|
+
else:
|
|
32
|
+
stderr_file = subprocess.PIPE
|
|
33
|
+
self.process = subprocess.Popen(
|
|
34
|
+
args=args,
|
|
35
|
+
stdout=stdout_file,
|
|
36
|
+
stderr=stderr_file,
|
|
37
|
+
shell=True,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# exit program change run flag to false and clean read thread and queue and process
|
|
41
|
+
def exit_program(self):
|
|
42
|
+
try:
|
|
43
|
+
process = psutil.Process(self.process.pid)
|
|
44
|
+
for proc in process.children(recursive=True):
|
|
45
|
+
proc.kill()
|
|
46
|
+
process.kill()
|
|
47
|
+
except psutil.NoSuchProcess:
|
|
48
|
+
pass
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Set, Dict, TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from test_pioneer.logging.loggin_instance import test_pioneer_logger
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from test_pioneer.process.execute_process import ExecuteProcess
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ProcessManager(object):
|
|
12
|
+
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self.name_set: Set[str] = set()
|
|
15
|
+
self.process_dict: Dict[str, ExecuteProcess] = dict()
|
|
16
|
+
|
|
17
|
+
def close_process(self, job_name):
|
|
18
|
+
execute_process = self.process_dict.get(job_name, None)
|
|
19
|
+
if execute_process is None:
|
|
20
|
+
test_pioneer_logger.error(f"Process not found {job_name}")
|
|
21
|
+
else:
|
|
22
|
+
execute_process.exit_program()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
process_manager_instance = ProcessManager()
|
|
File without changes
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from threading import Lock
|
|
3
|
+
|
|
4
|
+
from test_pioneer.exception.exceptions import ProjectException
|
|
5
|
+
from test_pioneer.exception.tags import cant_save_yaml_error
|
|
6
|
+
from test_pioneer.logging.loggin_instance import test_pioneer_logger
|
|
7
|
+
from test_pioneer.project.template.template import template_1_str
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def create_dir(dir_name: str) -> None:
|
|
11
|
+
"""
|
|
12
|
+
:param dir_name: create dir use dir name
|
|
13
|
+
:return: None
|
|
14
|
+
"""
|
|
15
|
+
Path(dir_name).mkdir(
|
|
16
|
+
parents=True,
|
|
17
|
+
exist_ok=True
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def create_template(parent_name: str, project_path: str = None) -> None:
|
|
22
|
+
if project_path is None:
|
|
23
|
+
project_path: str = str(Path.cwd())
|
|
24
|
+
template_dir = Path(project_path + "/" + parent_name)
|
|
25
|
+
lock = Lock()
|
|
26
|
+
if template_dir.exists() and template_dir.is_dir():
|
|
27
|
+
lock.acquire()
|
|
28
|
+
try:
|
|
29
|
+
with open(str(template_dir) + "/" + parent_name + ".yml", "w+") as file_to_write:
|
|
30
|
+
file_to_write.write(template_1_str)
|
|
31
|
+
except ProjectException:
|
|
32
|
+
raise ProjectException(cant_save_yaml_error)
|
|
33
|
+
finally:
|
|
34
|
+
lock.release()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def create_template_dir(project_path: str = None, parent_name: str = ".TestPioneer") -> None:
|
|
38
|
+
test_pioneer_logger.info(f"create_template_dir, project_path: {project_path}, parent_name: {parent_name}")
|
|
39
|
+
if project_path is None:
|
|
40
|
+
project_path: str = str(Path.cwd())
|
|
41
|
+
create_dir(project_path + "/" + parent_name)
|
|
42
|
+
create_template(parent_name)
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
template_1_str: str = \
|
|
2
|
+
"""
|
|
3
|
+
pioneer_log: "test_pioneer.log"
|
|
4
|
+
jobs:
|
|
5
|
+
steps:
|
|
6
|
+
- name: run_test_script_1
|
|
7
|
+
run: test/test1.json
|
|
8
|
+
with: gui-runner
|
|
9
|
+
- name: wait_seconds
|
|
10
|
+
wait: 5
|
|
11
|
+
- name: run_test_script_1
|
|
12
|
+
run: test/test1.json
|
|
13
|
+
with: gui-runner
|
|
14
|
+
"""
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: test_pioneer_dev
|
|
3
|
+
Version: 0.0.36
|
|
4
|
+
Summary: AutomationEditor for multi automation
|
|
5
|
+
Author-email: JE-Chen <jechenmailman@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Integration-Automation/TestPioneer
|
|
8
|
+
Project-URL: Code, https://github.com/Integration-Automation/TestPioneer
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
11
|
+
Classifier: Environment :: Win32 (MS Windows)
|
|
12
|
+
Classifier: Environment :: MacOS X
|
|
13
|
+
Classifier: Environment :: X11 Applications
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: je_auto_control
|
|
20
|
+
Requires-Dist: je_web_runner
|
|
21
|
+
Requires-Dist: je_load_density
|
|
22
|
+
Requires-Dist: je_api_testka
|
|
23
|
+
Requires-Dist: je-mail-thunder
|
|
24
|
+
Requires-Dist: automation-file
|
|
25
|
+
Requires-Dist: psutil
|
|
26
|
+
|
|
27
|
+
# TestPioneer
|
|
28
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
test_pioneer/__init__.py
|
|
5
|
+
test_pioneer/__main__.py
|
|
6
|
+
test_pioneer/exception/__init__.py
|
|
7
|
+
test_pioneer/exception/exceptions.py
|
|
8
|
+
test_pioneer/exception/tags.py
|
|
9
|
+
test_pioneer/executor/__init__.py
|
|
10
|
+
test_pioneer/executor/pioneer_executor.py
|
|
11
|
+
test_pioneer/logging/__init__.py
|
|
12
|
+
test_pioneer/logging/loggin_instance.py
|
|
13
|
+
test_pioneer/process/__init__.py
|
|
14
|
+
test_pioneer/process/execute_process.py
|
|
15
|
+
test_pioneer/process/process_manager.py
|
|
16
|
+
test_pioneer/project/__init__.py
|
|
17
|
+
test_pioneer/project/create_project_structure.py
|
|
18
|
+
test_pioneer/project/template/__init__.py
|
|
19
|
+
test_pioneer/project/template/template.py
|
|
20
|
+
test_pioneer_dev.egg-info/PKG-INFO
|
|
21
|
+
test_pioneer_dev.egg-info/SOURCES.txt
|
|
22
|
+
test_pioneer_dev.egg-info/dependency_links.txt
|
|
23
|
+
test_pioneer_dev.egg-info/requires.txt
|
|
24
|
+
test_pioneer_dev.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
test_pioneer
|