Module astrapy.utils.document_paths
Functions
def escape_field_names(*field_names: str | int | Iterable[str | int]) ‑> str-
Expand source code
def escape_field_names(*field_names: str | int | Iterable[str | int]) -> str: # type: ignore[misc] """ Escape one or more field-name path segments into a full string expression. Args: field_names: the function accepts any number of string or integer (non-negative) arguments - or, equivalently, a single argument with an iterable of them. In either case, the input(s) is a literal, unescaped specification for a path in a document. Returns: a single string resulting from dot-concatenation of the input segments, with each path segment having been escaped conforming to the Data API escaping rules. Example: >>> escape_field_names() '' >>> escape_field_names("f") 'f' >>> escape_field_names(123) '123' >>> escape_field_names("f", 123, "tom&jerry") 'f.123.tom&&jerry' >>> escape_field_names(["f"]) 'f' >>> escape_field_names(123) '123' >>> escape_field_names(["f", 123, "tom&jerry"]) 'f.123.tom&&jerry' """ _field_names: Iterable[str | int] # strings are iterables, so: if len(field_names) == 1 and not isinstance(field_names[0], (str, int)): _field_names = field_names[0] else: # user passing a list of string-or-ints. # But secretly any arg may still be Iterable: _field_names = [ segment for field_name in field_names for segment in ( [field_name] if isinstance(field_name, (str, int)) else field_name ) ] return FIELD_NAME_SEGMENT_SEPARATOR.join( [_escape_field_name(f_n) for f_n in _field_names] )Escape one or more field-name path segments into a full string expression.
Args
field_names- the function accepts any number of string or integer (non-negative) arguments - or, equivalently, a single argument with an iterable of them. In either case, the input(s) is a literal, unescaped specification for a path in a document.
Returns
a single string resulting from dot-concatenation of the input segments, with each path segment having been escaped conforming to the Data API escaping rules.
Example
>>> escape_field_names() '' >>> escape_field_names("f") 'f' >>> escape_field_names(123) '123' >>> escape_field_names("f", 123, "tom&jerry") 'f.123.tom&&jerry' >>> escape_field_names(["f"]) 'f' >>> escape_field_names(123) '123' >>> escape_field_names(["f", 123, "tom&jerry"]) 'f.123.tom&&jerry' def unescape_field_path(field_path: str) ‑> list[str]-
Expand source code
def unescape_field_path(field_path: str) -> list[str]: """Apply unescaping rules to a single-string field path. The result is a list of the individual field names, each a literal with nothing escaped anymore. Args: field_path: an expression denoting a field path following dot-notation with escaping for special characters. Returns: a list of literal field names. Even "number-looking" fields, such as "0" or "12", are returned as strings and it is up to the caller to interpret these according to the context. Example: >>> unescape_field_path("a.b") ['a', 'b'] >>> >>> unescape_field_path("a&.b") ['a.b'] >>> >>> unescape_field_path("a&&b&.c") ['a&b.c'] >>> >>> unescape_field_path("a&.b.c&&d") ['a.b', 'c&d'] """ segments: list[str] = [] buffer = "" path_length = len(field_path) if path_length == 0: return segments char_i = 0 while char_i < path_length: char = field_path[char_i] if char == FIELD_NAME_SEGMENT_SEPARATOR: segments += [buffer] buffer = "" elif char == FIELD_NAME_ESCAPE_CHAR: if char_i + 1 >= path_length: msg = UNTERMINATED_ESCAPE_ERROR_MESSAGE_TEMPLATE.format( field_path=field_path, ) raise ValueError(msg) char_i += 1 char = field_path[char_i] if char in FIELD_NAME_ESCAPED_CHARS: buffer += char else: msg = ILLEGAL_ESCAPE_ERROR_MESSAGE_TEMPLATE.format( field_path=field_path, escape_sequence=f"{FIELD_NAME_ESCAPE_CHAR}{char}", ) raise ValueError(msg) else: buffer += char char_i += 1 segments += [buffer] return segmentsApply unescaping rules to a single-string field path.
The result is a list of the individual field names, each a literal with nothing escaped anymore.
Args
field_path- an expression denoting a field path following dot-notation with escaping for special characters.
Returns
a list of literal field names. Even "number-looking" fields, such as "0" or "12", are returned as strings and it is up to the caller to interpret these according to the context.
Example
>>> unescape_field_path("a.b") ['a', 'b'] >>> >>> unescape_field_path("a&.b") ['a.b'] >>> >>> unescape_field_path("a&&b&.c") ['a&b.c'] >>> >>> unescape_field_path("a&.b.c&&d") ['a.b', 'c&d']