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/qleverfile.py
ADDED
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
import socket
|
|
5
|
+
import subprocess
|
|
6
|
+
from configparser import ConfigParser, ExtendedInterpolation, RawConfigParser
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from qlever import script_name
|
|
10
|
+
from qlever.containerize import Containerize
|
|
11
|
+
from qlever.log import log
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class QleverfileException(Exception):
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Qleverfile:
|
|
19
|
+
"""
|
|
20
|
+
Class that defines all the possible parameters that can be specified in a
|
|
21
|
+
Qleverfile + functions for parsing.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
# Runtime parameters (for `settings` and `start` commands).
|
|
25
|
+
SERVER_RUNTIME_PARAMETERS = [
|
|
26
|
+
"cache-max-num-entries",
|
|
27
|
+
"cache-max-size",
|
|
28
|
+
"cache-max-size-single-entry",
|
|
29
|
+
"cache-service-results",
|
|
30
|
+
"default-query-timeout",
|
|
31
|
+
"division-by-zero-is-undef",
|
|
32
|
+
"enable-distributive-union",
|
|
33
|
+
"enable-prefilter-on-index-scans",
|
|
34
|
+
"group-by-disable-index-scan-optimizations",
|
|
35
|
+
"group-by-hash-map-enabled",
|
|
36
|
+
"lazy-index-scan-max-size-materialization",
|
|
37
|
+
"lazy-index-scan-num-threads",
|
|
38
|
+
"lazy-index-scan-queue-size",
|
|
39
|
+
"lazy-result-max-cache-size",
|
|
40
|
+
"query-planning-budget",
|
|
41
|
+
"request-body-limit",
|
|
42
|
+
"service-max-redirects",
|
|
43
|
+
"service-max-value-rows",
|
|
44
|
+
"sort-estimate-cancellation-factor",
|
|
45
|
+
"sparql-results-json-with-time",
|
|
46
|
+
"spatial-join-prefilter-max-size",
|
|
47
|
+
"spatial-join-max-num-threads",
|
|
48
|
+
"strip-columns",
|
|
49
|
+
"syntax-test-mode",
|
|
50
|
+
"throw-on-unbound-variables",
|
|
51
|
+
"treat-default-graph-as-named-graph",
|
|
52
|
+
"use-binsearch-transitive-path",
|
|
53
|
+
"websocket-updates-enabled",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def all_arguments():
|
|
58
|
+
"""
|
|
59
|
+
Define all possible parameters. A value of `None` means that there is
|
|
60
|
+
no default value.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
# Helper function that takes a list of positional arguments and a list
|
|
64
|
+
# of keyword arguments and returns a tuple of both. That way, we can
|
|
65
|
+
# defined arguments below with exactly the same syntax as we would for
|
|
66
|
+
# `argparse.add_argument`.
|
|
67
|
+
def arg(*args, **kwargs):
|
|
68
|
+
return (args, kwargs)
|
|
69
|
+
|
|
70
|
+
all_args = {}
|
|
71
|
+
data_args = all_args["data"] = {}
|
|
72
|
+
index_args = all_args["index"] = {}
|
|
73
|
+
server_args = all_args["server"] = {}
|
|
74
|
+
runtime_args = all_args["runtime"] = {}
|
|
75
|
+
ui_args = all_args["ui"] = {}
|
|
76
|
+
|
|
77
|
+
data_args["name"] = arg(
|
|
78
|
+
"--name", type=str, required=True, help="The name of the dataset"
|
|
79
|
+
)
|
|
80
|
+
data_args["get_data_cmd"] = arg(
|
|
81
|
+
"--get-data-cmd",
|
|
82
|
+
type=str,
|
|
83
|
+
required=True,
|
|
84
|
+
help="The command to get the data",
|
|
85
|
+
)
|
|
86
|
+
data_args["description"] = arg(
|
|
87
|
+
"--description",
|
|
88
|
+
type=str,
|
|
89
|
+
required=True,
|
|
90
|
+
help="A concise description of the dataset",
|
|
91
|
+
)
|
|
92
|
+
data_args["text_description"] = arg(
|
|
93
|
+
"--text-description",
|
|
94
|
+
type=str,
|
|
95
|
+
default=None,
|
|
96
|
+
help="A concise description of the additional text data if any",
|
|
97
|
+
)
|
|
98
|
+
data_args["format"] = arg(
|
|
99
|
+
"--format",
|
|
100
|
+
type=str,
|
|
101
|
+
default="ttl",
|
|
102
|
+
choices=["ttl", "nt", "nq"],
|
|
103
|
+
help="The format of the data",
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
index_args["input_files"] = arg(
|
|
107
|
+
"--input-files",
|
|
108
|
+
type=str,
|
|
109
|
+
required=True,
|
|
110
|
+
help="A space-separated list of patterns that match "
|
|
111
|
+
"all the files of the dataset",
|
|
112
|
+
)
|
|
113
|
+
index_args["cat_input_files"] = arg(
|
|
114
|
+
"--cat-input-files",
|
|
115
|
+
type=str,
|
|
116
|
+
help="The command that produces the input",
|
|
117
|
+
)
|
|
118
|
+
index_args["multi_input_json"] = arg(
|
|
119
|
+
"--multi-input-json",
|
|
120
|
+
type=str,
|
|
121
|
+
default=None,
|
|
122
|
+
help="JSON to specify multiple input files, each with a "
|
|
123
|
+
"`cmd` (command that writes the triples to stdout), "
|
|
124
|
+
"`format` (format like for the `--format` option), "
|
|
125
|
+
"`graph` (name of the graph, use `-` for the default graph), "
|
|
126
|
+
"`parallel` (parallel parsing for large files, where all "
|
|
127
|
+
"prefix declaration are at the beginning)",
|
|
128
|
+
)
|
|
129
|
+
index_args["parallel_parsing"] = arg(
|
|
130
|
+
"--parallel-parsing",
|
|
131
|
+
type=str,
|
|
132
|
+
choices=["true", "false"],
|
|
133
|
+
help="Use parallel parsing (recommended for large files, "
|
|
134
|
+
"but it requires that all prefix declarations are at the "
|
|
135
|
+
"beginning of the file)",
|
|
136
|
+
)
|
|
137
|
+
index_args["settings_json"] = arg(
|
|
138
|
+
"--settings-json",
|
|
139
|
+
type=str,
|
|
140
|
+
default="{}",
|
|
141
|
+
help="The `.settings.json` file for the index",
|
|
142
|
+
)
|
|
143
|
+
index_args["ulimit"] = arg(
|
|
144
|
+
"--ulimit",
|
|
145
|
+
type=int,
|
|
146
|
+
default=None,
|
|
147
|
+
help="Explicitly set the limit for the maximal number of open "
|
|
148
|
+
"files (default: 1048576 when the total size of the input files "
|
|
149
|
+
"is larger than 10 GB)",
|
|
150
|
+
)
|
|
151
|
+
index_args["vocabulary_type"] = arg(
|
|
152
|
+
"--vocabulary-type",
|
|
153
|
+
type=str,
|
|
154
|
+
choices=[
|
|
155
|
+
"on-disk-compressed",
|
|
156
|
+
"on-disk-uncompressed",
|
|
157
|
+
"in-memory-compressed",
|
|
158
|
+
"in-memory-uncompressed",
|
|
159
|
+
"on-disk-compressed-geo-split",
|
|
160
|
+
],
|
|
161
|
+
default="on-disk-compressed",
|
|
162
|
+
help="The type of the vocabulary to use for the index "
|
|
163
|
+
" (default: `on-disk-compressed`)",
|
|
164
|
+
)
|
|
165
|
+
index_args["index_binary"] = arg(
|
|
166
|
+
"--index-binary",
|
|
167
|
+
type=str,
|
|
168
|
+
default="IndexBuilderMain",
|
|
169
|
+
help="The binary for building the index (this requires "
|
|
170
|
+
"that you have compiled QLever on your machine)",
|
|
171
|
+
)
|
|
172
|
+
index_args["stxxl_memory"] = arg(
|
|
173
|
+
"--stxxl-memory",
|
|
174
|
+
type=str,
|
|
175
|
+
help="The amount of memory to use for the index build "
|
|
176
|
+
"(the name of the option has historical reasons)",
|
|
177
|
+
)
|
|
178
|
+
index_args["parser_buffer_size"] = arg(
|
|
179
|
+
"--parser-buffer-size",
|
|
180
|
+
type=str,
|
|
181
|
+
help="Each parser thread reads the input in batches of this size, "
|
|
182
|
+
"and in parallel parsing, each batch that is not the last must be "
|
|
183
|
+
"large enough to contain the end of at least one statement "
|
|
184
|
+
"(default: 10M)",
|
|
185
|
+
)
|
|
186
|
+
index_args["encode_as_id"] = arg(
|
|
187
|
+
"--encode-as-id",
|
|
188
|
+
type=str,
|
|
189
|
+
help="Space-separated list of IRI prefixes (without angle "
|
|
190
|
+
"brackets); IRIs that start with one of these prefixes, followed "
|
|
191
|
+
"by a sequence of digits, do not require a vocabulary entry but "
|
|
192
|
+
"are directly encoded in the ID (default: none)",
|
|
193
|
+
)
|
|
194
|
+
index_args["only_pso_and_pos_permutations"] = arg(
|
|
195
|
+
"--only-pso-and-pos-permutations",
|
|
196
|
+
action="store_true",
|
|
197
|
+
default=False,
|
|
198
|
+
help="Only create the PSO and POS permutations",
|
|
199
|
+
)
|
|
200
|
+
index_args["use_patterns"] = arg(
|
|
201
|
+
"--use-patterns",
|
|
202
|
+
choices=["yes", "no"],
|
|
203
|
+
default="yes",
|
|
204
|
+
help="Whether to precompute the so-called patterns used for fast "
|
|
205
|
+
"processing of queries like SELECT ?p (COUNT(DISTINCT ?s) AS ?c) "
|
|
206
|
+
"WHERE { ?s ?p [] ... } GROUP BY ?p",
|
|
207
|
+
)
|
|
208
|
+
index_args["add_has_word_triples"] = arg(
|
|
209
|
+
"--add-has-word-triples",
|
|
210
|
+
action="store_true",
|
|
211
|
+
default=False,
|
|
212
|
+
help="Whether to add `ql:has-word` triples for text literals "
|
|
213
|
+
"(which can then be used for custom text search queries)",
|
|
214
|
+
)
|
|
215
|
+
index_args["text_index"] = arg(
|
|
216
|
+
"--text-index",
|
|
217
|
+
choices=[
|
|
218
|
+
"none",
|
|
219
|
+
"from_text_records",
|
|
220
|
+
"from_literals",
|
|
221
|
+
"from_text_records_and_literals",
|
|
222
|
+
],
|
|
223
|
+
default="none",
|
|
224
|
+
help="Whether to also build an index for text search"
|
|
225
|
+
"and for which texts",
|
|
226
|
+
)
|
|
227
|
+
index_args["text_words_file"] = arg(
|
|
228
|
+
"--text-words-file",
|
|
229
|
+
type=str,
|
|
230
|
+
default=None,
|
|
231
|
+
help="File with the words for the text index (one line "
|
|
232
|
+
"per word, format: `word or IRI\t0 or 1\tdoc id\t1`)",
|
|
233
|
+
)
|
|
234
|
+
index_args["text_docs_file"] = arg(
|
|
235
|
+
"--text-docs-file",
|
|
236
|
+
type=str,
|
|
237
|
+
default=None,
|
|
238
|
+
help="File with the documents for the text index (one line "
|
|
239
|
+
"per document, format: `id\tdocument text`)",
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
server_args["server_binary"] = arg(
|
|
243
|
+
"--server-binary",
|
|
244
|
+
type=str,
|
|
245
|
+
default="ServerMain",
|
|
246
|
+
help="The binary for starting the server (this requires "
|
|
247
|
+
"that you have compiled QLever on your machine)",
|
|
248
|
+
)
|
|
249
|
+
server_args["host_name"] = arg(
|
|
250
|
+
"--host-name",
|
|
251
|
+
type=str,
|
|
252
|
+
help="The name of the host on which the server listens for "
|
|
253
|
+
"requests",
|
|
254
|
+
)
|
|
255
|
+
server_args["port"] = arg(
|
|
256
|
+
"--port",
|
|
257
|
+
type=int,
|
|
258
|
+
help="The port on which the server listens for requests",
|
|
259
|
+
)
|
|
260
|
+
server_args["access_token"] = arg(
|
|
261
|
+
"--access-token",
|
|
262
|
+
type=str,
|
|
263
|
+
default=None,
|
|
264
|
+
help="The access token for privileged operations",
|
|
265
|
+
)
|
|
266
|
+
server_args["memory_for_queries"] = arg(
|
|
267
|
+
"--memory-for-queries",
|
|
268
|
+
type=str,
|
|
269
|
+
default="5G",
|
|
270
|
+
help="The maximal amount of memory used for query processing"
|
|
271
|
+
" (if a query needs more than what is available, the "
|
|
272
|
+
"query will not be processed)",
|
|
273
|
+
)
|
|
274
|
+
server_args["cache_max_size"] = arg(
|
|
275
|
+
"--cache-max-size",
|
|
276
|
+
type=str,
|
|
277
|
+
default="2G",
|
|
278
|
+
help="The maximal amount of memory used for caching",
|
|
279
|
+
)
|
|
280
|
+
server_args["cache_max_size_single_entry"] = arg(
|
|
281
|
+
"--cache-max-size-single-entry",
|
|
282
|
+
type=str,
|
|
283
|
+
default="1G",
|
|
284
|
+
help="The maximal amount of memory used for caching a single "
|
|
285
|
+
"query result",
|
|
286
|
+
)
|
|
287
|
+
server_args["cache_max_num_entries"] = arg(
|
|
288
|
+
"--cache-max-num-entries",
|
|
289
|
+
type=int,
|
|
290
|
+
default=200,
|
|
291
|
+
help="The maximal number of entries in the cache"
|
|
292
|
+
" (the eviction policy when the cache is full is LRU)",
|
|
293
|
+
)
|
|
294
|
+
server_args["timeout"] = arg(
|
|
295
|
+
"--timeout",
|
|
296
|
+
type=str,
|
|
297
|
+
default="30s",
|
|
298
|
+
help="The maximal time in seconds a query is allowed to run"
|
|
299
|
+
" (can be increased per query with the URL parameters "
|
|
300
|
+
"`timeout` and `access_token`)",
|
|
301
|
+
)
|
|
302
|
+
server_args["num_threads"] = arg(
|
|
303
|
+
"--num-threads",
|
|
304
|
+
type=int,
|
|
305
|
+
default=8,
|
|
306
|
+
help="The number of threads used for query processing",
|
|
307
|
+
)
|
|
308
|
+
server_args["persist_updates"] = arg(
|
|
309
|
+
"--persist-updates",
|
|
310
|
+
action="store_true",
|
|
311
|
+
default=False,
|
|
312
|
+
help="Persist updates to the index (write updates to disk and "
|
|
313
|
+
"read them back in when restarting the server)",
|
|
314
|
+
)
|
|
315
|
+
server_args["only_pso_and_pos_permutations"] = arg(
|
|
316
|
+
"--only-pso-and-pos-permutations",
|
|
317
|
+
action="store_true",
|
|
318
|
+
default=False,
|
|
319
|
+
help="Only use the PSO and POS permutations (then each "
|
|
320
|
+
"triple pattern must have a fixed predicate)",
|
|
321
|
+
)
|
|
322
|
+
server_args["use_patterns"] = arg(
|
|
323
|
+
"--use-patterns",
|
|
324
|
+
choices=["yes", "no"],
|
|
325
|
+
default="yes",
|
|
326
|
+
help="Whether to use the patterns precomputed during the index "
|
|
327
|
+
"build (see `qlever index --help` for their utility)",
|
|
328
|
+
)
|
|
329
|
+
server_args["use_text_index"] = arg(
|
|
330
|
+
"--use-text-index",
|
|
331
|
+
choices=["yes", "no"],
|
|
332
|
+
default="no",
|
|
333
|
+
help="Whether to use the text index (requires that one was "
|
|
334
|
+
"built, see `qlever index`)",
|
|
335
|
+
)
|
|
336
|
+
server_args["warmup_cmd"] = arg(
|
|
337
|
+
"--warmup-cmd",
|
|
338
|
+
type=str,
|
|
339
|
+
help="Command executed after the server has started "
|
|
340
|
+
" (executed as part of `qlever start` unless "
|
|
341
|
+
" `--no-warmup` is specified, or with `qlever warmup`)",
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
runtime_args["system"] = arg(
|
|
345
|
+
"--system",
|
|
346
|
+
type=str,
|
|
347
|
+
choices=Containerize.supported_systems() + ["native"],
|
|
348
|
+
default="docker",
|
|
349
|
+
help=(
|
|
350
|
+
"Whether to run commands like `index` or `start` "
|
|
351
|
+
"natively or in a container, and if in a container, "
|
|
352
|
+
"which system to use"
|
|
353
|
+
),
|
|
354
|
+
)
|
|
355
|
+
runtime_args["image"] = arg(
|
|
356
|
+
"--image",
|
|
357
|
+
type=str,
|
|
358
|
+
default="docker.io/adfreiburg/qlever",
|
|
359
|
+
help="The name of the image when running in a container",
|
|
360
|
+
)
|
|
361
|
+
runtime_args["index_container"] = arg(
|
|
362
|
+
"--index-container",
|
|
363
|
+
type=str,
|
|
364
|
+
help=f"The name of the container used by `{script_name} index`",
|
|
365
|
+
)
|
|
366
|
+
runtime_args["server_container"] = arg(
|
|
367
|
+
"--server-container",
|
|
368
|
+
type=str,
|
|
369
|
+
help=f"The name of the container used by `{script_name} start`",
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
ui_args["ui_port"] = arg(
|
|
373
|
+
"--ui-port",
|
|
374
|
+
type=int,
|
|
375
|
+
default=8176,
|
|
376
|
+
help="The port of the Qlever UI when running `qlever ui`",
|
|
377
|
+
)
|
|
378
|
+
ui_args["ui_config"] = arg(
|
|
379
|
+
"--ui-config",
|
|
380
|
+
type=str,
|
|
381
|
+
default="default",
|
|
382
|
+
help="The name of the backend configuration for the QLever UI"
|
|
383
|
+
" (this determines AC queries and example queries)",
|
|
384
|
+
)
|
|
385
|
+
ui_args["ui_system"] = arg(
|
|
386
|
+
"--ui-system",
|
|
387
|
+
type=str,
|
|
388
|
+
choices=Containerize.supported_systems(),
|
|
389
|
+
default="docker",
|
|
390
|
+
help="Which container system to use for `qlever ui`"
|
|
391
|
+
" (unlike for `qlever index` and `qlever start`, "
|
|
392
|
+
' "native" is not yet supported here)',
|
|
393
|
+
)
|
|
394
|
+
ui_args["ui_image"] = arg(
|
|
395
|
+
"--ui-image",
|
|
396
|
+
type=str,
|
|
397
|
+
default="docker.io/adfreiburg/qlever-ui",
|
|
398
|
+
help="The name of the image used for `qlever ui`",
|
|
399
|
+
)
|
|
400
|
+
ui_args["ui_container"] = arg(
|
|
401
|
+
"--ui-container",
|
|
402
|
+
type=str,
|
|
403
|
+
help="The name of the container used for `qlever ui`",
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
return all_args
|
|
407
|
+
|
|
408
|
+
@staticmethod
|
|
409
|
+
def read(qleverfile_path):
|
|
410
|
+
"""
|
|
411
|
+
Read the given Qleverfile (the function assumes that it exists) and
|
|
412
|
+
return a `ConfigParser` object with all the options and their values.
|
|
413
|
+
|
|
414
|
+
NOTE: The keys have the same hierarchical structure as the keys in
|
|
415
|
+
`all_arguments()`. The Qleverfile may contain options that are not
|
|
416
|
+
defined in `all_arguments()`. They can be used as temporary variables
|
|
417
|
+
to define other options, but cannot be accessed by the commands later.
|
|
418
|
+
"""
|
|
419
|
+
|
|
420
|
+
# Read the Qleverfile.
|
|
421
|
+
defaults = {"random": "83724324hztz", "version": "01.01.01"}
|
|
422
|
+
config = ConfigParser(
|
|
423
|
+
interpolation=ExtendedInterpolation(), defaults=defaults
|
|
424
|
+
)
|
|
425
|
+
try:
|
|
426
|
+
config.read(qleverfile_path)
|
|
427
|
+
except Exception as e:
|
|
428
|
+
raise QleverfileException(f"Error parsing {qleverfile_path}: {e}")
|
|
429
|
+
|
|
430
|
+
# Iterate over all sections and options and check if there are any
|
|
431
|
+
# values of the form $$(...) that need to be replaced.
|
|
432
|
+
for section in config.sections():
|
|
433
|
+
for option in config[section]:
|
|
434
|
+
value = config[section][option]
|
|
435
|
+
match = re.match(r"^\$\((.*)\)$", value)
|
|
436
|
+
if match:
|
|
437
|
+
try:
|
|
438
|
+
value = subprocess.check_output(
|
|
439
|
+
match.group(1),
|
|
440
|
+
shell=True,
|
|
441
|
+
text=True,
|
|
442
|
+
stderr=subprocess.STDOUT,
|
|
443
|
+
).strip()
|
|
444
|
+
except Exception as e:
|
|
445
|
+
log.info("")
|
|
446
|
+
log.error(
|
|
447
|
+
f"Error evaluating {value} for option "
|
|
448
|
+
f"{section}.{option.upper()} in "
|
|
449
|
+
f"{qleverfile_path}:"
|
|
450
|
+
)
|
|
451
|
+
log.info("")
|
|
452
|
+
log.info(e.output if hasattr(e, "output") else e)
|
|
453
|
+
exit(1)
|
|
454
|
+
config[section][option] = value
|
|
455
|
+
|
|
456
|
+
# Make sure that all the sections are there.
|
|
457
|
+
for section in ["data", "index", "server", "runtime", "ui"]:
|
|
458
|
+
if section not in config:
|
|
459
|
+
config[section] = {}
|
|
460
|
+
|
|
461
|
+
# Add default values that are based on other values.
|
|
462
|
+
if "name" in config["data"]:
|
|
463
|
+
name = config["data"]["name"]
|
|
464
|
+
runtime = config["runtime"]
|
|
465
|
+
if "server_container" not in runtime:
|
|
466
|
+
runtime["server_container"] = f"{script_name}.server.{name}"
|
|
467
|
+
if "index_container" not in runtime:
|
|
468
|
+
runtime["index_container"] = f"{script_name}.index.{name}"
|
|
469
|
+
if "ui_container" not in config["ui"]:
|
|
470
|
+
config["ui"]["ui_container"] = f"qlever.ui.{name}"
|
|
471
|
+
index = config["index"]
|
|
472
|
+
if "text_words_file" not in index:
|
|
473
|
+
index["text_words_file"] = f"{name}.wordsfile.tsv"
|
|
474
|
+
if "text_docs_file" not in index:
|
|
475
|
+
index["text_docs_file"] = f"{name}.docsfile.tsv"
|
|
476
|
+
server = config["server"]
|
|
477
|
+
if index.get("text_index", "none") != "none":
|
|
478
|
+
server["use_text_index"] = "yes"
|
|
479
|
+
if index.get("only_pso_and_pos_permutations", "false") == "true":
|
|
480
|
+
index["use_patterns"] = "no"
|
|
481
|
+
if index.get("use_patterns", None) == "no":
|
|
482
|
+
server["use_patterns"] = "no"
|
|
483
|
+
|
|
484
|
+
# Add other non-trivial default values.
|
|
485
|
+
try:
|
|
486
|
+
if config["server"].get("host_name") is None:
|
|
487
|
+
config["server"]["host_name"] = socket.gethostname()
|
|
488
|
+
except Exception:
|
|
489
|
+
log.warning(
|
|
490
|
+
"Could not get the hostname, using `localhost` as default"
|
|
491
|
+
)
|
|
492
|
+
pass
|
|
493
|
+
|
|
494
|
+
# Return the parsed Qleverfile with the added inherited values.
|
|
495
|
+
return config
|
|
496
|
+
|
|
497
|
+
@staticmethod
|
|
498
|
+
def filter(
|
|
499
|
+
qleverfile_path: Path, options_included: dict[str, list[str]]
|
|
500
|
+
) -> RawConfigParser:
|
|
501
|
+
"""
|
|
502
|
+
Given a filter criteria (key: section_header, value: list[options]),
|
|
503
|
+
return a RawConfigParser object to create a new filtered Qleverfile
|
|
504
|
+
with only the specified sections and options (selects all options if
|
|
505
|
+
list[options] is empty). Mainly to be used by non-qlever scripts for
|
|
506
|
+
the setup-config command
|
|
507
|
+
"""
|
|
508
|
+
# Read the Qleverfile.
|
|
509
|
+
config = RawConfigParser()
|
|
510
|
+
config.optionxform = str # Preserve case sensitivity of keys
|
|
511
|
+
config.read(qleverfile_path)
|
|
512
|
+
|
|
513
|
+
filtered_config = RawConfigParser()
|
|
514
|
+
filtered_config.optionxform = str
|
|
515
|
+
|
|
516
|
+
for section, desired_fields in options_included.items():
|
|
517
|
+
if config.has_section(section):
|
|
518
|
+
filtered_config.add_section(section)
|
|
519
|
+
|
|
520
|
+
# If the list is empty, copy all fields
|
|
521
|
+
if not desired_fields:
|
|
522
|
+
for field, value in config.items(section):
|
|
523
|
+
filtered_config.set(section, field, value)
|
|
524
|
+
else:
|
|
525
|
+
for desired_field in desired_fields:
|
|
526
|
+
if config.has_option(section, desired_field):
|
|
527
|
+
value = config.get(section, desired_field)
|
|
528
|
+
filtered_config.set(section, desired_field, value)
|
|
529
|
+
|
|
530
|
+
return filtered_config
|