qlever 0.5.20__py3-none-any.whl → 0.5.22__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of qlever might be problematic. Click here for more details.
- qlever/__init__.py +17 -10
- qlever/command.py +1 -1
- qlever/commands/cache_stats.py +2 -2
- qlever/commands/clear_cache.py +30 -20
- qlever/commands/example_queries.py +40 -13
- qlever/commands/index.py +2 -10
- qlever/commands/query.py +2 -2
- qlever/commands/settings.py +1 -0
- qlever/commands/start.py +6 -26
- qlever/commands/stop.py +17 -41
- qlever/commands/ui.py +178 -26
- qlever/config.py +13 -6
- qlever/containerize.py +9 -4
- qlever/qlever_main.py +9 -4
- qlever/qleverfile.py +59 -5
- qlever/util.py +89 -4
- {qlever-0.5.20.dist-info → qlever-0.5.22.dist-info}/METADATA +6 -4
- {qlever-0.5.20.dist-info → qlever-0.5.22.dist-info}/RECORD +22 -23
- {qlever-0.5.20.dist-info → qlever-0.5.22.dist-info}/WHEEL +1 -1
- {qlever-0.5.20.dist-info → qlever-0.5.22.dist-info}/entry_points.txt +0 -1
- qlever/qlever_old.py +0 -1715
- {qlever-0.5.20.dist-info → qlever-0.5.22.dist-info/licenses}/LICENSE +0 -0
- {qlever-0.5.20.dist-info → qlever-0.5.22.dist-info}/top_level.txt +0 -0
qlever/__init__.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
|
+
from importlib import import_module
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
|
|
6
7
|
|
|
@@ -10,9 +11,19 @@ def snake_to_camel(str):
|
|
|
10
11
|
return "".join([w.capitalize() for w in str.replace("-", "_").split("_")])
|
|
11
12
|
|
|
12
13
|
|
|
14
|
+
# Get the name of the script (without the path and without the extension).
|
|
15
|
+
script_name = Path(sys.argv[0]).stem
|
|
16
|
+
|
|
17
|
+
ENGINE_NAMES = {
|
|
18
|
+
"qlever": "QLever",
|
|
19
|
+
"qmdb": "MillenniumDB",
|
|
20
|
+
}
|
|
21
|
+
# Default engine_name = script_name without starting 'q' and capitalized
|
|
22
|
+
engine_name = ENGINE_NAMES.get(script_name, script_name[1:].capitalize())
|
|
23
|
+
|
|
13
24
|
# Each module in `qlever/commands` corresponds to a command. The name
|
|
14
25
|
# of the command is the base name of the module file.
|
|
15
|
-
package_path = Path(__file__).parent
|
|
26
|
+
package_path = Path(__file__).parent.parent / script_name
|
|
16
27
|
command_names = [
|
|
17
28
|
Path(p).stem
|
|
18
29
|
for p in package_path.glob("commands/*.py")
|
|
@@ -22,19 +33,15 @@ command_names = [
|
|
|
22
33
|
# Dynamically load all the command classes and create an object for each.
|
|
23
34
|
command_objects = {}
|
|
24
35
|
for command_name in command_names:
|
|
25
|
-
module_path = f"
|
|
26
|
-
class_name = snake_to_camel(command_name) + "Command"
|
|
36
|
+
module_path = f"{script_name}.commands.{command_name}"
|
|
27
37
|
try:
|
|
28
|
-
module =
|
|
38
|
+
module = import_module(module_path)
|
|
29
39
|
except ImportError as e:
|
|
30
40
|
raise Exception(
|
|
31
|
-
f"Could not import
|
|
32
|
-
|
|
33
|
-
)
|
|
41
|
+
f"Could not import module {module_path} for {script_name}: {e}"
|
|
42
|
+
) from e
|
|
34
43
|
# Create an object of the class and store it in the dictionary. For the
|
|
35
44
|
# commands, take - instead of _.
|
|
45
|
+
class_name = snake_to_camel(command_name) + "Command"
|
|
36
46
|
command_class = getattr(module, class_name)
|
|
37
47
|
command_objects[command_name.replace("_", "-")] = command_class()
|
|
38
|
-
|
|
39
|
-
# Get the name of the script (without the path and without the extension).
|
|
40
|
-
script_name = Path(sys.argv[0]).stem
|
qlever/command.py
CHANGED
|
@@ -81,7 +81,7 @@ class QleverCommand(ABC):
|
|
|
81
81
|
log.info("")
|
|
82
82
|
if only_show:
|
|
83
83
|
log.info(
|
|
84
|
-
'You
|
|
84
|
+
'You passed the argument "--show", therefore the command '
|
|
85
85
|
'is only shown, but not executed (omit the "--show" to '
|
|
86
86
|
"execute it)"
|
|
87
87
|
)
|
qlever/commands/cache_stats.py
CHANGED
|
@@ -28,7 +28,7 @@ class CacheStatsCommand(QleverCommand):
|
|
|
28
28
|
def additional_arguments(self, subparser) -> None:
|
|
29
29
|
subparser.add_argument("--server-url",
|
|
30
30
|
help="URL of the QLever server, default is "
|
|
31
|
-
"
|
|
31
|
+
"{host_name}:{port}")
|
|
32
32
|
subparser.add_argument("--detailed",
|
|
33
33
|
action="store_true",
|
|
34
34
|
default=False,
|
|
@@ -37,7 +37,7 @@ class CacheStatsCommand(QleverCommand):
|
|
|
37
37
|
def execute(self, args) -> bool:
|
|
38
38
|
# Construct the two curl commands.
|
|
39
39
|
server_url = (args.server_url if args.server_url
|
|
40
|
-
else f"
|
|
40
|
+
else f"{args.host_name}:{args.port}")
|
|
41
41
|
cache_stats_cmd = (f"curl -s {server_url} "
|
|
42
42
|
f"--data-urlencode \"cmd=cache-stats\"")
|
|
43
43
|
cache_settings_cmd = (f"curl -s {server_url} "
|
qlever/commands/clear_cache.py
CHANGED
|
@@ -17,22 +17,25 @@ class ClearCacheCommand(QleverCommand):
|
|
|
17
17
|
pass
|
|
18
18
|
|
|
19
19
|
def description(self) -> str:
|
|
20
|
-
return
|
|
20
|
+
return "Clear the query processing cache"
|
|
21
21
|
|
|
22
22
|
def should_have_qleverfile(self) -> bool:
|
|
23
23
|
return True
|
|
24
24
|
|
|
25
|
-
def relevant_qleverfile_arguments(self) -> dict[str: list[str]]:
|
|
26
|
-
return {"server": ["port", "access_token"]}
|
|
25
|
+
def relevant_qleverfile_arguments(self) -> dict[str : list[str]]:
|
|
26
|
+
return {"server": ["host_name", "port", "access_token"]}
|
|
27
27
|
|
|
28
28
|
def additional_arguments(self, subparser) -> None:
|
|
29
|
-
subparser.add_argument(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
subparser.add_argument(
|
|
30
|
+
"--server-url",
|
|
31
|
+
help="URL of the QLever server, default is {host_name}:{port}",
|
|
32
|
+
)
|
|
33
|
+
subparser.add_argument(
|
|
34
|
+
"--complete",
|
|
35
|
+
action="store_true",
|
|
36
|
+
default=False,
|
|
37
|
+
help="Clear the cache completely, including the pinned queries",
|
|
38
|
+
)
|
|
36
39
|
|
|
37
40
|
def execute(self, args) -> bool:
|
|
38
41
|
# Construct command line and show it.
|
|
@@ -40,22 +43,27 @@ class ClearCacheCommand(QleverCommand):
|
|
|
40
43
|
if args.server_url:
|
|
41
44
|
clear_cache_cmd += f" {args.server_url}"
|
|
42
45
|
else:
|
|
43
|
-
clear_cache_cmd += f"
|
|
46
|
+
clear_cache_cmd += f" {args.host_name}:{args.port}"
|
|
44
47
|
cmd_val = "clear-cache-complete" if args.complete else "clear-cache"
|
|
45
|
-
clear_cache_cmd += f
|
|
48
|
+
clear_cache_cmd += f' --data-urlencode "cmd={cmd_val}"'
|
|
46
49
|
if args.complete:
|
|
47
|
-
clear_cache_cmd += (
|
|
48
|
-
|
|
50
|
+
clear_cache_cmd += (
|
|
51
|
+
f" --data-urlencode access-token=" f'"{args.access_token}"'
|
|
52
|
+
)
|
|
49
53
|
self.show(clear_cache_cmd, only_show=args.show)
|
|
50
54
|
if args.show:
|
|
51
55
|
return True
|
|
52
56
|
|
|
53
57
|
# Execute the command.
|
|
54
58
|
try:
|
|
55
|
-
clear_cache_cmd +=
|
|
56
|
-
result = subprocess.run(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
clear_cache_cmd += ' -w " %{http_code}"'
|
|
60
|
+
result = subprocess.run(
|
|
61
|
+
clear_cache_cmd,
|
|
62
|
+
shell=True,
|
|
63
|
+
capture_output=True,
|
|
64
|
+
text=True,
|
|
65
|
+
check=True,
|
|
66
|
+
).stdout
|
|
59
67
|
match = re.match(r"^(.*) (\d+)$", result, re.DOTALL)
|
|
60
68
|
if not match:
|
|
61
69
|
raise Exception(f"Unexpected output:\n{result}")
|
|
@@ -77,6 +85,8 @@ class ClearCacheCommand(QleverCommand):
|
|
|
77
85
|
log.info("")
|
|
78
86
|
args.detailed = False
|
|
79
87
|
if not CacheStatsCommand().execute(args):
|
|
80
|
-
log.error(
|
|
81
|
-
|
|
88
|
+
log.error(
|
|
89
|
+
"Clearing the cache was successful, but showing the "
|
|
90
|
+
"cache stats failed {e}"
|
|
91
|
+
)
|
|
82
92
|
return True
|
|
@@ -31,7 +31,7 @@ class ExampleQueriesCommand(QleverCommand):
|
|
|
31
31
|
return False
|
|
32
32
|
|
|
33
33
|
def relevant_qleverfile_arguments(self) -> dict[str : list[str]]:
|
|
34
|
-
return {"server": ["port"], "ui": ["ui_config"]}
|
|
34
|
+
return {"server": ["host_name", "port"], "ui": ["ui_config"]}
|
|
35
35
|
|
|
36
36
|
def additional_arguments(self, subparser) -> None:
|
|
37
37
|
subparser.add_argument(
|
|
@@ -103,8 +103,8 @@ class ExampleQueriesCommand(QleverCommand):
|
|
|
103
103
|
subparser.add_argument(
|
|
104
104
|
"--clear-cache",
|
|
105
105
|
choices=["yes", "no"],
|
|
106
|
-
default="
|
|
107
|
-
help="Clear the cache before each query",
|
|
106
|
+
default="no",
|
|
107
|
+
help="Clear the cache before each query (only works for QLever)",
|
|
108
108
|
)
|
|
109
109
|
subparser.add_argument(
|
|
110
110
|
"--width-query-description",
|
|
@@ -213,9 +213,18 @@ class ExampleQueriesCommand(QleverCommand):
|
|
|
213
213
|
not args.sparql_endpoint
|
|
214
214
|
or args.sparql_endpoint.startswith("https://qlever")
|
|
215
215
|
)
|
|
216
|
-
if args.clear_cache == "yes"
|
|
217
|
-
|
|
218
|
-
|
|
216
|
+
if args.clear_cache == "yes":
|
|
217
|
+
if is_qlever:
|
|
218
|
+
log.warning(
|
|
219
|
+
"Clearing the cache before each query"
|
|
220
|
+
" (only works for QLever)"
|
|
221
|
+
)
|
|
222
|
+
else:
|
|
223
|
+
log.warning(
|
|
224
|
+
"Clearing the cache only works for QLever"
|
|
225
|
+
", option `--clear-cache` is ignored"
|
|
226
|
+
)
|
|
227
|
+
args.clear_cache = "no"
|
|
219
228
|
|
|
220
229
|
# Show what the command will do.
|
|
221
230
|
get_queries_cmd = (
|
|
@@ -231,14 +240,12 @@ class ExampleQueriesCommand(QleverCommand):
|
|
|
231
240
|
sparql_endpoint = (
|
|
232
241
|
args.sparql_endpoint
|
|
233
242
|
if args.sparql_endpoint
|
|
234
|
-
else f"
|
|
243
|
+
else f"{args.host_name}:{args.port}"
|
|
235
244
|
)
|
|
236
245
|
self.show(
|
|
237
246
|
f"Obtain queries via: {get_queries_cmd}\n"
|
|
238
247
|
f"SPARQL endpoint: {sparql_endpoint}\n"
|
|
239
248
|
f"Accept header: {args.accept}\n"
|
|
240
|
-
f"Clear cache before each query:"
|
|
241
|
-
f" {args.clear_cache.upper()}\n"
|
|
242
249
|
f"Download result for each query or just count:"
|
|
243
250
|
f" {args.download_or_count.upper()}"
|
|
244
251
|
+ (f" with LIMIT {args.limit}" if args.limit else ""),
|
|
@@ -404,6 +411,7 @@ class ExampleQueriesCommand(QleverCommand):
|
|
|
404
411
|
# Get result size (via the command line, in order to avoid loading
|
|
405
412
|
# a potentially large JSON file into Python, which is slow).
|
|
406
413
|
if error_msg is None:
|
|
414
|
+
single_int_result = None
|
|
407
415
|
# CASE 0: The result is empty despite a 200 HTTP code (not a
|
|
408
416
|
# problem for CONSTRUCT and DESCRIBE queries).
|
|
409
417
|
if Path(result_file).stat().st_size == 0 and (
|
|
@@ -461,16 +469,29 @@ class ExampleQueriesCommand(QleverCommand):
|
|
|
461
469
|
)
|
|
462
470
|
else:
|
|
463
471
|
try:
|
|
464
|
-
result_size =
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
472
|
+
result_size = int(
|
|
473
|
+
run_command(
|
|
474
|
+
f'jq -r ".results.bindings | length"'
|
|
475
|
+
f" {result_file}",
|
|
476
|
+
return_output=True,
|
|
477
|
+
).rstrip()
|
|
468
478
|
)
|
|
469
479
|
except Exception as e:
|
|
470
480
|
error_msg = {
|
|
471
481
|
"short": "Malformed JSON",
|
|
472
482
|
"long": re.sub(r"\s+", " ", str(e)),
|
|
473
483
|
}
|
|
484
|
+
if result_size == 1:
|
|
485
|
+
try:
|
|
486
|
+
single_int_result = int(
|
|
487
|
+
run_command(
|
|
488
|
+
f'jq -e -r ".results.bindings[0][] | .value"'
|
|
489
|
+
f" {result_file}",
|
|
490
|
+
return_output=True,
|
|
491
|
+
).rstrip()
|
|
492
|
+
)
|
|
493
|
+
except Exception:
|
|
494
|
+
pass
|
|
474
495
|
|
|
475
496
|
# Remove the result file (unless in debug mode).
|
|
476
497
|
if args.log_level != "DEBUG":
|
|
@@ -485,10 +506,16 @@ class ExampleQueriesCommand(QleverCommand):
|
|
|
485
506
|
)
|
|
486
507
|
if error_msg is None:
|
|
487
508
|
result_size = int(result_size)
|
|
509
|
+
single_int_result = (
|
|
510
|
+
f" [single int result: {single_int_result:,}]"
|
|
511
|
+
if single_int_result is not None
|
|
512
|
+
else ""
|
|
513
|
+
)
|
|
488
514
|
log.info(
|
|
489
515
|
f"{description:<{width_query_description}} "
|
|
490
516
|
f"{time_seconds:6.2f} s "
|
|
491
517
|
f"{result_size:>{args.width_result_size},}"
|
|
518
|
+
f"{single_int_result}"
|
|
492
519
|
)
|
|
493
520
|
query_times.append(time_seconds)
|
|
494
521
|
result_sizes.append(result_size)
|
qlever/commands/index.py
CHANGED
|
@@ -9,6 +9,7 @@ from qlever.command import QleverCommand
|
|
|
9
9
|
from qlever.containerize import Containerize
|
|
10
10
|
from qlever.log import log
|
|
11
11
|
from qlever.util import (
|
|
12
|
+
binary_exists,
|
|
12
13
|
get_existing_index_files,
|
|
13
14
|
get_total_file_size,
|
|
14
15
|
run_command,
|
|
@@ -267,16 +268,7 @@ class IndexCommand(QleverCommand):
|
|
|
267
268
|
|
|
268
269
|
# When running natively, check if the binary exists and works.
|
|
269
270
|
if args.system == "native":
|
|
270
|
-
|
|
271
|
-
run_command(f"{args.index_binary} --help")
|
|
272
|
-
except Exception as e:
|
|
273
|
-
log.error(
|
|
274
|
-
f'Running "{args.index_binary}" failed, '
|
|
275
|
-
f"set `--index-binary` to a different binary or "
|
|
276
|
-
f"set `--system to a container system`"
|
|
277
|
-
)
|
|
278
|
-
log.info("")
|
|
279
|
-
log.info(f"The error message was: {e}")
|
|
271
|
+
if not binary_exists(args.index_binary, "index-binary"):
|
|
280
272
|
return False
|
|
281
273
|
|
|
282
274
|
# Check if all of the input files exist.
|
qlever/commands/query.py
CHANGED
|
@@ -38,7 +38,7 @@ class QueryCommand(QleverCommand):
|
|
|
38
38
|
return False
|
|
39
39
|
|
|
40
40
|
def relevant_qleverfile_arguments(self) -> dict[str : list[str]]:
|
|
41
|
-
return {"server": ["port", "access_token"]}
|
|
41
|
+
return {"server": ["host_name", "port", "access_token"]}
|
|
42
42
|
|
|
43
43
|
def additional_arguments(self, subparser) -> None:
|
|
44
44
|
subparser.add_argument(
|
|
@@ -109,7 +109,7 @@ class QueryCommand(QleverCommand):
|
|
|
109
109
|
sparql_endpoint = (
|
|
110
110
|
args.sparql_endpoint
|
|
111
111
|
if args.sparql_endpoint
|
|
112
|
-
else f"
|
|
112
|
+
else f"{args.host_name}:{args.port}"
|
|
113
113
|
)
|
|
114
114
|
curl_cmd = (
|
|
115
115
|
f"curl -s {sparql_endpoint}"
|
qlever/commands/settings.py
CHANGED
qlever/commands/start.py
CHANGED
|
@@ -10,7 +10,7 @@ from qlever.commands.stop import StopCommand
|
|
|
10
10
|
from qlever.commands.warmup import WarmupCommand
|
|
11
11
|
from qlever.containerize import Containerize
|
|
12
12
|
from qlever.log import log
|
|
13
|
-
from qlever.util import is_qlever_server_alive, run_command
|
|
13
|
+
from qlever.util import binary_exists, is_qlever_server_alive, run_command
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
# Construct the command line based on the config file.
|
|
@@ -30,6 +30,8 @@ def construct_command(args) -> str:
|
|
|
30
30
|
start_cmd += f" -s {args.timeout}"
|
|
31
31
|
if args.access_token:
|
|
32
32
|
start_cmd += f" -a {args.access_token}"
|
|
33
|
+
if args.persist_updates:
|
|
34
|
+
start_cmd += " --persist-updates"
|
|
33
35
|
if args.only_pso_and_pos_permutations:
|
|
34
36
|
start_cmd += " --only-pso-and-pos-permutations"
|
|
35
37
|
if not args.use_patterns:
|
|
@@ -69,22 +71,6 @@ def wrap_command_in_container(args, start_cmd) -> str:
|
|
|
69
71
|
return start_cmd
|
|
70
72
|
|
|
71
73
|
|
|
72
|
-
# When running natively, check if the binary exists and works.
|
|
73
|
-
def check_binary(binary) -> bool:
|
|
74
|
-
try:
|
|
75
|
-
run_command(f"{binary} --help")
|
|
76
|
-
return True
|
|
77
|
-
except Exception as e:
|
|
78
|
-
log.error(
|
|
79
|
-
f'Running "{binary}" failed, '
|
|
80
|
-
f"set `--server-binary` to a different binary or "
|
|
81
|
-
f"set `--system to a container system`"
|
|
82
|
-
)
|
|
83
|
-
log.info("")
|
|
84
|
-
log.info(f"The error message was: {e}")
|
|
85
|
-
return False
|
|
86
|
-
|
|
87
|
-
|
|
88
74
|
# Set the index description.
|
|
89
75
|
def set_index_description(access_arg, port, desc) -> bool:
|
|
90
76
|
curl_cmd = (
|
|
@@ -148,6 +134,7 @@ class StartCommand(QleverCommand):
|
|
|
148
134
|
"cache_max_num_entries",
|
|
149
135
|
"num_threads",
|
|
150
136
|
"timeout",
|
|
137
|
+
"persist_updates",
|
|
151
138
|
"only_pso_and_pos_permutations",
|
|
152
139
|
"use_patterns",
|
|
153
140
|
"use_text_index",
|
|
@@ -157,12 +144,6 @@ class StartCommand(QleverCommand):
|
|
|
157
144
|
}
|
|
158
145
|
|
|
159
146
|
def additional_arguments(self, subparser) -> None:
|
|
160
|
-
# subparser.add_argument("--kill-existing-with-same-name",
|
|
161
|
-
# action="store_true",
|
|
162
|
-
# default=False,
|
|
163
|
-
# help="If a QLever server is already running "
|
|
164
|
-
# "with the same name, kill it before "
|
|
165
|
-
# "starting a new server")
|
|
166
147
|
subparser.add_argument(
|
|
167
148
|
"--kill-existing-with-same-port",
|
|
168
149
|
action="store_true",
|
|
@@ -223,12 +204,11 @@ class StartCommand(QleverCommand):
|
|
|
223
204
|
|
|
224
205
|
# When running natively, check if the binary exists and works.
|
|
225
206
|
if args.system == "native":
|
|
226
|
-
|
|
227
|
-
if not ret:
|
|
207
|
+
if not binary_exists(args.server_binary, "server-binary"):
|
|
228
208
|
return False
|
|
229
209
|
|
|
230
210
|
# Check if a QLever server is already running on this port.
|
|
231
|
-
endpoint_url = f"http://
|
|
211
|
+
endpoint_url = f"http://{args.host_name}:{args.port}"
|
|
232
212
|
if is_qlever_server_alive(endpoint_url):
|
|
233
213
|
log.error(f"QLever server already running on {endpoint_url}")
|
|
234
214
|
log.info("")
|
qlever/commands/stop.py
CHANGED
|
@@ -1,37 +1,25 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import psutil
|
|
2
|
+
|
|
4
3
|
from qlever.command import QleverCommand
|
|
5
4
|
from qlever.commands.status import StatusCommand
|
|
6
5
|
from qlever.containerize import Containerize
|
|
7
6
|
from qlever.log import log
|
|
8
|
-
from qlever.util import
|
|
9
|
-
|
|
10
|
-
# try to kill the given process, return true iff it was killed successfully.
|
|
11
|
-
# the process_info is used for logging.
|
|
12
|
-
def stop_process(proc, pinfo):
|
|
13
|
-
try:
|
|
14
|
-
proc.kill()
|
|
15
|
-
log.info(f"Killed process {pinfo['pid']}")
|
|
16
|
-
return True
|
|
17
|
-
except Exception as e:
|
|
18
|
-
log.error(f"Could not kill process with PID "
|
|
19
|
-
f"{pinfo['pid']} ({e}) ... try to kill it "
|
|
20
|
-
f"manually")
|
|
21
|
-
log.info("")
|
|
22
|
-
show_process_info(proc, "", show_heading=True)
|
|
23
|
-
return False
|
|
7
|
+
from qlever.util import stop_process_with_regex
|
|
24
8
|
|
|
25
9
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
10
|
+
def stop_container(server_container: str) -> bool:
|
|
11
|
+
"""
|
|
12
|
+
Try to stop and remove container. return True iff it was stopped
|
|
13
|
+
successfully. Gives log info accordingly.
|
|
14
|
+
"""
|
|
29
15
|
for container_system in Containerize.supported_systems():
|
|
30
16
|
if Containerize.stop_and_remove_container(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
17
|
+
container_system, server_container
|
|
18
|
+
):
|
|
19
|
+
log.info(
|
|
20
|
+
f"{container_system.capitalize()} container with "
|
|
21
|
+
f'name "{server_container}" stopped and removed'
|
|
22
|
+
)
|
|
35
23
|
return True
|
|
36
24
|
return False
|
|
37
25
|
|
|
@@ -45,7 +33,7 @@ class StopCommand(QleverCommand):
|
|
|
45
33
|
pass
|
|
46
34
|
|
|
47
35
|
def description(self) -> str:
|
|
48
|
-
return "Stop QLever server for a given
|
|
36
|
+
return "Stop QLever server for a given dataset or port"
|
|
49
37
|
|
|
50
38
|
def should_have_qleverfile(self) -> bool:
|
|
51
39
|
return True
|
|
@@ -85,21 +73,9 @@ class StopCommand(QleverCommand):
|
|
|
85
73
|
# Check if there is a process running on the server port using psutil.
|
|
86
74
|
# NOTE: On MacOS, some of the proc's returned by psutil.process_iter()
|
|
87
75
|
# no longer exist when we try to access them, so we just skip them.
|
|
88
|
-
stop_process_results =
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
pinfo = proc.as_dict(
|
|
92
|
-
attrs=['pid', 'username', 'create_time',
|
|
93
|
-
'memory_info', 'cmdline'])
|
|
94
|
-
cmdline = " ".join(pinfo['cmdline'])
|
|
95
|
-
except Exception as e:
|
|
96
|
-
log.debug(f"Error getting process info: {e}")
|
|
97
|
-
return False
|
|
98
|
-
if re.search(cmdline_regex, cmdline):
|
|
99
|
-
log.info(f"Found process {pinfo['pid']} from user "
|
|
100
|
-
f"{pinfo['username']} with command line: {cmdline}")
|
|
101
|
-
log.info("")
|
|
102
|
-
stop_process_results.append(stop_process(proc, pinfo))
|
|
76
|
+
stop_process_results = stop_process_with_regex(cmdline_regex)
|
|
77
|
+
if stop_process_results is None:
|
|
78
|
+
return False
|
|
103
79
|
if len(stop_process_results) > 0:
|
|
104
80
|
return all(stop_process_results)
|
|
105
81
|
|