|
2 | 2 | Provides various utility functions for use in baking logic. |
3 | 3 | """ |
4 | 4 |
|
| 5 | +import re |
5 | 6 | from collections import defaultdict |
6 | | -from typing import Any, Dict, Set, Tuple |
| 7 | +from typing import Any, Dict, List, Set, Tuple |
7 | 8 |
|
8 | 9 | from openapi3.schemas import Schema |
9 | 10 |
|
@@ -51,3 +52,58 @@ def _handle_schema(_schema: Schema): |
51 | 52 | # We only want to mark fields that are required by ALL subschema as required |
52 | 53 | set(key for key, count in required.items() if count == schema_count), |
53 | 54 | ) |
| 55 | + |
| 56 | + |
| 57 | +ESCAPED_PATH_DELIMITER_PATTERN = re.compile(r"(?<!\\)\.") |
| 58 | + |
| 59 | + |
| 60 | +def escape_arg_segment(segment: str) -> str: |
| 61 | + """ |
| 62 | + Escapes periods in a segment by prefixing them with a backslash. |
| 63 | +
|
| 64 | + :param segment: The input string segment to escape. |
| 65 | + :return: The escaped segment with periods replaced by '\\.'. |
| 66 | + """ |
| 67 | + return segment.replace(".", "\\.") |
| 68 | + |
| 69 | + |
| 70 | +def unescape_arg_segment(segment: str) -> str: |
| 71 | + """ |
| 72 | + Reverses the escaping of periods in a segment, turning '\\.' back into '.'. |
| 73 | +
|
| 74 | + :param segment: The input string segment to unescape. |
| 75 | + :return: The unescaped segment with '\\.' replaced by '.'. |
| 76 | + """ |
| 77 | + return segment.replace("\\.", ".") |
| 78 | + |
| 79 | + |
| 80 | +def get_path_segments(path: str) -> List[str]: |
| 81 | + """ |
| 82 | + Splits a path string into segments using a delimiter pattern, |
| 83 | + and unescapes any escaped delimiters in the resulting segments. |
| 84 | +
|
| 85 | + :param path: The full path string to split and unescape. |
| 86 | + :return: A list of unescaped path segments. |
| 87 | + """ |
| 88 | + return [ |
| 89 | + unescape_arg_segment(seg) |
| 90 | + for seg in ESCAPED_PATH_DELIMITER_PATTERN.split(path) |
| 91 | + ] |
| 92 | + |
| 93 | + |
| 94 | +def get_terminal_keys(data: Dict[str, Any]) -> List[str]: |
| 95 | + """ |
| 96 | + Recursively retrieves all terminal (non-dict) keys from a nested dictionary. |
| 97 | +
|
| 98 | + :param data: The input dictionary, possibly nested. |
| 99 | + :return: A list of all terminal keys (keys whose values are not dictionaries). |
| 100 | + """ |
| 101 | + ret = [] |
| 102 | + |
| 103 | + for k, v in data.items(): |
| 104 | + if isinstance(v, dict): |
| 105 | + ret.extend(get_terminal_keys(v)) # recurse into nested dicts |
| 106 | + else: |
| 107 | + ret.append(k) # terminal key |
| 108 | + |
| 109 | + return ret |
0 commit comments