I wrote a library using just ast and inspect libraries to parse and emit [uses astor on Python < 3.9] internal Python constructs.
Just realised that I really need to preserve comments afterall. Preferably without resorting to a RedBaron or LibCST; as I just need to emit the unaltered commentary; is there a clean and concise way of comment-preserving parsing/emitting Python source with just stdlib?
What I ended up doing was writing a simple parser, without a meta-language in 339 source lines: https://github.com/offscale/cdd-python/blob/master/cdd/cst_utils.py
Implementation of Concrete Syntax Tree [List!]
if line.lstrip().startswith("#") or line not endswith('\\') and balanced_parens(line)else continue munching until that condition is true… plus some edge-cases around multiline strings and the like;namedtuplewith avalueproperty.Integration with builtin Abstract Syntax Tree
astastnodes to modify—not remove—to: {ClassDef,AsyncFunctionDef,FunctionDef} docstring (first body elementConstant|Str),AssignandAnnAssign;cst_idx, cst_node = find_cst_at_ast(cst_list, _node);maybe_replace_doc_str_in_function_or_class(_node, cst_idx, cst_list)cst_listcontains only changes to those aforementioned nodes, and only when that change is more than whitespace, and can be created into a string with"".join(map(attrgetter("value"), cst_list))for outputting toevalor straight out to a source file (e.g., in-place overriding).Quality control
Limitations
match/caseis supported, but if there's new syntax introduced since, it isn't [yet?] supported… at least not automatically);