Releases: tom-pytel/pfst
Releases · tom-pytel/pfst
Release list
v0.3.2
0.3.2 - alpha - 2026-03-27
Added
- Python 3.15 lazy import support
MatchClass.patterns+kwd_attrs=kwd_patternsslice get and put_pattern_attrlikesspecial slice container holds both combined unnamed and keyword patterns, e.ga, b, c=d, e=f_attrsvirtual field onMatchClassand_pattern_attrlikes
- filled out lots of non-basic coercions, mostly between forms like
**a, keywordskw=valand annotationsv: annarguments,_arglikes,_expr_arglikes,_pattern_attrlikesand_type_paramsbetween each otherTypeVar=default_valueand**ParamSpecto the previous and also to single_arglikeand to/fromkeywordTypeVar: bound<->arg: annotation- singleton
argumentsand_pattern_attrlikesto singleargandkeywordif possible
Changed
- concretized behavior of locations of nonstandard slices like
comprehension.ifs,Assign.targetsor.decorator_list- includes extra syntax in location when accessed as slice but not when accessed as single item
- parse unspecified type will not reduce statement
Exprto single expression if has trailing semicolon dump(loc=False)will no longer outputROOTfor root node, easier to compare just structure dumps
Fixed
- special
FSTViewclasses for decorator lists,comprehension.ifsandAssign.targetsso that slice locations from these field views are correct - honor
dump()eolparameter when outputtingout='str' - coercing
FSTexpression to a non-arglike expression, if it is arglike-only then it will be appropriately parenthesized, e.g. FST(*not a, 'expr_arglike').as_('expr') ->*(not a) fst.cli.subproperly prints multiple statement substution lines- fixed a few cases of parse expression where trailing semicolon was accepted for an expression
v0.3.1
0.3.1 - alpha - 2026-03-13
Added
- substitution and traversal
- added
onparameter to allowwalk()andsearch()yield on'enter'or'leave'node or'both' - added
onparameter tosub()can do substitution on'enter'or'leave', allowing bottom-up substitution for easier collapsing of nested structures - added
callbackandcallback_afterparameters tosub()andsubn()to better observe and control individual substitutions - added
MExceptHandler._starparameter to allow differentiating betweenexceptandexcept*on match - new CLI modules
fst.cli.searchandfst.cli.subfor convenient application to source files
- added
- allow use of
FSTViewas a singleton item reference- types which dereference to singleton
FSTViewget a flagis_oneto indicate this and can return single node oncopy/cut()instead of slice at()method to get an item as a singletonFSTViewif getting that item alone would lose information like aNoneorstr.itemproperty for quick access to singletonFSTViewitem
- types which dereference to singleton
promoteoption to control whether primitive fields are gotten as primitives or nodes, covers all primitive fieldsFST.parse_ast()to parse a pureASTwithoutFSTnodes using our extended parsing- put slice to
DictandMatchMappingcan accept undelimitedDictandMatchMappingsource opcan be set as a global option for convenience for putting slices toCompare- added
--color/--no-coloroptions to mainfstCLI module
Changed
- tweaked certain cases of multiline slice put indentation to be slightly less horrible, aesthetics still need a rework when functionality is no longer the priority
- non-raise fail substitution inside f-strings on Python < 3.12, warn instead, as those replacements are not implemented and probably will not be
get/put/get_slice/put_slice()typing tweaked for easier to swizzle parameters with type checking enabled- added
FST.strip()which removes trivia surrounding node at root, was previously private function_sanitize() - identifier puts using
FSTnodes as source (which doesn't consume them), will now unmake those nodes to stay consistent with all other puts - loosened
Constantrulesfromast()andas_()will accept negative numericalConstant.valueand normalize those toUnaryOp(USub, abs(Constant))- put to primitive int field will accept
UnaryOp(USub, Constant)numerical values
- put one to
Subscript.slice- automatically parenthesize
TuplecontainingStarredinstead of raising on Python 3.10 - automatically unparenthesize
TuplecontainingSlices instead of raising
- automatically parenthesize
Fixed
- fixed bug in
sub()when putting certain slices whenrepl_optionspresent which caused errors likeValueError: expecting single item pair for put as 'one=True' - corrected
walk(scope=True)of Comprehension first generator iterator if it itself is a scope, e.g.a = [i for i in [j for j in iter]] - fixed reparse empty
AST_ExceptHandlersslice - fixed swap
Try<->TryStaron replace allhandlerswith an empty slice (not delete, replace with empty)
v0.3.0
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
- unpacking in comprehensions,
- 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...
- added usage of this in indexing (single-element only, not slice):
FST/fstviewinteroperability for convenience- added
src,lines,loc/ln/col/end_ln/end_col,bloc/bln/bcol/bend_ln/bend_colandpars()tofstview - added
basetoFSTso that you can dof.base.get_src(*f.loc)without knowing if isFSTorfstview
- added
walk()- can take explicit list of nodes to walk instead of just "all children of self"
- can take user callback for the
allparameter for deciding if node matches
- added
topparameter tostep_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=Truesingle-itemDictorMatchMappinginstead of error, makes more sense - simplified
triviaoption to always specify entire state, no more merging with current state Global/Nonlocal.namesviews now return a single-elementFSTViewwhen dereferencing a single element instead of the string value at that index- allow delete
Raise.excifcauseexists by automatically deletingcausefirst - allow delete
ExceptHandler.typeifnameexists by automatically deletingnamefirst
Fixed
- fixed
step_fwd/back()for anything that wasn'tall=True/False/'loc' - replacement of single statement no longer replaces that statement's
FST, allowingwalk()to recurse into replaced children - disallow put
_as name toMatchMapping.restandMatchClass.kwd_attrs - disallow put
*or dotted as name toalias.nameif context does not allow - disallow put
*to_aliases.namesif there are multiple names (only allowed to replace a single one) - put empty slice of statementlikes containing only trivia erasing whole
orelseorfinalbodyfield now deletes the whole field instead of leaving a hangingelse:orfinally:
v0.2.6
0.2.6 - alpha - 2026-01-31
Breaking Changes
- when putting source instead of an
FSTorASTnode directly as a slice to an expression, if the source is a delimited sequence then it will always be put as one node and not unpacked, previous behavior of.put_slice('[1, 2, 3]')being put as a slice of three distinct elements can be selected by passingone=None
Added
- coercion expanded greatly, can now put more nodes which are not the exact type but that "should work", e.g.
TupleFST.elts = MatchSequenceFST.patterns.copy()pattern,arguments,arg,alias,withitem,TypeVarandTypeVarTupletoexpr- custom slice types
_Assign_targets,_decorator_list,_arglikes,_comprehension_ifs,_aliases,_withitemsand_type_paramstoTuple,ListorSet - all sequence types, custom and standard, to custom slice types
- all expressions and custom slice types to
pattern keywordtoarguments
FST.as_(mode)for explicit coercion directly tomode(which can be an explicittype[AST]or a parse mode)FST(FST, mode)for constructor default non-destructive coerce copy from otherFSTnode, a-lalist(other_list) is not other_listFST(AST, mode)andFST.fromast(AST, type[AST] or mode)can use the new coercion to convertAST- with these changes,
FST(x[, mode])now works likelist(x)in that it converts source,ASTorFSTto the given modeFSTif possible, or just ANFSTif mode not provided
- with these changes,
- put slice as
one=Truefor_Assign_targets,_decorator_list,_arglikes,_comprehension_ifs,_aliases,_withitems,_type_paramsand_expr_arglikes - prescribed slicing for
MatchClass.patterns - prescribed slicing for
arguments._all, e.g.FunctionDefFST.args[x:y] = 'a: int, /, b=c' unpar('invalid')can remove delimiters fromList,Set,Dict,MatchMapping,ListComp,SetComp,DictCompandGeneratorExp, if needed for some reason
Changed
FST.dump()returnsselfwhen not returning str or lines and those are now specified without='str'orout='lines'- concretized behavior of put slice with
one=Truefor custom special slices, will not put multiple elements now in this mode when one requested parse_withitem('x,')now parses to singletonTuplewithiteminstead of singleNamewithitemwith trailing comma, makes more sense- allow put
Starredtovaluefield ofExpr,Return,AnnAssignandYieldeven though not compilable, for consistency, our metric is parsability, not compilability - REMOVED
norm_putoption as was too annoying to maintain everywhere needed for the little good it did,norm_selfandnorm_getremain - improved put multiline slice aesthetics, specifically better needs-own-line detection and keeping line comment on pre-insert element line instead of moving it
- parse
withitemand_withitemsno longer accept single unparenthesizedYield,NamedExprorTupleas a convenience, causes too many problems downstream - empty
argumentsnow always have a location, having potentially zero-lengthargumentsis less ugly than having arguments with no location DictandMatchMappingslice views dereferenced with a single index will now return a view of that single key:value pair instead of raising
Fixed
- fixed
comprehension_ifsand_arglikescoercions where unparenthesized tuple needed to be parenthesized FST.dump()will no longer output trailing whitespace on lines when the line is completely empty, better for tests- fixed delimit of whole node at root when degenerate last line has line continuation without trailing newline
- fixed parse location correction of multiline unparenthesized tuple with group parenthesized first and / or last elements
- fixed parse of unparenthesized tuple with trailing comma to
_Assign_targets - don't accept
Starrednode for awithitem,_withitemsnormal or_comprehension_ifscoerce - don't try to parse
*starred = valueasTypeVarTuplein place ofAssignon py < 3.13 - allow put
StarredtoTypeVarTuple.default_value - fixed parse
withitemof a soloGeneratorExp - will not parenthesize
argorargumentsif putting multiline to aLambdabut instead parenthesize theLambda - will not parenthesize multiline
withitemput toWith.itemswith existingitemsbut rather the wholeitemsfield - fixed
unpar(node=True)node if first and or last elements are parenthesized
v0.2.5
0.2.4 alpha
Full Changelog: v0.2.3...v0.2.4
v0.2.2
v0.1.1
Initial release
v0.1.0 include documentation