qlever 0.2.5__py3-none-any.whl → 0.5.41__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.
- qlever/Qleverfiles/Qleverfile.dblp +36 -0
- qlever/Qleverfiles/Qleverfile.dblp-plus +33 -0
- qlever/Qleverfiles/Qleverfile.dbpedia +30 -0
- qlever/Qleverfiles/Qleverfile.default +51 -0
- qlever/Qleverfiles/Qleverfile.dnb +40 -0
- qlever/Qleverfiles/Qleverfile.fbeasy +29 -0
- qlever/Qleverfiles/Qleverfile.freebase +28 -0
- qlever/Qleverfiles/Qleverfile.imdb +36 -0
- qlever/Qleverfiles/Qleverfile.ohm-planet +41 -0
- qlever/Qleverfiles/Qleverfile.olympics +31 -0
- qlever/Qleverfiles/Qleverfile.orkg +30 -0
- qlever/Qleverfiles/Qleverfile.osm-country +39 -0
- qlever/Qleverfiles/Qleverfile.osm-planet +39 -0
- qlever/Qleverfiles/Qleverfile.osm-planet-from-pbf +42 -0
- qlever/Qleverfiles/Qleverfile.pubchem +131 -0
- qlever/Qleverfiles/Qleverfile.scientists +29 -0
- qlever/Qleverfiles/Qleverfile.uniprot +74 -0
- qlever/Qleverfiles/Qleverfile.vvz +31 -0
- qlever/Qleverfiles/Qleverfile.wikidata +42 -0
- qlever/Qleverfiles/Qleverfile.wikipathways +40 -0
- qlever/Qleverfiles/Qleverfile.yago-4 +33 -0
- qlever/__init__.py +44 -1380
- qlever/command.py +87 -0
- qlever/commands/__init__.py +0 -0
- qlever/commands/add_text_index.py +115 -0
- qlever/commands/benchmark_queries.py +1019 -0
- qlever/commands/cache_stats.py +125 -0
- qlever/commands/clear_cache.py +88 -0
- qlever/commands/extract_queries.py +120 -0
- qlever/commands/get_data.py +48 -0
- qlever/commands/index.py +333 -0
- qlever/commands/index_stats.py +306 -0
- qlever/commands/log.py +66 -0
- qlever/commands/materialized_view.py +110 -0
- qlever/commands/query.py +142 -0
- qlever/commands/rebuild_index.py +176 -0
- qlever/commands/reset_updates.py +59 -0
- qlever/commands/settings.py +115 -0
- qlever/commands/setup_config.py +97 -0
- qlever/commands/start.py +336 -0
- qlever/commands/status.py +50 -0
- qlever/commands/stop.py +90 -0
- qlever/commands/system_info.py +130 -0
- qlever/commands/ui.py +271 -0
- qlever/commands/update.py +90 -0
- qlever/commands/update_wikidata.py +1204 -0
- qlever/commands/warmup.py +41 -0
- qlever/config.py +223 -0
- qlever/containerize.py +167 -0
- qlever/log.py +55 -0
- qlever/qlever_main.py +79 -0
- qlever/qleverfile.py +530 -0
- qlever/util.py +330 -0
- qlever-0.5.41.dist-info/METADATA +127 -0
- qlever-0.5.41.dist-info/RECORD +59 -0
- {qlever-0.2.5.dist-info → qlever-0.5.41.dist-info}/WHEEL +1 -1
- qlever-0.5.41.dist-info/entry_points.txt +2 -0
- qlever-0.5.41.dist-info/top_level.txt +1 -0
- build/lib/qlever/__init__.py +0 -1383
- build/lib/qlever/__main__.py +0 -4
- qlever/__main__.py +0 -4
- qlever-0.2.5.dist-info/METADATA +0 -277
- qlever-0.2.5.dist-info/RECORD +0 -12
- qlever-0.2.5.dist-info/entry_points.txt +0 -2
- qlever-0.2.5.dist-info/top_level.txt +0 -4
- src/qlever/__init__.py +0 -1383
- src/qlever/__main__.py +0 -4
- {qlever-0.2.5.dist-info → qlever-0.5.41.dist-info/licenses}/LICENSE +0 -0
qlever/util.py
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import errno
|
|
4
|
+
import re
|
|
5
|
+
import secrets
|
|
6
|
+
import shlex
|
|
7
|
+
import shutil
|
|
8
|
+
import socket
|
|
9
|
+
import string
|
|
10
|
+
import subprocess
|
|
11
|
+
from datetime import date, datetime
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Any, Optional
|
|
14
|
+
|
|
15
|
+
import psutil
|
|
16
|
+
|
|
17
|
+
from qlever.log import log
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_total_file_size(patterns: list[str]) -> int:
|
|
21
|
+
"""
|
|
22
|
+
Helper function that gets the total size of all files mathing the given
|
|
23
|
+
patterns in bytes.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
total_size = 0
|
|
27
|
+
search_dir = Path.cwd()
|
|
28
|
+
for pattern in patterns:
|
|
29
|
+
for file in search_dir.glob(pattern):
|
|
30
|
+
total_size += file.stat().st_size
|
|
31
|
+
return total_size
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def run_command(
|
|
35
|
+
cmd: str,
|
|
36
|
+
return_output: bool = False,
|
|
37
|
+
show_output: bool = False,
|
|
38
|
+
show_stderr: bool = False,
|
|
39
|
+
use_popen: bool = False,
|
|
40
|
+
) -> Optional[str | subprocess.Popen]:
|
|
41
|
+
"""
|
|
42
|
+
Run the given command and throw an exception if the exit code is non-zero.
|
|
43
|
+
If `return_output` is `True`, return what the command wrote to `stdout`.
|
|
44
|
+
|
|
45
|
+
NOTE: The `set -o pipefail` ensures that the exit code of the command is
|
|
46
|
+
non-zero if any part of the pipeline fails (not just the last part).
|
|
47
|
+
|
|
48
|
+
TODO: Find the executable for `bash` in `__init__.py`.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
subprocess_args = {
|
|
52
|
+
"executable": shutil.which("bash"),
|
|
53
|
+
"shell": True,
|
|
54
|
+
"text": True,
|
|
55
|
+
"stdout": None if show_output else subprocess.PIPE,
|
|
56
|
+
"stderr": None if show_stderr else subprocess.PIPE,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# With `Popen`, the command runs in the current shell and a process object
|
|
60
|
+
# is returned (which can be used, e.g., to kill the process).
|
|
61
|
+
if use_popen:
|
|
62
|
+
if return_output:
|
|
63
|
+
raise Exception("Cannot return output if `use_popen` is `True`")
|
|
64
|
+
return subprocess.Popen(f"set -o pipefail; {cmd}", **subprocess_args)
|
|
65
|
+
|
|
66
|
+
# With `run`, the command runs in a subshell and the output is captured.
|
|
67
|
+
result = subprocess.run(f"set -o pipefail; {cmd}", **subprocess_args)
|
|
68
|
+
|
|
69
|
+
# If the exit code is non-zero, throw an exception. If something was
|
|
70
|
+
# written to `stderr`, use that as the exception message. Otherwise, use a
|
|
71
|
+
# generic message (which is also what `subprocess.run` does with
|
|
72
|
+
# `check=True`).
|
|
73
|
+
if result.returncode != 0:
|
|
74
|
+
if len(result.stderr) > 0:
|
|
75
|
+
raise Exception(result.stderr.replace("\n", " ").strip())
|
|
76
|
+
else:
|
|
77
|
+
raise Exception(
|
|
78
|
+
f"Command failed with exit code {result.returncode}, "
|
|
79
|
+
f" nothing written to stderr (stdout: {result.stdout})"
|
|
80
|
+
)
|
|
81
|
+
# Optionally, return what was written to `stdout`.
|
|
82
|
+
if return_output:
|
|
83
|
+
return result.stdout
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def run_curl_command(
|
|
87
|
+
url: str,
|
|
88
|
+
headers: dict[str, str] = {},
|
|
89
|
+
params: dict[str, str] = {},
|
|
90
|
+
result_file: Optional[str] = None,
|
|
91
|
+
) -> str:
|
|
92
|
+
"""
|
|
93
|
+
Run `curl` with the given `url`, `headers`, and `params`. If `result_file`
|
|
94
|
+
is `None`, return the output, otherwise, write the output to the given file
|
|
95
|
+
and return the HTTP code. If the `curl` command fails, throw an exception.
|
|
96
|
+
|
|
97
|
+
"""
|
|
98
|
+
# Construct and run the `curl` command.
|
|
99
|
+
default_result_file = "/tmp/qlever.curl.result"
|
|
100
|
+
actual_result_file = result_file if result_file else default_result_file
|
|
101
|
+
curl_cmd = (
|
|
102
|
+
f'curl -Ls -o "{actual_result_file}"'
|
|
103
|
+
f' -w "%{{http_code}}\n" {url}'
|
|
104
|
+
+ "".join([f' -H "{key}: {value}"' for key, value in headers.items()])
|
|
105
|
+
+ "".join(
|
|
106
|
+
[
|
|
107
|
+
f" --data-urlencode {key}={shlex.quote(value)}"
|
|
108
|
+
for key, value in params.items()
|
|
109
|
+
]
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
result = subprocess.run(
|
|
113
|
+
curl_cmd,
|
|
114
|
+
shell=True,
|
|
115
|
+
text=True,
|
|
116
|
+
stdout=subprocess.PIPE,
|
|
117
|
+
stderr=subprocess.PIPE,
|
|
118
|
+
)
|
|
119
|
+
# Case 1: An error occurred, raise an exception.
|
|
120
|
+
if result.returncode != 0:
|
|
121
|
+
if len(result.stderr) > 0:
|
|
122
|
+
raise Exception(result.stderr)
|
|
123
|
+
else:
|
|
124
|
+
raise Exception(
|
|
125
|
+
f"curl command failed with exit code "
|
|
126
|
+
f"{result.returncode}, stderr is empty"
|
|
127
|
+
)
|
|
128
|
+
# Case 2: Return output (read from `default_result_file`).
|
|
129
|
+
if result_file is None:
|
|
130
|
+
result_file_path = Path(default_result_file)
|
|
131
|
+
result = result_file_path.read_text()
|
|
132
|
+
result_file_path.unlink()
|
|
133
|
+
return result
|
|
134
|
+
# Case 3: Return HTTP code.
|
|
135
|
+
return result.stdout
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def is_qlever_server_alive(endpoint_url: str) -> bool:
|
|
139
|
+
"""
|
|
140
|
+
Helper function that checks if a QLever server is running on the given
|
|
141
|
+
endpoint. Return `True` if the server is alive, `False` otherwise.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
message = "from the `qlever` CLI"
|
|
145
|
+
curl_cmd = (
|
|
146
|
+
f"curl -s {endpoint_url}/ping"
|
|
147
|
+
f" --data-urlencode msg={shlex.quote(message)}"
|
|
148
|
+
)
|
|
149
|
+
log.debug(curl_cmd)
|
|
150
|
+
try:
|
|
151
|
+
run_command(curl_cmd)
|
|
152
|
+
return True
|
|
153
|
+
except Exception:
|
|
154
|
+
return False
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def get_existing_index_files(basename: str) -> list[str]:
|
|
158
|
+
"""
|
|
159
|
+
Helper function that returns a list of all index files for `basename` in
|
|
160
|
+
the current working directory.
|
|
161
|
+
"""
|
|
162
|
+
existing_index_files = []
|
|
163
|
+
existing_index_files.extend(Path.cwd().glob(f"{basename}.index.*"))
|
|
164
|
+
existing_index_files.extend(Path.cwd().glob(f"{basename}.text.*"))
|
|
165
|
+
existing_index_files.extend(Path.cwd().glob(f"{basename}.vocabulary.*"))
|
|
166
|
+
existing_index_files.extend(Path.cwd().glob(f"{basename}.meta-data.json"))
|
|
167
|
+
existing_index_files.extend(Path.cwd().glob(f"{basename}.prefixes"))
|
|
168
|
+
# Return only the file names, not the full paths.
|
|
169
|
+
return [path.name for path in existing_index_files]
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def show_process_info(psutil_process, cmdline_regex, show_heading=True):
|
|
173
|
+
"""
|
|
174
|
+
Helper function that shows information about a process if information
|
|
175
|
+
about the process can be retrieved and the command line matches the
|
|
176
|
+
given regex (in which case the function returns `True`). The heading is
|
|
177
|
+
only shown if `show_heading` is `True` and the function returns `True`.
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
# Helper function that shows a line of the process table.
|
|
181
|
+
def show_table_line(pid, user, start_time, rss, cmdline):
|
|
182
|
+
log.info(f"{pid:<8} {user:<8} {start_time:>5} {rss:>5} {cmdline}")
|
|
183
|
+
|
|
184
|
+
try:
|
|
185
|
+
pinfo = psutil_process.as_dict(
|
|
186
|
+
attrs=["pid", "username", "create_time", "memory_info", "cmdline"]
|
|
187
|
+
)
|
|
188
|
+
# Note: pinfo[`cmdline`] is `None` if the process is a zombie.
|
|
189
|
+
cmdline = " ".join(pinfo["cmdline"] or [])
|
|
190
|
+
if len(cmdline) == 0 or not re.search(cmdline_regex, cmdline):
|
|
191
|
+
return False
|
|
192
|
+
pid = pinfo["pid"]
|
|
193
|
+
user = pinfo["username"] if pinfo["username"] else ""
|
|
194
|
+
start_time = datetime.fromtimestamp(pinfo["create_time"])
|
|
195
|
+
if start_time.date() == date.today():
|
|
196
|
+
start_time = start_time.strftime("%H:%M")
|
|
197
|
+
else:
|
|
198
|
+
start_time = start_time.strftime("%b%d")
|
|
199
|
+
rss = f"{pinfo['memory_info'].rss / 1e9:.0f}G"
|
|
200
|
+
if show_heading:
|
|
201
|
+
show_table_line("PID", "USER", "START", "RSS", "COMMAND")
|
|
202
|
+
show_table_line(pid, user, start_time, rss, cmdline)
|
|
203
|
+
return True
|
|
204
|
+
except Exception as e:
|
|
205
|
+
log.error(f"Could not get process info: {e}")
|
|
206
|
+
return False
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def get_random_string(length: int) -> str:
|
|
210
|
+
"""
|
|
211
|
+
Helper function that returns a randomly chosen string of the given
|
|
212
|
+
length. Take the current time as seed.
|
|
213
|
+
"""
|
|
214
|
+
characters = string.ascii_letters + string.digits
|
|
215
|
+
return "".join(secrets.choice(characters) for _ in range(length))
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def is_port_used(port: int) -> bool:
|
|
219
|
+
"""
|
|
220
|
+
Try to bind to the port on all interfaces to check if the port is already in use.
|
|
221
|
+
If the port is already in use, `socket.bind` will raise an `OSError` with errno EADDRINUSE.
|
|
222
|
+
"""
|
|
223
|
+
try:
|
|
224
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
225
|
+
# Ensure that the port is not blocked after the check.
|
|
226
|
+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
227
|
+
sock.bind(("", port))
|
|
228
|
+
sock.close()
|
|
229
|
+
return False
|
|
230
|
+
except OSError as err:
|
|
231
|
+
if err.errno != errno.EADDRINUSE:
|
|
232
|
+
log.warning(f"Failed to determine if port is used: {err}")
|
|
233
|
+
return True
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def format_size(bytes, suffix="B"):
|
|
237
|
+
"""
|
|
238
|
+
Scale bytes to its proper format
|
|
239
|
+
e.g:
|
|
240
|
+
1253656 => '1.20MB'
|
|
241
|
+
1253656678 => '1.17GB'
|
|
242
|
+
"""
|
|
243
|
+
factor = 1024
|
|
244
|
+
for unit in ["", "K", "M", "G", "T", "P"]:
|
|
245
|
+
if bytes < factor:
|
|
246
|
+
return f"{bytes:.2f} {unit}{suffix}"
|
|
247
|
+
bytes /= factor
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def stop_process(proc: psutil.Process, pinfo: dict[str, Any]) -> bool:
|
|
251
|
+
"""
|
|
252
|
+
Try to kill the given process, return True iff it was killed
|
|
253
|
+
successfully. The process_info is used for logging.
|
|
254
|
+
"""
|
|
255
|
+
try:
|
|
256
|
+
proc.kill()
|
|
257
|
+
log.info(f"Killed process {pinfo['pid']}")
|
|
258
|
+
return True
|
|
259
|
+
except Exception as e:
|
|
260
|
+
log.error(
|
|
261
|
+
f"Could not kill process with PID "
|
|
262
|
+
f"{pinfo['pid']} ({e}) ... try to kill it "
|
|
263
|
+
f"manually"
|
|
264
|
+
)
|
|
265
|
+
log.info("")
|
|
266
|
+
show_process_info(proc, "", show_heading=True)
|
|
267
|
+
return False
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def stop_process_with_regex(cmdline_regex: str) -> list[bool] | None:
|
|
271
|
+
"""
|
|
272
|
+
Given a cmdline_regex for a native process, try to kill the processes that
|
|
273
|
+
match the regex and return a list of their stopped status (bool).
|
|
274
|
+
Show the matched processes as log info.
|
|
275
|
+
"""
|
|
276
|
+
stop_process_results = []
|
|
277
|
+
for proc in psutil.process_iter():
|
|
278
|
+
try:
|
|
279
|
+
pinfo = proc.as_dict(
|
|
280
|
+
attrs=[
|
|
281
|
+
"pid",
|
|
282
|
+
"username",
|
|
283
|
+
"create_time",
|
|
284
|
+
"memory_info",
|
|
285
|
+
"cmdline",
|
|
286
|
+
]
|
|
287
|
+
)
|
|
288
|
+
cmdline = " ".join(pinfo["cmdline"])
|
|
289
|
+
except Exception as e:
|
|
290
|
+
# For some processes (e.g., zombies), getting info may fail.
|
|
291
|
+
log.debug(f"Error getting process info: {e}")
|
|
292
|
+
continue
|
|
293
|
+
if re.search(cmdline_regex, cmdline):
|
|
294
|
+
log.info(
|
|
295
|
+
f"Found process {pinfo['pid']} from user "
|
|
296
|
+
f"{pinfo['username']} with command line: {cmdline}"
|
|
297
|
+
)
|
|
298
|
+
log.info("")
|
|
299
|
+
stop_process_results.append(stop_process(proc, pinfo))
|
|
300
|
+
return stop_process_results
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def binary_exists(binary: str, cmd_arg: str) -> bool:
|
|
304
|
+
"""
|
|
305
|
+
When a command is run natively, check if the binary exists on the system
|
|
306
|
+
"""
|
|
307
|
+
try:
|
|
308
|
+
run_command(f"{binary} --help")
|
|
309
|
+
return True
|
|
310
|
+
except Exception as e:
|
|
311
|
+
log.error(
|
|
312
|
+
f'Running "{binary}" failed, '
|
|
313
|
+
f"set `--{cmd_arg}` to a different binary or "
|
|
314
|
+
f"set `--system to a container system`"
|
|
315
|
+
)
|
|
316
|
+
log.info("")
|
|
317
|
+
log.info(f"The error message was: {e}")
|
|
318
|
+
return False
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def is_server_alive(url: str) -> bool:
|
|
322
|
+
"""
|
|
323
|
+
Check if the server is already alive at the given endpoint url
|
|
324
|
+
"""
|
|
325
|
+
check_server_cmd = f"curl -s {url}"
|
|
326
|
+
try:
|
|
327
|
+
run_command(check_server_cmd)
|
|
328
|
+
return True
|
|
329
|
+
except Exception:
|
|
330
|
+
return False
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qlever
|
|
3
|
+
Version: 0.5.41
|
|
4
|
+
Summary: Command-line tool for using the QLever graph database
|
|
5
|
+
Author-email: Hannah Bast <bast@cs.uni-freiburg.de>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: homepage, https://github.com/ad-freiburg/qlever
|
|
8
|
+
Project-URL: documentation, https://docs.qlever.dev
|
|
9
|
+
Project-URL: repository, https://github.com/ad-freiburg/qlever.git
|
|
10
|
+
Project-URL: bugtracker, https://github.com/ad-freiburg/qlever/issues
|
|
11
|
+
Keywords: Graph database,Triplestore,Knowledge graphs,SPARQL,RDF
|
|
12
|
+
Classifier: Topic :: Database :: Database Engines/Servers
|
|
13
|
+
Classifier: Topic :: Database :: Front-Ends
|
|
14
|
+
Requires-Python: >=3.8
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: psutil
|
|
18
|
+
Requires-Dist: termcolor
|
|
19
|
+
Requires-Dist: argcomplete
|
|
20
|
+
Requires-Dist: pyyaml
|
|
21
|
+
Requires-Dist: rdflib
|
|
22
|
+
Requires-Dist: requests-sse
|
|
23
|
+
Requires-Dist: tqdm
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# QLever
|
|
27
|
+
|
|
28
|
+
This repository provides a self-documenting and easy-to-use command-line tool
|
|
29
|
+
for QLever (pronounced "Clever"), a graph database implementing the
|
|
30
|
+
[RDF](https://www.w3.org/TR/rdf11-concepts/) and
|
|
31
|
+
[SPARQL](https://www.w3.org/TR/sparql11-overview/) standards.
|
|
32
|
+
For a detailed description of what QLever is and what it can do, see
|
|
33
|
+
[here](https://github.com/ad-freiburg/qlever).
|
|
34
|
+
|
|
35
|
+
# Installation
|
|
36
|
+
|
|
37
|
+
Simply do `pip install qlever` and make sure that the directory where `pip`
|
|
38
|
+
installs the package is in your `PATH`. Typically, `pip` will warn you when
|
|
39
|
+
that is not the case and tell you what to do. If you encounter an "Externally
|
|
40
|
+
managed Environment" error, try `pipx` instead of `pip`.
|
|
41
|
+
|
|
42
|
+
Type `qlever` without arguments to check that the installation worked. When
|
|
43
|
+
using it for the first time, you will see a warning at the top with
|
|
44
|
+
instructions on how to enable autocompletion. Do it, it makes using `qlever`
|
|
45
|
+
so much easier (`pip` cannot do that for you automatically, sorry).
|
|
46
|
+
|
|
47
|
+
# Usage
|
|
48
|
+
|
|
49
|
+
Create an empty directory, with a name corresponding to the dataset you want to
|
|
50
|
+
work with. For the following example, take `olympics`. Go to that directory
|
|
51
|
+
and do the following.
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
qlever setup-config olympics # Get Qleverfile (config file) for this dataset
|
|
55
|
+
qlever get-data # Download the dataset
|
|
56
|
+
qlever index # Build index data structures for this dataset
|
|
57
|
+
qlever start # Start a QLever server using that index
|
|
58
|
+
qlever query # Launch an example query
|
|
59
|
+
qlever ui # Launch the QLever UI
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
This will create a SPARQL endpoint for the [120 Years of
|
|
63
|
+
Olympics](https://github.com/wallscope/olympics-rdf) dataset. It is a great
|
|
64
|
+
dataset for getting started because it is small, but not trivial (around 2
|
|
65
|
+
million triples), and the downloading and indexing should only take a few
|
|
66
|
+
seconds.
|
|
67
|
+
|
|
68
|
+
Each command will also show you the command line it uses. That way you can
|
|
69
|
+
learn, on the side, how QLever works internally. If you just want to know the
|
|
70
|
+
command line for a particular command, without executing it, you can append
|
|
71
|
+
`--show` like this:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
qlever index --show
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
There are many more commands and options, see `qlever --help` for general help,
|
|
78
|
+
`qlever <command> --help` for help on a specific command, or just use the
|
|
79
|
+
autocompletion.
|
|
80
|
+
|
|
81
|
+
# Use on macOS and Windows
|
|
82
|
+
|
|
83
|
+
By default, `qlever` uses [QLever's official Docker
|
|
84
|
+
image](https://hub.docker.com/r/adfreiburg/qlever). In principle, that image
|
|
85
|
+
runs on Linux, macOS, and Windows. On Linux, Docker runs natively
|
|
86
|
+
and incurs only a relatively small overhead regarding performance and RAM
|
|
87
|
+
consumption. On macOS and Windows, Docker runs in a virtual machine, which
|
|
88
|
+
incurs a significant and sometimes unpredictable overhead. For example, `qlever
|
|
89
|
+
index` might abort prematurely (without a proper error message) because the
|
|
90
|
+
virtual machine runs out of RAM.
|
|
91
|
+
|
|
92
|
+
For optimal performance, compile QLever from source on your machine. For Linux,
|
|
93
|
+
this is relatively straightforward: just follow the `RUN` instructions in the
|
|
94
|
+
[Dockerfile](https://github.com/ad-freiburg/qlever/blob/master/Dockerfile). For
|
|
95
|
+
macOS, this is more complicated, see [this
|
|
96
|
+
workflow](https://github.com/ad-freiburg/qlever/blob/master/.github/workflows/macos.yml).
|
|
97
|
+
|
|
98
|
+
# Use with your own dataset
|
|
99
|
+
|
|
100
|
+
To use QLever with your own dataset, you need a `Qleverfile`, like in the
|
|
101
|
+
example above. The easiest way to write a `Qleverfile` is to get one of the
|
|
102
|
+
existing ones (using `qlever setup-config ...` as explained above) and then
|
|
103
|
+
change it according to your needs (the variable names should be
|
|
104
|
+
self-explanatory). Pick one for a dataset that is similar to yours and when in
|
|
105
|
+
doubt, pick `olympics`.
|
|
106
|
+
|
|
107
|
+
# For developers
|
|
108
|
+
|
|
109
|
+
The (Python) code for the script is in the `*.py` files in `src/qlever`. The
|
|
110
|
+
preconfigured Qleverfiles are in `src/qlever/Qleverfiles`.
|
|
111
|
+
|
|
112
|
+
If you want to make changes to the script, or add new commands, do as follows:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
git clone https://github.com/ad-freiburg/qlever-control
|
|
116
|
+
cd qlever-control
|
|
117
|
+
pip install -e .
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Then you can use `qlever` just as if you had installed it via `pip install
|
|
121
|
+
qlever`. Note that you don't have to rerun `pip install -e .` when you modify
|
|
122
|
+
any of the `*.py` files and not even when you add new commands in
|
|
123
|
+
`src/qlever/commands`. The exceutable created by `pip` simply links and refers
|
|
124
|
+
to the files in your working copy.
|
|
125
|
+
|
|
126
|
+
If you have bug fixes or new useful features or commands, please open a pull
|
|
127
|
+
request. If you have questions or suggestions, please open an issue.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
qlever/__init__.py,sha256=ZbzivHALRlzAUoFBBSbbkKFcvATBX7yVR6Q9JyEQ8ig,1631
|
|
2
|
+
qlever/command.py,sha256=QTg1SOiVc8_v0RYxwu74dv9FhVJs85RKMfAZuklEw6o,2766
|
|
3
|
+
qlever/config.py,sha256=gNw2_-jj1TjzhzqLOuUI_Dh19q_ViCiArrtrgXL2F4E,10354
|
|
4
|
+
qlever/containerize.py,sha256=QK2CylUnbZ0r-YCCnJMjxupE5ZBIlQZmS1Vn0-3PiI4,5496
|
|
5
|
+
qlever/log.py,sha256=WLscWV4fFF_w_uXSOfvWzhyzRM7t_61inE2ks3zf6Gw,1317
|
|
6
|
+
qlever/qlever_main.py,sha256=QlVXq7azyuAG0QhH_pER2fdZL8el2mG0I6d9r0dGgOA,2593
|
|
7
|
+
qlever/qleverfile.py,sha256=hNn_tmJxlLWrkp7pl9hOaKkVRVLO22bZUh9MfSklng4,20083
|
|
8
|
+
qlever/util.py,sha256=86v5tyoPoCiWqWOu8pLB7M2GwQO251hhbKF2cN0-vCY,11036
|
|
9
|
+
qlever/Qleverfiles/Qleverfile.dblp,sha256=y4AyUg8Dk2NHV972aeqnj77GZzWbgwV-zRD1qcdwhQE,1246
|
|
10
|
+
qlever/Qleverfiles/Qleverfile.dblp-plus,sha256=TJHxp8I1P6JKJjbuAllEpB32-huuY1gH0FlenqPVJ5g,1334
|
|
11
|
+
qlever/Qleverfiles/Qleverfile.dbpedia,sha256=aaNZZayE-zVePGSwPzXemkX__Ns8-kP_E7DNNKZPnqg,1160
|
|
12
|
+
qlever/Qleverfiles/Qleverfile.default,sha256=Kj-J1Kkv8PWN7wuMdZU6DUUlEuBIcSNysJCE-R63we8,2407
|
|
13
|
+
qlever/Qleverfiles/Qleverfile.dnb,sha256=43w_CVi00yf7FHdDvBtHHQR3yU1d-JCNnD_uxYZJOvk,1803
|
|
14
|
+
qlever/Qleverfiles/Qleverfile.fbeasy,sha256=CYmbxRnb4OFAagwoVfciyFR_26G-Ohk1ObBL6duSfuE,936
|
|
15
|
+
qlever/Qleverfiles/Qleverfile.freebase,sha256=Kol5ffUjJ5cXIWRxdY-SotOG1kGm82gZ3S8OV4BnrJA,1036
|
|
16
|
+
qlever/Qleverfiles/Qleverfile.imdb,sha256=iEzJuDU1AaC7-EZYfocaoEb32VH-QvbBiXhnzwWmGaQ,1756
|
|
17
|
+
qlever/Qleverfiles/Qleverfile.ohm-planet,sha256=Cr0MI0mSDnfaDI1iDyKhA2wO4XjdMmewlUc4Ge4Gc5c,2735
|
|
18
|
+
qlever/Qleverfiles/Qleverfile.olympics,sha256=5w9BOFwEBhdSzPz-0LRxwhv-7Gj6xbF539HOXr3cqD0,1088
|
|
19
|
+
qlever/Qleverfiles/Qleverfile.orkg,sha256=Uizz-RhlSeExgfckWztewa4l_v3zMN8IR7NaGYKrqt4,937
|
|
20
|
+
qlever/Qleverfiles/Qleverfile.osm-country,sha256=4Y2zCetMSxfRa23LPv-uYXJHMtIhl8lwOSbZgU_eIQc,1843
|
|
21
|
+
qlever/Qleverfiles/Qleverfile.osm-planet,sha256=fbP0y_OAx1-eOAA1PaEjaDwL-5QIrctBDJnxh_1D084,1758
|
|
22
|
+
qlever/Qleverfiles/Qleverfile.osm-planet-from-pbf,sha256=62IGpXkw0RyLyi0boyf2W3LEh3o_QtRM8o15QV1OPL4,2207
|
|
23
|
+
qlever/Qleverfiles/Qleverfile.pubchem,sha256=7RvCNJXxxyuhVpzaHVY03Rsoeml3cTkkKeonp9fiHek,14474
|
|
24
|
+
qlever/Qleverfiles/Qleverfile.scientists,sha256=9eZ2c6P9a3E3VHa3RR7LdOQbF4k3oyyrn56Z3u4LZYs,1164
|
|
25
|
+
qlever/Qleverfiles/Qleverfile.uniprot,sha256=s27n8yoNlQsIOO-vqgBkvmTn-s-dq7_wYthReAo57f0,6273
|
|
26
|
+
qlever/Qleverfiles/Qleverfile.vvz,sha256=cLzm85erKoFCDllH5eFcSi35MdR6Tahj1MgtvGRxanM,922
|
|
27
|
+
qlever/Qleverfiles/Qleverfile.wikidata,sha256=KLal5FjAzcEU0aqUDC5muFunm_Lti8is4RGu4IOQuMg,2061
|
|
28
|
+
qlever/Qleverfiles/Qleverfile.wikipathways,sha256=GENI4KYtrn_4M9mnGnfGPNkKy_lAPfO2LwnzbOx3fCE,1982
|
|
29
|
+
qlever/Qleverfiles/Qleverfile.yago-4,sha256=hAS_2ZmC1zxNsKXip7t1F_iqu3CC-6O7v6HZhuFbnWY,1819
|
|
30
|
+
qlever/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
+
qlever/commands/add_text_index.py,sha256=8Ri9e2cfJmsWLjD-iEB5jkbm4toEME0bccMJJkyx_sU,3819
|
|
32
|
+
qlever/commands/benchmark_queries.py,sha256=znT4pCCtvSgyXNWOEBJcRZ6lR_4zUDG4YphvUyzM2Zw,39204
|
|
33
|
+
qlever/commands/cache_stats.py,sha256=7JL1P4SX0F8xyN5VTiOSG5E1reCcM1rPaQsqllHuFTM,4366
|
|
34
|
+
qlever/commands/clear_cache.py,sha256=R0jRn_76A7dvyQyWgHld0THoYbohiVVEFAjBjOV3Uy4,2807
|
|
35
|
+
qlever/commands/extract_queries.py,sha256=1l59ipbNNJIesOXQOf3b8xWYu4-tPP73dHl2qP8LR48,4281
|
|
36
|
+
qlever/commands/get_data.py,sha256=nHOHMjv0tSLWJDOR0ba_LK-Bk-mcGnphb8hbqcVYFhE,1411
|
|
37
|
+
qlever/commands/index.py,sha256=IOvT8GqrBXcb5JPQ82359Mf1cD5EgzTQoRro-3w5HRw,13395
|
|
38
|
+
qlever/commands/index_stats.py,sha256=qNbDMogB83Ni5fGXPOZQO9VZQ_x2096vFyCCJ0jEuYw,11719
|
|
39
|
+
qlever/commands/log.py,sha256=vLqkgtx1udnQqoUBMWB5G9rwr-l7UKrDpyFYSMuoXWw,1987
|
|
40
|
+
qlever/commands/materialized_view.py,sha256=F9caIEfQbjDm2U-5iKelUiRkb8MceAesJiB2_zG6Mko,3523
|
|
41
|
+
qlever/commands/query.py,sha256=QJpr_sxNL03OBXq9LIPiuhMoSVamgz-RF9uevbQ61QM,4652
|
|
42
|
+
qlever/commands/rebuild_index.py,sha256=Iow3If0xhOQ2GYfRLuX5dXS5sk8wPdTicS_XTWjL_hk,6496
|
|
43
|
+
qlever/commands/reset_updates.py,sha256=uJvfKPCbgp-9247Ievyb292nR1VvOcaAIcVM-EalP7o,1879
|
|
44
|
+
qlever/commands/settings.py,sha256=YBob1LiYTSHTIZ6vIQcWc7hIWImP60HQCoacJu8XY2M,4001
|
|
45
|
+
qlever/commands/setup_config.py,sha256=mFO-GWPBOI47IS4W4v56NSdA5SEncEHG2vZjG9lP6_4,3343
|
|
46
|
+
qlever/commands/start.py,sha256=Moi1zbACmCxr3Fj3DzrEn-2W6dxB10GR0t7snIksgEo,11613
|
|
47
|
+
qlever/commands/status.py,sha256=TtnBqcdkF3zTDKft07zpVcIX7kFu7d_nOy9b6Ohh9vQ,1650
|
|
48
|
+
qlever/commands/stop.py,sha256=5BNKArOzoJ8kYiTVAmtN81w7nQ42fkxISgsxL-qJpO0,3463
|
|
49
|
+
qlever/commands/system_info.py,sha256=16HMl-MSQITfesuupuRE7gajVcahhCxeA7NCOaKCiKk,4659
|
|
50
|
+
qlever/commands/ui.py,sha256=QRSN-aO5jfG_97hz8lvo1x-SYWx_56zr78kVx6P8DWU,9810
|
|
51
|
+
qlever/commands/update.py,sha256=9EAPuUct5gQvwEimpBsqxefYWVUezufAa90jzClAE7Q,2710
|
|
52
|
+
qlever/commands/update_wikidata.py,sha256=VpYdgLetlNXk-FUTBV_evnw2hW00PQTzHEaI-1eKS-0,53540
|
|
53
|
+
qlever/commands/warmup.py,sha256=kJHzS7HJo8pD2CphJuaXDj_CYP02YDo2DVM-pun3A80,1029
|
|
54
|
+
qlever-0.5.41.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
55
|
+
qlever-0.5.41.dist-info/METADATA,sha256=g6rZUghOc1_4SesMiCvSEByeELZ-i0GPZIkYFrNuHhc,5373
|
|
56
|
+
qlever-0.5.41.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
57
|
+
qlever-0.5.41.dist-info/entry_points.txt,sha256=U_1U6SFIEZ-AnNlvk2nzcL0e4jnjEpuSbxYZ_E0XpEg,51
|
|
58
|
+
qlever-0.5.41.dist-info/top_level.txt,sha256=kd3zsYqiFd0--Czh5XTVkfEq6XR-XgRFW35X0v0GT-c,7
|
|
59
|
+
qlever-0.5.41.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
qlever
|