Skip to content

Commit 67c497b

Browse files
committed
Merge branch 'config-prop-fixes' of https://github.com/redpanda-data/docs-extensions-and-macros into config-prop-fixes
2 parents f395f3c + 9874bd7 commit 67c497b

File tree

2 files changed

+153
-83
lines changed

2 files changed

+153
-83
lines changed

tools/property-extractor/property_extractor.py

Lines changed: 69 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -214,19 +214,15 @@ def process_enterprise_value(enterprise_str):
214214

215215
def resolve_cpp_function_call(function_name):
216216
"""
217-
Resolve certain small, known C++ zero-argument functions to their literal return values by searching Redpanda source files.
217+
Resolve a small set of known zero-argument C++ functions to their literal string return values by scanning a local Redpanda source tree.
218218
219-
This function looks up predefined search patterns for well-known functions (currently a small set under `model::*`), locates a local Redpanda source tree from several commonly used paths, and scans the listed files (and, if needed, the broader model directory) for a regex match that captures the string returned by the function. If a match is found the captured string is returned; if the source tree cannot be found or no match is located the function returns None.
219+
Searches predefined files and regex patterns for the specified fully-qualified function name (e.g., "model::kafka_audit_logging_topic") and returns the captured string if found; returns None when no match or when the Redpanda source tree cannot be located.
220220
221221
Parameters:
222-
function_name (str): Fully-qualified C++ function name to resolve (e.g., "model::kafka_audit_logging_topic").
222+
function_name (str): Fully-qualified C++ function name to resolve.
223223
224224
Returns:
225-
str or None: The resolved literal string returned by the C++ function, or None when unresolved (source not found or no matching pattern).
226-
227-
Notes:
228-
- The function performs filesystem I/O and regex-based source searching; it does not raise on read errors but logs and continues.
229-
- Only a small, hard-coded set of function names/patterns is supported; unknown names immediately return None.
225+
str or None: The literal string returned by the C++ function when resolved, or `None` if unresolved.
230226
"""
231227
# Map function names to likely search patterns and file locations
232228
search_patterns = {
@@ -342,17 +338,15 @@ def resolve_cpp_function_call(function_name):
342338

343339
def resolve_constexpr_identifier(identifier):
344340
"""
345-
Resolve a constexpr identifier from Redpanda source code to its literal value.
341+
Resolve a constexpr identifier from Redpanda source code to its literal string value.
346342
347-
This function searches recursively through header and source files for constexpr
348-
variable definitions. It's specifically useful for resolving identifiers like 'scram'
349-
which are defined as constexpr string_view variables.
343+
Searches common Redpanda source locations for constexpr string or string_view definitions matching the given identifier and returns the literal if found.
350344
351345
Parameters:
352346
identifier (str): The identifier name to resolve (e.g., "scram").
353347
354348
Returns:
355-
str or None: The resolved literal string value, or None if not found.
349+
str or None: The resolved literal string value if found, otherwise `None`.
356350
"""
357351
# Try to find the Redpanda source directory
358352
redpanda_source_paths = [
@@ -423,15 +417,15 @@ def resolve_constexpr_identifier(identifier):
423417

424418
def get_enterprise_sasl_mechanisms():
425419
"""
426-
Dynamically extract the list of enterprise SASL mechanisms from Redpanda source code.
420+
Locate and resolve enterprise SASL mechanisms declared in Redpanda's sasl_mechanisms.h.
427421
428-
This function looks for the enterprise_sasl_mechanisms definition in sasl_mechanisms.h
429-
and extracts the list of mechanism identifiers, then resolves each identifier to its
430-
actual string value.
422+
Searches known Redpanda source locations for an inline constexpr definition of enterprise_sasl_mechanisms,
423+
extracts the identifiers, and resolves each identifier to its literal string value where possible; unresolved
424+
identifiers are converted to an uppercase fallback.
431425
432426
Returns:
433-
list or None: List of enterprise SASL mechanism strings (like ["GSSAPI", "OAUTHBEARER"]),
434-
or None if the lookup fails.
427+
list or None: List of enterprise SASL mechanism strings (e.g., ["GSSAPI", "OAUTHBEARER"]),
428+
or `None` if the lookup fails.
435429
"""
436430
# Try to find the Redpanda source directory
437431
redpanda_source_paths = [
@@ -498,6 +492,18 @@ def get_enterprise_sasl_mechanisms():
498492

499493

500494
def validate_paths(options):
495+
"""
496+
Validate that required file-system paths referenced by `options` exist and exit the process on failure.
497+
498+
Checks:
499+
- Verifies `options.path` exists; logs an error and exits with status code 1 if it does not.
500+
- If `options.definitions` is provided, verifies that file exists; logs an error and exits with status code 1 if it does not.
501+
502+
Parameters:
503+
options: An object with at least the attributes:
504+
- path (str): Path to the input source directory or file.
505+
- definitions (Optional[str]): Path to the type definitions file (may be None or empty).
506+
"""
501507
path = options.path
502508

503509
if not os.path.exists(path):
@@ -888,21 +894,16 @@ def add_config_scope(properties):
888894

889895
def resolve_type_and_default(properties, definitions):
890896
"""
891-
Resolve JSON Schema types and expand C++-style default values for all properties.
897+
Normalize property types and expand C++-style default values into JSON-compatible Python structures.
892898
893-
This function:
894-
- Resolves type references found in `properties` against `definitions` (supports "$ref" and direct type names) and normalizes property "type" to a JSON Schema primitive ("object", "string", "integer", "boolean", "array", "number") with sensible fallbacks.
895-
- Expands C++ constructor/initializer syntax and common C++ patterns appearing in default values into JSON-compatible Python values (e.g., nested constructor calls -> dicts, initializer lists -> lists, `std::nullopt` -> None, enum-like tokens -> strings).
896-
- Ensures array-typed properties (including one_or_many_property cases) have array defaults: single-object defaults are wrapped into a one-element list and "{}" string defaults become [].
897-
- Updates array item type information when item types reference definitions.
898-
- Applies a final pass to convert any remaining C++-patterned defaults and to transform any `enterprise_value` strings via process_enterprise_value.
899+
This function resolves type references in each property against the provided definitions (supports "$ref" and direct type names), normalizes property "type" to a JSON Schema primitive when possible, expands C++ constructor/initializer and common C++ literal patterns found in "default" values into Python primitives/objects/lists, ensures array-typed properties have array defaults (including handling one_or_many_property cases), updates array item type information when item types reference definitions, and converts any `enterprise_value` strings via process_enterprise_value.
899900
900901
Parameters:
901-
properties (dict): Mapping of property names to property metadata dictionaries. Each property may include keys like "type", "default", "items", and "enterprise_value".
902-
definitions (dict): Mapping of type names to JSON Schema definition dictionaries used to resolve $ref targets and to infer property shapes when expanding constructors.
902+
properties (dict): Mapping of property names to metadata dictionaries. Relevant keys that may be modified include "type", "default", "items", and "enterprise_value".
903+
definitions (dict): Mapping of definition names to JSON Schema definition dictionaries used to resolve $ref targets and to infer shapes for expanding constructor-style defaults.
903904
904905
Returns:
905-
dict: The same `properties` mapping after in-place normalization and expansion of types and defaults.
906+
dict: The same `properties` mapping after in-place normalization and expansion of types, defaults, item types, and enterprise values.
906907
"""
907908
import ast
908909
import re
@@ -917,7 +918,19 @@ def resolve_definition_type(defn):
917918
return defn
918919

919920
def parse_constructor(s):
920-
"""Parse C++ constructor syntax into type name and arguments."""
921+
"""
922+
Parse a C++-style constructor or initializer expression into its type name and argument list.
923+
924+
Parses input forms such as `Type(arg1, arg2)`, `Type{arg1, arg2}`, or plain literals/enum-like tokens. For string literals the returned argument is a Python string value; for integer literals the returned argument is an int. Nested constructors and nested brace/paren groups are preserved as argument tokens.
925+
926+
Parameters:
927+
s (str): The C++ expression to parse.
928+
929+
Returns:
930+
tuple:
931+
- type_name (str|None): The parsed type name for constructor forms, or `None` when `s` is a primitive literal or enum-like token.
932+
- args (list): A list of argument tokens; tokens are raw strings for complex/nested arguments, Python `str` for quoted string literals, or `int` for integer literals.
933+
"""
921934
s = s.strip()
922935
original_s = s
923936
if s.startswith("{") and s.endswith("}"):
@@ -964,13 +977,18 @@ def parse_constructor(s):
964977

965978
def process_cpp_patterns(arg_str):
966979
"""
967-
Process specific C++ patterns to user-friendly values.
980+
Convert a C++-style expression string into a JSON-friendly literal representation.
968981
969-
Handles:
970-
- net::unresolved_address("127.0.0.1", 9092) -> expands based on type definition
982+
This function recognises common C++ patterns produced by the extractor and maps them to values suitable for JSON schema defaults and examples. Handled cases include:
971983
- std::nullopt -> null
972-
- fips_mode_flag::disabled -> "disabled"
973-
- model::kafka_audit_logging_topic() -> dynamically looked up from source
984+
- zero-argument functions (e.g., model::kafka_audit_logging_topic()) resolved from source when possible
985+
- enum tokens (e.g., fips_mode_flag::disabled -> "disabled")
986+
- constexpr identifiers and simple string constructors resolved to their literal strings when available
987+
- known default constructors and truncated type names mapped to sensible defaults (e.g., duration -> 0, path -> "")
988+
- simple heuristics for unknown constructors and concatenated expressions
989+
990+
Returns:
991+
processed (str): A string representing the JSON-ready value (for example: '"value"', 'null', '0', or the original input when no mapping applied).
974992
"""
975993
arg_str = arg_str.strip()
976994

@@ -1064,12 +1082,23 @@ def process_cpp_patterns(arg_str):
10641082

10651083
def expand_default(type_name, default_str):
10661084
"""
1067-
Expand C++ default values into structured JSON objects.
1085+
Convert a C++-style default initializer into a JSON-serializable Python value.
10681086
1069-
For array types with initializer list syntax like:
1070-
{model::broker_endpoint(net::unresolved_address("127.0.0.1", 9644))}
1087+
This expands C++ constructor and initializer-list syntax into Python primitives, dictionaries, and lists suitable for JSON output. Supported transformations include:
1088+
- String constructors and quoted literals → Python str.
1089+
- Integer and boolean literals → Python int and bool.
1090+
- Object constructors (Type(arg1, arg2) or Type{...}) → dict mapping constructor arguments to the object's properties when a corresponding type definition exists.
1091+
- Nested constructors → nested dicts with their fields expanded.
1092+
- Array initializer lists (e.g., {Type(...), Type(...)}) → Python list with each element expanded.
1093+
- Special-case mappings for known type patterns (for example, an address-type constructor expanded into {"address", "port"} when the target type expects that shape).
1094+
If a default cannot be resolved or the type is an enum, the original input is returned unchanged; the string "null" is converted to None. If default_str is not a string, it is returned as-is.
10711095
1072-
This creates: [{address: "127.0.0.1", port: 9644}]
1096+
Parameters:
1097+
type_name (str): The resolved type name for the default value (e.g., "model::broker_endpoint" or a primitive type like "string").
1098+
default_str (str | any): The C++ default expression to expand, or a non-string value already decoded.
1099+
1100+
Returns:
1101+
The expanded Python representation of the default: a dict for objects, a list for arrays, a primitive (str/int/bool), None for null, or the original value/string when expansion is not possible.
10731102
"""
10741103
# Handle non-string defaults
10751104
if not isinstance(default_str, str):
@@ -1835,4 +1864,4 @@ def generate_options():
18351864
sys.exit(1)
18361865

18371866
if __name__ == "__main__":
1838-
main()
1867+
main()

0 commit comments

Comments
 (0)