ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Generators
GeneratorConfig
python
GeneratorSettingsSemantics.py
Go to the documentation of this file.
1
# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
2
3
from
enum
import
Enum, IntEnum
4
import
re
5
6
from
GaudiConfig2.semantics
import
getSemanticsFor, SequenceSemantics
7
from
AthenaCommon.Logging
import
logging
8
9
genSettingsLog = logging.getLogger(
"GeneratorSettingsSemantics"
)
10
11
12
class
GeneratorSettingsKeep
(str, Enum):
13
"""
14
Which duplicate setting survives after layers are sorted by precedence.
15
16
Layers are resolved in increasing precedence order: BASE, then TUNE, then
17
USER. A duplicate is either a parsed command with the same normalized key,
18
or an unparsed command with the same normalized full text.
19
20
FIRST keeps the first duplicate encountered. This preserves lower-precedence
21
defaults when later layers repeat the same setting.
22
23
LAST keeps the last duplicate encountered. This is the normal generator
24
behavior: tune settings override base settings, and user settings override
25
both.
26
"""
27
FIRST =
"first"
28
LAST =
"last"
29
30
31
class
GeneratorSettingsRecord
(str, Enum):
32
"""
33
How one command string is understood during merging.
34
35
Each command is parsed with the separators from GeneratorSettingsLayer.
36
Commands that contain one of those separators are treated as parsed
37
key/value commands, e.g. "Main:timesAllowErrors = 500". These can override
38
each other by key.
39
40
Commands without any configured separator are unparsed commands. They have
41
no key, so they can only be deduplicated when their normalized full text is
42
identical.
43
"""
44
PARSED_COMMAND =
"parsed_command"
45
UNPARSED_COMMAND =
"unparsed_command"
46
47
48
class
GeneratorSettingsPrecedence
(IntEnum):
49
"""
50
Precedence levels for generator settings layers.
51
Lower precedence layers are overridden by higher ones during merging.
52
"""
53
BASE = 10
54
TUNE = 20
55
MATCHING = 30
56
WEIGHTS = 40
57
USER = 100
58
59
60
class
GeneratorSettingsLayer
:
61
"""
62
A layer contains all generator settings from a single source,
63
e.g. a user fragment, tune, etc.
64
65
Normal assignments still use a plain sequence of strings. Layers are only
66
needed by configuration fragments that want to describe where commands came
67
from and how they should be ordered during CA merging.
68
"""
69
70
def
__init__
(self,
71
source,
72
values,
73
precedence,
74
separators="=",
75
keep=GeneratorSettingsKeep.LAST,
76
report_context=None):
77
if
isinstance(values, str):
78
raise
TypeError(
"GeneratorSettingsLayer values must be a sequence"
)
79
80
# Label used in conflict/duplicate reports
81
self.
source
= str(source)
82
83
# Generator command strings belonging to this layer
84
self.
values
= tuple(values
or
())
85
86
# Precedence used for deduplication and conflict resolution during merging
87
self.
precedence
=
GeneratorSettingsPrecedence
(precedence)
88
89
# Separators used to parse a generator setting command into a key/value
90
# pair for duplicate detection
91
if
isinstance(separators, str):
92
separators = [separators]
93
self.
separators
= tuple(separators)
94
95
# Which matching key wins after sorting by layer precedence
96
self.
keep
=
GeneratorSettingsKeep
(keep)
97
98
# Text that should be mentioned in the deduplication report,
99
# usually the property name from the fragment.
100
self.
report_context
= report_context
101
102
103
class
GeneratorSettingsValue
:
104
"""
105
Stored property value used by GeneratorSettingsSemantics.
106
107
It keeps the unresolved layers rather than a pre-merged list so that
108
CA merges remain associative: base.merge(user) and user.merge(base)
109
yield the same result.
110
"""
111
def
__init__
(self, layers=None):
112
self.
layers
= []
113
self.
_reported_contexts
=
set
()
114
seen =
set
()
115
116
for
layer
in
layers
or
():
117
if
not
isinstance(layer, GeneratorSettingsLayer):
118
layer_type =
type
(layer).__name__
119
raise
TypeError(
120
f
"GeneratorSettingsValue layers must be "
121
f
"GeneratorSettingsLayer instances, got {layer_type}"
122
)
123
124
# Deduplicate identical layers explicitly instead of relying on
125
# object identity. This is what makes repeated symmetric CA merges
126
# yield the same result.
127
key = (
128
layer.source,
129
layer.values,
130
layer.precedence,
131
layer.separators,
132
layer.keep,
133
layer.report_context,
134
)
135
if
key
not
in
seen:
136
self.
layers
.append(layer)
137
seen.add(key)
138
139
@property
140
def
data(self):
141
return
self.
resolve
()
142
143
def
resolve
(self, report_context=None, emit_report=False):
144
"""
145
Resolve all layers to the final settings list.
146
147
If emit_report is True, print duplicate/conflict warnings once using
148
report_context (or a layer-provided report_context if available).
149
"""
150
settings, report = self.
_resolve
()
151
152
if
emit_report:
153
for
settings_layer
in
_ordered_layers
(self.
layers
):
154
if
settings_layer.report_context:
155
report_context = settings_layer.report_context
156
break
157
158
if
report_context
and
report_context
not
in
self.
_reported_contexts
:
159
_log_report
(report_context, report)
160
self.
_reported_contexts
.
add
(report_context)
161
162
return
settings
163
164
def
__str__
(self):
165
"""
166
Return the resolved list as a string.
167
ComponentAccumulator.gatherProps() converts stored property values
168
to strings before handing them to Gaudi.
169
"""
170
return
str(self.
resolve
(emit_report=
True
))
171
172
def
_resolve
(self):
173
"""Return the final command list plus the duplicate/conflict report."""
174
layers =
_ordered_layers
(self.
layers
)
175
separators = layers[0].separators
if
layers
else
(
"="
,)
176
keep = layers[0].keep
if
layers
else
GeneratorSettingsKeep.LAST
177
precedences_seen = {}
178
for
layer
in
layers:
179
if
(
180
layer.separators == separators
181
and
layer.keep == keep
182
):
183
if
layer.precedence
in
precedences_seen:
184
previous_layer = precedences_seen[layer.precedence]
185
raise
ValueError(
186
f
"cannot merge generator settings with duplicate "
187
f
"precedence {layer.precedence.name}: "
188
f
"{previous_layer.source} and {layer.source}"
189
)
190
precedences_seen[layer.precedence] = layer
191
continue
192
193
summary =
", "
.join(
194
f
"{entry.source}: separators={entry.separators}, "
195
f
"keep={entry.keep.value}"
196
for
entry
in
layers
197
)
198
raise
ValueError(
199
f
"cannot merge generator settings with different parsing "
200
f
"settings: "
201
f
"{summary}"
202
)
203
204
records =
_build_records
(layers, separators)
205
kept_records, removed_records =
_deduplicate_records
(records, keep)
206
return
(
207
[record[
"original_setting"
]
for
record
in
kept_records],
208
_build_report
(records, kept_records, removed_records),
209
)
210
211
212
class
GeneratorSettingsSemantics
(SequenceSemantics):
213
"""
214
Semantics for generator settings properties.
215
216
Gaudi sees the property as a sequence of strings, but CA merging receives
217
GeneratorSettingsLayer objects so fragments can be combined by precedence
218
before the final list is handed to the C++ component.
219
"""
220
__handled_types__ = [re.compile(
r"^GeneratorSettings<.*>$"
)]
221
222
def
__init__
(self, cpp_type):
223
# SequenceSemantics needs the element semantics even though we store a
224
# custom helper value instead of Gaudi's normal list helper.
225
super().
__init__
(cpp_type, valueSem=getSemanticsFor(
"std::string"
))
226
227
def
store
(self, assigned_value):
228
"""Convert user input into the internal unresolved layer container."""
229
if
isinstance(assigned_value, GeneratorSettingsValue):
230
return
assigned_value
231
if
isinstance(assigned_value, GeneratorSettingsLayer):
232
return
GeneratorSettingsValue
([assigned_value])
233
if
isinstance(assigned_value, str):
234
raise
TypeError(
"generator settings must be assigned from a sequence"
)
235
return
GeneratorSettingsValue
([
236
GeneratorSettingsLayer
(
237
source=self.name
or
"<unknown>"
,
238
values=tuple(assigned_value
or
()),
239
precedence=GeneratorSettingsPrecedence.USER,
240
report_context=self.name,
241
)
242
])
243
244
def
default
(self, default_commands):
245
"""Store C++ defaults as the lowest-precedence command layer."""
246
if
not
default_commands:
247
return
GeneratorSettingsValue
()
248
if
isinstance(default_commands, str):
249
raise
TypeError(
"generator settings must be assigned from a sequence"
)
250
return
GeneratorSettingsValue
([
251
GeneratorSettingsLayer
(
252
source=self.name
or
"<default>"
,
253
values=tuple(default_commands
or
()),
254
precedence=GeneratorSettingsPrecedence.BASE,
255
report_context=self.name,
256
)
257
])
258
259
def
merge
(self, current_value, incoming_value):
260
"""Merge two unresolved layer sets during CA merging."""
261
current_settings = self.
store
(current_value)
262
incoming_settings = self.
store
(incoming_value)
263
return
GeneratorSettingsValue
(
264
current_settings.layers + incoming_settings.layers
265
)
266
267
def
opt_value
(self, stored_value):
268
"""
269
Return the final plain command list.
270
This is the point where all layers are resolved.
271
Print duplicate and conflict warnings here.
272
"""
273
settings_value = self.
store
(stored_value)
274
return
settings_value.resolve(report_context=self.name, emit_report=
True
)
275
276
277
def
_ordered_layers
(layers):
278
"""Apply precedence before deduplication."""
279
return
sorted(
280
layers,
281
key=
lambda
layer: (
282
int(layer.precedence),
283
layer.source,
284
repr(layer.values),
285
),
286
)
287
288
289
def
_build_records
(layers, separators):
290
"""
291
Convert raw command strings into normalized records.
292
Parsed commands are deduplicated by key. Commands that cannot be parsed as
293
key/value records are deduplicated by their normalized full text.
294
"""
295
records = []
296
for
layer
in
layers:
297
for
raw_setting
in
layer.values:
298
key_text, value_text =
_parse_assignment
(raw_setting, separators)
299
if
key_text
is
None
:
300
records.append({
301
"source_name"
: layer.source,
302
"record_kind"
: GeneratorSettingsRecord.UNPARSED_COMMAND,
303
"normalized_key"
:
None
,
304
"normalized_value"
:
None
,
305
"original_setting"
: raw_setting,
306
"dedup_signature"
: (
307
GeneratorSettingsRecord.UNPARSED_COMMAND,
308
_normalize_text
(raw_setting),
309
),
310
})
311
continue
312
313
normalized_key =
_normalize_text
(key_text)
314
records.append({
315
"source_name"
: layer.source,
316
"record_kind"
: GeneratorSettingsRecord.PARSED_COMMAND,
317
"normalized_key"
: normalized_key,
318
"normalized_value"
:
_normalize_text
(value_text),
319
"original_setting"
: raw_setting,
320
"dedup_signature"
: (
321
GeneratorSettingsRecord.PARSED_COMMAND,
322
normalized_key,
323
),
324
})
325
return
records
326
327
328
def
_parse_assignment
(setting_text, separators):
329
text = str(setting_text).
strip
()
330
for
separator
in
separators:
331
if
separator
in
text:
332
key_text, value_text = text.split(separator, 1)
333
return
key_text.strip(), value_text.strip()
334
return
None
,
None
335
336
337
def
_normalize_text
(value):
338
text = str(value).
strip
()
339
return
" "
.join(text.split())
340
341
342
def
_deduplicate_records
(records, keep):
343
"""Keep the first or last record for each normalized setting key."""
344
keep_last = keep == GeneratorSettingsKeep.LAST
345
records_to_scan = reversed(records)
if
keep_last
else
records
346
347
kept_records = []
348
removed_records = []
349
first_seen_by_signature = {}
350
for
record
in
records_to_scan:
351
signature = record[
"dedup_signature"
]
352
if
signature
in
first_seen_by_signature:
353
kept_record = first_seen_by_signature[signature]
354
removed_record = dict(record)
355
removed_record[
"duplicate_of_source_name"
] = kept_record[
"source_name"
]
356
removed_record[
"kept_normalized_value"
] = kept_record[
"normalized_value"
]
357
removed_record[
"kept_original_setting"
] = kept_record[
"original_setting"
]
358
removed_records.append(removed_record)
359
continue
360
361
first_seen_by_signature[signature] = record
362
kept_records.append(record)
363
364
if
keep_last:
365
kept_records.reverse()
366
removed_records.reverse()
367
return
kept_records, removed_records
368
369
370
def
_build_report
(records, kept_records, removed_records):
371
"""Collect duplicate and conflict information for logging/tests."""
372
removed_duplicates = [
373
{
374
"source"
: record[
"source_name"
],
375
"duplicate_of_source"
: record.get(
"duplicate_of_source_name"
),
376
"setting"
: record[
"original_setting"
],
377
"kept_setting"
: record.get(
"kept_original_setting"
),
378
"normalized_value"
: record[
"normalized_value"
],
379
"kept_normalized_value"
: record.get(
"kept_normalized_value"
),
380
}
381
for
record
in
removed_records
382
]
383
384
removed_identical = [
385
{
386
"source"
: record[
"source"
],
387
"duplicate_of_source"
: record.get(
"duplicate_of_source"
),
388
"setting"
: record[
"setting"
],
389
"kept_setting"
: record.get(
"kept_setting"
),
390
}
391
for
record
in
removed_duplicates
392
if
record[
"normalized_value"
] == record.get(
"kept_normalized_value"
)
393
]
394
duplicates_in_source = {}
395
duplicates_across_sources = {}
396
397
for
record
in
removed_identical:
398
source_name = record.get(
"source"
,
"<unknown>"
)
399
duplicate_of_source = record.get(
"duplicate_of_source"
,
"<unknown>"
)
400
if
duplicate_of_source == source_name:
401
duplicates_in_source[source_name] = (
402
duplicates_in_source.get(source_name, 0) + 1
403
)
404
continue
405
406
source_pair = (source_name, duplicate_of_source)
407
duplicates_across_sources[source_pair] = (
408
duplicates_across_sources.get(source_pair, 0) + 1
409
)
410
411
conflict_details =
_build_conflict_details
(records, kept_records)
412
413
return
{
414
"removed_duplicates"
: removed_duplicates,
415
"removed_identical"
: removed_identical,
416
"conflicting_reassignments"
: [
417
record
418
for
record
in
removed_duplicates
419
if
record[
"normalized_value"
] != record.get(
"kept_normalized_value"
)
420
],
421
"removed_overridden"
: [
422
record
423
for
record
in
removed_duplicates
424
if
record[
"normalized_value"
] != record.get(
"kept_normalized_value"
)
425
],
426
"conflict_details"
: conflict_details,
427
"conflicts"
:
_find_conflicts
(records),
428
"duplicates_in_source"
: duplicates_in_source,
429
"duplicates_across_sources"
: [
430
{
431
"source"
: source_name,
432
"duplicate_of_source"
: duplicate_of_source,
433
"count"
: duplicate_count,
434
}
435
for
(source_name, duplicate_of_source), duplicate_count
436
in
sorted(duplicates_across_sources.items())
437
],
438
}
439
440
441
def
_build_conflict_details
(records, kept_records):
442
"""
443
Build one reporting entry per conflicting parsed key.
444
445
The source and value order follows the original record order, and the kept
446
value is marked explicitly in the value list.
447
"""
448
kept_value_by_key = {}
449
for
record
in
kept_records:
450
if
record[
"record_kind"
] != GeneratorSettingsRecord.PARSED_COMMAND:
451
continue
452
kept_value_by_key[record[
"normalized_key"
]] = record[
"normalized_value"
]
453
454
values_by_key = {}
455
for
record
in
records:
456
if
record[
"record_kind"
] != GeneratorSettingsRecord.PARSED_COMMAND:
457
continue
458
459
key = record[
"normalized_key"
]
460
source_name = record[
"source_name"
]
461
value = record[
"normalized_value"
]
462
463
key_entry = values_by_key.setdefault(
464
key,
465
{
466
"sources"
: [],
467
"source_set"
:
set
(),
468
"values"
: [],
469
"value_set"
:
set
(),
470
"source_to_values"
: {},
471
},
472
)
473
if
source_name
not
in
key_entry[
"source_set"
]:
474
key_entry[
"source_set"
].
add
(source_name)
475
key_entry[
"sources"
].append(source_name)
476
if
value
not
in
key_entry[
"value_set"
]:
477
key_entry[
"value_set"
].
add
(value)
478
key_entry[
"values"
].append(value)
479
key_entry[
"source_to_values"
].setdefault(source_name,
set
()).
add
(value)
480
481
conflict_details = []
482
for
key, key_entry
in
values_by_key.items():
483
merged_values =
set
()
484
for
values
in
key_entry[
"source_to_values"
].values():
485
merged_values.update(values)
486
if
len(merged_values) <= 1
or
len(key_entry[
"source_to_values"
]) <= 1:
487
continue
488
489
kept_value = kept_value_by_key.get(key)
490
marked_values = []
491
for
value
in
key_entry[
"values"
]:
492
if
value == kept_value:
493
marked_values.append(f
"{value} (kept)"
)
494
continue
495
marked_values.append(value)
496
497
conflict_details.append({
498
"key"
: key,
499
"sources"
: key_entry[
"sources"
],
500
"values"
: marked_values,
501
})
502
return
conflict_details
503
504
505
def
_find_conflicts
(records):
506
"""Find keys assigned to multiple values within or across sources."""
507
values_by_key_and_source = {}
508
for
record
in
records:
509
if
record[
"record_kind"
] != GeneratorSettingsRecord.PARSED_COMMAND:
510
continue
511
512
key = record[
"normalized_key"
]
513
source_name = record[
"source_name"
]
514
value = record[
"normalized_value"
]
515
values_by_key_and_source.setdefault(key, {}).setdefault(
516
source_name,
517
set
(),
518
).
add
(value)
519
520
conflicts = []
521
for
key, source_to_values
in
values_by_key_and_source.items():
522
for
source_name, values
in
source_to_values.items():
523
if
len(values) > 1:
524
conflicts.append({
525
"type"
:
"intra_source_conflict"
,
526
"key"
: key,
527
"source"
: source_name,
528
"values"
: sorted(values),
529
})
530
531
merged_values =
set
()
532
for
values
in
source_to_values.values():
533
merged_values.update(values)
534
if
len(merged_values) > 1
and
len(source_to_values) > 1:
535
conflicts.append({
536
"type"
:
"inter_source_conflict"
,
537
"key"
: key,
538
"sources"
: sorted(source_to_values.keys()),
539
"values"
: sorted(merged_values),
540
})
541
return
conflicts
542
543
544
def
_log_report
(context, report):
545
"""Print warnings from the structured report."""
546
issue_prefix =
"Potential issue with generator settings"
547
548
duplicates = report.get(
"removed_identical"
, [])
549
conflict_details = report.get(
"conflict_details"
, [])
550
if
not
duplicates
and
not
conflict_details:
551
return
552
553
genSettingsLog.warning(
554
f
"{issue_prefix} [{context}]: found {len(duplicates)} duplicate "
555
f
"setting(s) across sources and {len(conflict_details)} conflicting "
556
f
"setting key(s)"
557
)
558
559
for
entry
in
sorted(
560
duplicates,
561
key=
lambda
record: (
562
record.get(
"source"
,
""
),
563
record.get(
"duplicate_of_source"
,
""
),
564
record.get(
"setting"
,
""
),
565
),
566
):
567
source_name = entry.get(
"source"
,
"<unknown>"
)
568
duplicate_of_source = entry.get(
"duplicate_of_source"
,
"<unknown>"
)
569
setting = entry.get(
"setting"
,
"<unknown>"
)
570
source_list = [source_name]
571
if
duplicate_of_source != source_name:
572
source_list.append(duplicate_of_source)
573
genSettingsLog.warning(
574
f
"{issue_prefix} [{context}]: duplicate setting from sources "
575
f
"[{', '.join(source_list)}]: {setting}"
576
)
577
578
for
entry
in
conflict_details:
579
key = entry.get(
"key"
,
"<unknown>"
)
580
sources =
", "
.join(entry.get(
"sources"
, []))
581
values =
", "
.join(entry.get(
"values"
, []))
582
genSettingsLog.warning(
583
f
"{issue_prefix} [{context}]: conflicting setting '{key}' across "
584
f
"sources [{sources}] -> [{values}]"
585
)
SiliconTech::strip
@ strip
Definition
FPGATrackSimTypes.h:25
python.GeneratorSettingsSemantics.GeneratorSettingsKeep
Definition
GeneratorSettingsSemantics.py:12
python.GeneratorSettingsSemantics.GeneratorSettingsLayer
Definition
GeneratorSettingsSemantics.py:60
python.GeneratorSettingsSemantics.GeneratorSettingsLayer.__init__
__init__(self, source, values, precedence, separators="=", keep=GeneratorSettingsKeep.LAST, report_context=None)
Definition
GeneratorSettingsSemantics.py:76
python.GeneratorSettingsSemantics.GeneratorSettingsLayer.separators
separators
Definition
GeneratorSettingsSemantics.py:93
python.GeneratorSettingsSemantics.GeneratorSettingsLayer.source
source
Definition
GeneratorSettingsSemantics.py:81
python.GeneratorSettingsSemantics.GeneratorSettingsLayer.report_context
report_context
Definition
GeneratorSettingsSemantics.py:100
python.GeneratorSettingsSemantics.GeneratorSettingsLayer.values
values
Definition
GeneratorSettingsSemantics.py:84
python.GeneratorSettingsSemantics.GeneratorSettingsLayer.keep
keep
Definition
GeneratorSettingsSemantics.py:96
python.GeneratorSettingsSemantics.GeneratorSettingsLayer.precedence
precedence
Definition
GeneratorSettingsSemantics.py:87
python.GeneratorSettingsSemantics.GeneratorSettingsPrecedence
Definition
GeneratorSettingsSemantics.py:48
python.GeneratorSettingsSemantics.GeneratorSettingsRecord
Definition
GeneratorSettingsSemantics.py:31
python.GeneratorSettingsSemantics.GeneratorSettingsSemantics
Definition
GeneratorSettingsSemantics.py:212
python.GeneratorSettingsSemantics.GeneratorSettingsSemantics.opt_value
opt_value(self, stored_value)
Definition
GeneratorSettingsSemantics.py:267
python.GeneratorSettingsSemantics.GeneratorSettingsSemantics.store
store(self, assigned_value)
Definition
GeneratorSettingsSemantics.py:227
python.GeneratorSettingsSemantics.GeneratorSettingsSemantics.default
default(self, default_commands)
Definition
GeneratorSettingsSemantics.py:244
python.GeneratorSettingsSemantics.GeneratorSettingsSemantics.__init__
__init__(self, cpp_type)
Definition
GeneratorSettingsSemantics.py:222
python.GeneratorSettingsSemantics.GeneratorSettingsValue
Definition
GeneratorSettingsSemantics.py:103
python.GeneratorSettingsSemantics.GeneratorSettingsValue.__init__
__init__(self, layers=None)
Definition
GeneratorSettingsSemantics.py:111
python.GeneratorSettingsSemantics.GeneratorSettingsValue._resolve
_resolve(self)
Definition
GeneratorSettingsSemantics.py:172
python.GeneratorSettingsSemantics.GeneratorSettingsValue.resolve
resolve(self, report_context=None, emit_report=False)
Definition
GeneratorSettingsSemantics.py:143
python.GeneratorSettingsSemantics.GeneratorSettingsValue._reported_contexts
_reported_contexts
Definition
GeneratorSettingsSemantics.py:113
python.GeneratorSettingsSemantics.GeneratorSettingsValue.__str__
__str__(self)
Definition
GeneratorSettingsSemantics.py:164
python.GeneratorSettingsSemantics.GeneratorSettingsValue.layers
list layers
Definition
GeneratorSettingsSemantics.py:112
set
STL class.
add
bool add(const std::string &hname, TKey *tobj)
Definition
fastadd.cxx:55
GaudiConfig2.semantics
merge
Definition
merge.py:1
python.GeneratorSettingsSemantics._build_records
_build_records(layers, separators)
Definition
GeneratorSettingsSemantics.py:289
python.GeneratorSettingsSemantics._deduplicate_records
_deduplicate_records(records, keep)
Definition
GeneratorSettingsSemantics.py:342
python.GeneratorSettingsSemantics._ordered_layers
_ordered_layers(layers)
Definition
GeneratorSettingsSemantics.py:277
python.GeneratorSettingsSemantics._find_conflicts
_find_conflicts(records)
Definition
GeneratorSettingsSemantics.py:505
python.GeneratorSettingsSemantics._parse_assignment
_parse_assignment(setting_text, separators)
Definition
GeneratorSettingsSemantics.py:328
python.GeneratorSettingsSemantics._build_conflict_details
_build_conflict_details(records, kept_records)
Definition
GeneratorSettingsSemantics.py:441
python.GeneratorSettingsSemantics._normalize_text
_normalize_text(value)
Definition
GeneratorSettingsSemantics.py:337
python.GeneratorSettingsSemantics._log_report
_log_report(context, report)
Definition
GeneratorSettingsSemantics.py:544
python.GeneratorSettingsSemantics._build_report
_build_report(records, kept_records, removed_records)
Definition
GeneratorSettingsSemantics.py:370
type
Generated on
for ATLAS Offline Software by
1.17.0