@redpanda-data/docs-extensions-and-macros 4.11.0 → 4.12.0
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.
- package/bin/doc-tools.js +4 -2
- package/extensions/convert-to-markdown.js +17 -1
- package/package.json +3 -1
- package/tools/property-extractor/COMPUTED_CONSTANTS.md +173 -0
- package/tools/property-extractor/Makefile +12 -1
- package/tools/property-extractor/README.adoc +828 -97
- package/tools/property-extractor/compare-properties.js +38 -13
- package/tools/property-extractor/constant_resolver.py +610 -0
- package/tools/property-extractor/file_pair.py +42 -0
- package/tools/property-extractor/generate-handlebars-docs.js +41 -8
- package/tools/property-extractor/helpers/gt.js +9 -0
- package/tools/property-extractor/helpers/includes.js +17 -0
- package/tools/property-extractor/helpers/index.js +3 -0
- package/tools/property-extractor/helpers/isEnterpriseEnum.js +24 -0
- package/tools/property-extractor/helpers/renderPropertyExample.js +6 -5
- package/tools/property-extractor/overrides.json +248 -0
- package/tools/property-extractor/parser.py +254 -32
- package/tools/property-extractor/property_bag.py +40 -0
- package/tools/property-extractor/property_extractor.py +1417 -430
- package/tools/property-extractor/requirements.txt +1 -0
- package/tools/property-extractor/templates/property-backup.hbs +161 -0
- package/tools/property-extractor/templates/property.hbs +104 -49
- package/tools/property-extractor/templates/topic-property-backup.hbs +148 -0
- package/tools/property-extractor/templates/topic-property.hbs +72 -34
- package/tools/property-extractor/tests/test_known_values.py +617 -0
- package/tools/property-extractor/tests/transformers_test.py +81 -6
- package/tools/property-extractor/topic_property_extractor.py +23 -10
- package/tools/property-extractor/transformers.py +2191 -369
- package/tools/property-extractor/type_definition_extractor.py +669 -0
- package/tools/property-extractor/definitions.json +0 -245
|
@@ -109,8 +109,9 @@ class NeedsRestartTransformerTestCase(unittest.TestCase):
|
|
|
109
109
|
)
|
|
110
110
|
)
|
|
111
111
|
|
|
112
|
-
def
|
|
113
|
-
|
|
112
|
+
def test_accepts_without_needs_restart(self):
|
|
113
|
+
"""NeedsRestartTransformer now accepts all properties and applies defaults"""
|
|
114
|
+
self.assertTrue(
|
|
114
115
|
self.transformer.accepts(
|
|
115
116
|
create_property_info(
|
|
116
117
|
"test_property", "test description", "bool", PropertyBag()
|
|
@@ -251,21 +252,34 @@ class DeprecatedTransformerTestCase(unittest.TestCase):
|
|
|
251
252
|
def setUp(self):
|
|
252
253
|
self.transformer = DeprecatedTransformer()
|
|
253
254
|
|
|
254
|
-
def
|
|
255
|
+
def test_accepts_deprecated_metadata(self):
|
|
256
|
+
"""DeprecatedTransformer accepts properties with .deprecated in meta"""
|
|
255
257
|
self.assertTrue(
|
|
256
258
|
self.transformer.accepts(
|
|
257
259
|
create_property_info(
|
|
258
260
|
"test_property",
|
|
259
261
|
"test description",
|
|
260
262
|
"bool",
|
|
261
|
-
PropertyBag(
|
|
263
|
+
PropertyBag(deprecated="yes"),
|
|
262
264
|
),
|
|
263
265
|
None,
|
|
264
266
|
)
|
|
265
267
|
)
|
|
266
268
|
|
|
267
|
-
def
|
|
268
|
-
|
|
269
|
+
def test_rejects_without_deprecated_metadata(self):
|
|
270
|
+
"""DeprecatedTransformer rejects properties without .deprecated in meta"""
|
|
271
|
+
self.assertFalse(
|
|
272
|
+
self.transformer.accepts(
|
|
273
|
+
create_property_info(
|
|
274
|
+
"test_property",
|
|
275
|
+
"test description",
|
|
276
|
+
"bool",
|
|
277
|
+
PropertyBag(visibility="visibility::deprecated"),
|
|
278
|
+
),
|
|
279
|
+
None,
|
|
280
|
+
)
|
|
281
|
+
)
|
|
282
|
+
self.assertFalse(
|
|
269
283
|
self.transformer.accepts(
|
|
270
284
|
create_property_info(
|
|
271
285
|
"test_property",
|
|
@@ -372,5 +386,66 @@ class IsSecretTransformerTestCase(unittest.TestCase):
|
|
|
372
386
|
self.assertFalse(property["is_secret"])
|
|
373
387
|
|
|
374
388
|
|
|
389
|
+
class FriendlyDefaultTransformerTestCase(unittest.TestCase):
|
|
390
|
+
def setUp(self):
|
|
391
|
+
self.transformer = FriendlyDefaultTransformer()
|
|
392
|
+
|
|
393
|
+
def test_strips_unsigned_integer_suffix(self):
|
|
394
|
+
"""Test that C++ unsigned integer suffixes are stripped from defaults"""
|
|
395
|
+
property = PropertyBag()
|
|
396
|
+
info = create_property_info(
|
|
397
|
+
"test_property",
|
|
398
|
+
"test description",
|
|
399
|
+
"uint32_t",
|
|
400
|
+
PropertyBag(needs_restart="needs_restart::no"),
|
|
401
|
+
default_value="1024u",
|
|
402
|
+
default_value_type="number_literal"
|
|
403
|
+
)
|
|
404
|
+
self.transformer.parse(property, info, FilePair("testfile.h", "testfile.cc"))
|
|
405
|
+
self.assertEqual(1024, property["default"])
|
|
406
|
+
|
|
407
|
+
def test_strips_long_integer_suffix(self):
|
|
408
|
+
"""Test that C++ long integer suffixes are stripped from defaults"""
|
|
409
|
+
property = PropertyBag()
|
|
410
|
+
info = create_property_info(
|
|
411
|
+
"test_property",
|
|
412
|
+
"test description",
|
|
413
|
+
"int64_t",
|
|
414
|
+
PropertyBag(needs_restart="needs_restart::no"),
|
|
415
|
+
default_value="42L",
|
|
416
|
+
default_value_type="number_literal"
|
|
417
|
+
)
|
|
418
|
+
self.transformer.parse(property, info, FilePair("testfile.h", "testfile.cc"))
|
|
419
|
+
self.assertEqual(42, property["default"])
|
|
420
|
+
|
|
421
|
+
def test_strips_unsigned_long_long_suffix(self):
|
|
422
|
+
"""Test that C++ unsigned long long suffixes are stripped from defaults"""
|
|
423
|
+
property = PropertyBag()
|
|
424
|
+
info = create_property_info(
|
|
425
|
+
"test_property",
|
|
426
|
+
"test description",
|
|
427
|
+
"uint64_t",
|
|
428
|
+
PropertyBag(needs_restart="needs_restart::no"),
|
|
429
|
+
default_value="999ULL",
|
|
430
|
+
default_value_type="number_literal"
|
|
431
|
+
)
|
|
432
|
+
self.transformer.parse(property, info, FilePair("testfile.h", "testfile.cc"))
|
|
433
|
+
self.assertEqual(999, property["default"])
|
|
434
|
+
|
|
435
|
+
def test_strips_float_suffix(self):
|
|
436
|
+
"""Test that C++ float suffixes are stripped from defaults"""
|
|
437
|
+
property = PropertyBag()
|
|
438
|
+
info = create_property_info(
|
|
439
|
+
"test_property",
|
|
440
|
+
"test description",
|
|
441
|
+
"float",
|
|
442
|
+
PropertyBag(needs_restart="needs_restart::no"),
|
|
443
|
+
default_value="3.14f",
|
|
444
|
+
default_value_type="number_literal"
|
|
445
|
+
)
|
|
446
|
+
self.transformer.parse(property, info, FilePair("testfile.h", "testfile.cc"))
|
|
447
|
+
self.assertAlmostEqual(3.14, property["default"], places=2)
|
|
448
|
+
|
|
449
|
+
|
|
375
450
|
if __name__ == "__main__":
|
|
376
451
|
unittest.main()
|
|
@@ -107,7 +107,7 @@ class TopicPropertyExtractor:
|
|
|
107
107
|
self.topic_properties[property_name] = {
|
|
108
108
|
"variable_name": f"topic_property_{var_name}",
|
|
109
109
|
"property_name": property_name,
|
|
110
|
-
"
|
|
110
|
+
"defined_in": str(file_path.relative_to(self.source_path)),
|
|
111
111
|
"description": "",
|
|
112
112
|
"type": self._determine_property_type(property_name),
|
|
113
113
|
"acceptable_values": None,
|
|
@@ -120,6 +120,10 @@ class TopicPropertyExtractor:
|
|
|
120
120
|
|
|
121
121
|
def _scan_file_for_topic_properties(self, file_path: Path):
|
|
122
122
|
"""Scan any file for topic_property_ constants"""
|
|
123
|
+
# Skip admin proxy files - they contain RPC service definitions, not topic properties
|
|
124
|
+
if 'admin/proxy/' in str(file_path):
|
|
125
|
+
return
|
|
126
|
+
|
|
123
127
|
try:
|
|
124
128
|
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
|
|
125
129
|
content = f.read()
|
|
@@ -156,7 +160,7 @@ class TopicPropertyExtractor:
|
|
|
156
160
|
self.topic_properties[property_name] = {
|
|
157
161
|
"variable_name": f"topic_property_{var_name}",
|
|
158
162
|
"property_name": property_name,
|
|
159
|
-
"
|
|
163
|
+
"defined_in": str(file_path.relative_to(self.source_path)),
|
|
160
164
|
"description": "",
|
|
161
165
|
"type": self._determine_property_type(property_name),
|
|
162
166
|
"acceptable_values": None,
|
|
@@ -231,7 +235,7 @@ class TopicPropertyExtractor:
|
|
|
231
235
|
values = self._extract_enum_values(enum_body)
|
|
232
236
|
if values:
|
|
233
237
|
self.enum_values[enum_name] = {
|
|
234
|
-
"
|
|
238
|
+
"defined_in": str(file_path.relative_to(self.source_path)),
|
|
235
239
|
"values": values
|
|
236
240
|
}
|
|
237
241
|
|
|
@@ -243,7 +247,7 @@ class TopicPropertyExtractor:
|
|
|
243
247
|
values = self._extract_enum_values(enum_body)
|
|
244
248
|
if values:
|
|
245
249
|
self.enum_values[enum_name] = {
|
|
246
|
-
"
|
|
250
|
+
"defined_in": str(file_path.relative_to(self.source_path)),
|
|
247
251
|
"values": values
|
|
248
252
|
}
|
|
249
253
|
|
|
@@ -265,7 +269,7 @@ class TopicPropertyExtractor:
|
|
|
265
269
|
values = self._extract_enum_values(enum_body)
|
|
266
270
|
if values:
|
|
267
271
|
self.enum_values[enum_name] = {
|
|
268
|
-
"
|
|
272
|
+
"defined_in": str(file_path.relative_to(self.source_path)),
|
|
269
273
|
"values": values
|
|
270
274
|
}
|
|
271
275
|
except Exception as e:
|
|
@@ -273,14 +277,22 @@ class TopicPropertyExtractor:
|
|
|
273
277
|
|
|
274
278
|
def _is_valid_topic_property(self, prop_name: str) -> bool:
|
|
275
279
|
"""Validate that a string looks like a real topic property"""
|
|
276
|
-
|
|
280
|
+
|
|
277
281
|
# Must be non-empty and reasonable length
|
|
278
282
|
if not prop_name or len(prop_name) < 3 or len(prop_name) > 100:
|
|
279
283
|
return False
|
|
280
|
-
|
|
284
|
+
|
|
281
285
|
# Must contain only valid characters for topic properties
|
|
282
286
|
if not re.match(r'^[a-zA-Z][a-zA-Z0-9._-]*$', prop_name):
|
|
283
287
|
return False
|
|
288
|
+
|
|
289
|
+
# Reject Java-style package names (e.g., "redpanda.core.admin.Service")
|
|
290
|
+
# Topic properties use lowercase with dots (e.g., "cleanup.policy", "segment.ms")
|
|
291
|
+
# Split by dots and check each segment - reject if any segment after first has uppercase
|
|
292
|
+
segments = prop_name.split('.')
|
|
293
|
+
for i, segment in enumerate(segments):
|
|
294
|
+
if i > 0 and segment and segment[0].isupper():
|
|
295
|
+
return False
|
|
284
296
|
|
|
285
297
|
# Known topic property prefixes/patterns
|
|
286
298
|
valid_patterns = [
|
|
@@ -525,10 +537,11 @@ class TopicPropertyExtractor:
|
|
|
525
537
|
|
|
526
538
|
elif "timestamp.type" in prop_name:
|
|
527
539
|
return "[`CreateTime`, `LogAppendTime`]"
|
|
528
|
-
|
|
540
|
+
|
|
529
541
|
elif prop_data.get("type") == "boolean":
|
|
530
|
-
|
|
531
|
-
|
|
542
|
+
# Boolean properties don't need acceptable_values - it's redundant
|
|
543
|
+
return ""
|
|
544
|
+
|
|
532
545
|
# For numeric properties, determine format based on type and name
|
|
533
546
|
elif prop_data.get("type") == "number" and "ratio" in prop_name:
|
|
534
547
|
return "[`0`, `1.0`]"
|