Skip to content

v0.3.0

Pre-release
Pre-release

Choose a tag to compare

@tom-pytel tom-pytel released this 28 Feb 14:38
· 82 commits to main since this release

0.3.0 - alpha - 2026-02-28

Added

  • Python 3.15a support
    • unpacking in comprehensions, [*st for st in itr], {**key for key in itr}
    • lazy imports not on main branch yet
  • structural pattern matching
    • FST.match() match - f.match(Mstmt(body=[Expr(Constant(str)), ...]))
    • FST.search() search - for m in f.search(Assign([Name], ListComp))
    • FST.sub() substitute - f.sub(MCall('old_name', _args=M(all_args=...)), 'new_name(__FST_all_args, new_kw=newval)')
  • FST.find_def() easily find (possibly nested) function and class definitions by name in a given scope by dotted name
    • added usage of this in indexing (single-element only, not slice): method = module['class.method'], del someclass['method'], etc...
  • FST / fstview interoperability for convenience
    • added src, lines, loc/ln/col/end_ln/end_col, bloc/bln/bcol/bend_ln/bend_col and pars() to fstview
    • added base to FST so that you can do f.base.get_src(*f.loc) without knowing if is FST or fstview
  • walk()
    • can take explicit list of nodes to walk instead of just "all children of self"
    • can take user callback for the all parameter for deciding if node matches
  • added top parameter to step_fwd/back() to restrict stepping above a given parent
  • finally validating options
  • trivia option shorthand () for (False, False)

Changed

  • allow get and put as one=True single-item Dict or MatchMapping instead of error, makes more sense
  • simplified trivia option to always specify entire state, no more merging with current state
  • Global/Nonlocal.names views now return a single-element FSTView when dereferencing a single element instead of the string value at that index
  • allow delete Raise.exc if cause exists by automatically deleting cause first
  • allow delete ExceptHandler.type if name exists by automatically deleting name first

Fixed

  • fixed step_fwd/back() for anything that wasn't all=True/False/'loc'
  • replacement of single statement no longer replaces that statement's FST, allowing walk() to recurse into replaced children
  • disallow put _ as name to MatchMapping.rest and MatchClass.kwd_attrs
  • disallow put * or dotted as name to alias.name if context does not allow
  • disallow put * to _aliases.names if there are multiple names (only allowed to replace a single one)
  • put empty slice of statementlikes containing only trivia erasing whole orelse or finalbody field now deletes the whole field instead of leaving a hanging else: or finally: