Package: pyfiletree
What and whyThis library's creation was motivated by my deep thirst to automate everything.It enables you to programmatically read, change and write python files.Short explanationIn simple words, anFTreeobject stores the .py file in a tree-like format
for simpler use with Python's indentation levels.You can append different other .py files to your main one and
keep/adapt the levels of indentation.This allows you to automatically change/create new python files and
transform them to your needs.The root of this tree is the file name, with an indentation level of-1and is ignored in most of the transform/write/equality operations.Children of root and other nodes are determined based of their level of indentation,
taken as a multiple of 4. (even blank line are treated as children)InstallationInstall using pip package managerpipinstallpyfiletreeUsageExample 1Simple, but useless use of this libraryfrompyfiletree.ftreeimportFTreefile=FTree(read_file_path)file.write_to(write_file_path)Example 2Using the transformer parameter to change every line of the input filefrompyfiletree.ftreeimportFTreetransformer=[lambdax:x.replace(" ","_"),lambdax:x.replace("self.","MyClass."),lambdax:x.lower(),]file=FTree(read_file_path,transformer)file.apply_transformer()file.write_to(write_file_path)Example 3Concatenating two python files.Here you have the option to append the second file at a certain line
using thelineparameter of theappendmethod.This way of appending keeps the existing level of indentation intact.frompyfiletree.ftreeimportFTreefile=FTree(read_file_path)file_to_append=FTree(append_file_path)file.append(file_to_append,line=3)file.write_to(write_file_path)How it worksFTree parametersfile_pathFile from which to read and create the code tree.
You have to ensure this is a.pyfile. For now, no restrictions are applied
to the file type.transformerThis is the end goal I had in mind when developing this library.
Based on this parameter, your file will change.Thetransformerparameter takes a list of functions, i.e.:transformer=[lambdax:x.replace("3","4"),before_declared_func,lambday:y.lower()]f=FTree(file_path,transformer=transformer)Both named functions and lambda functions are allowed.In order for these changes to take place, theapply_transformermethod
needs to be called.f.apply_transformer()New FeatureIf your function returns a tuple as(None, Boolean), that node
will be deleted from the file tree, i.e.transformer=[lambdax:(None,True)if"def"inxelsex,lambdax:Noneif"return"inxelsex]The boolean value is optional(defaults toTrue) and signals
if the node's children should be deleted too or not.
IfTruethen the children are appended to node's father.Restriction: The functions provided apply to eachlinein the file, hence the functions need to expect only
one parameter(the line).Observations:Functions are applied in their appearance order.Incoming featuresSpecify list of lines/ threshold line for where to apply the transformerdebugThis boolean value influences what is printed by theprint_treemethod.WhenTrue, the logs will show:level of indentationfather nodetestThe same asdebug, but it only shows the value of each node, without indent.FTree methodsprint_tree()Prints tree to console, formatting is dependent ondebugandtestvalues.get_node_by_line(line)Returns the node at the line provided.If no such node/line exists, an exception will be raised.write_to(path, mode='a+', apply_transformer=False)Method to write the current tree to a said file path.pathis not restricted to only .py filesyet, you have to handle thismode-> mode in which the file is opened, default is to appendapply_transformer-> Boolean to apply the transformer before writing.
Convenient to skip additional call toapply_transformer()append(obj, line=-1, transformer=None)Using this method you can append another file to a certain line.lineis by default-1which appends at the end of file, under the root parentWhenlineis specified,objwill be appended at said line,
but under the parent of the current node that is found at that lineobjcan be either an FTree instance or a file path to a .py(in which case
an FTree object will automatically be created)transformer-> transformer to be applied only to the appended file.
This function list is not appended to the existingtransformerExampleFile to append to -> path:"usr/file1"importos# line 1# line 2deffunc():# line 3x=1# line 4y=0# line 5ifx==1:# line 6y=x+2# line 7returnx+y# line 8File to be appended -> path:"usr/file2"y=1FTree code:frompyfiletreeimportFTreemain_file=FTree("usr/file1")main_file.append("usr/file2",line=6)main_file.write_to("usr/file3")This example attempts to appendfile2at line 6,
this leads toy = 1getting assigned as the children
of the father node ofif x == 1:, which currently is at line 6.
Father node beingdef func():File after append -> path:"usr/file3"importos# line 1# line 2deffunc():# line 3x=1# line 4y=0# line 5y=1# <- new line appendedifx==1:# line 7y=x+2# line 8returnx+y# line 9Incoming features:Append just a nodeapply_transformer=Falseboolean to apply the current transformer to
just the appended treeapply_transformer()Applies the functions in thetransformerparameter to each line
in the tree.set_transformer(new_transformer)new_transformerisappendedto the existingtransformer, if it
exists, else acts like a basic setter.Node classYou wouldn't want to use this class, since FTree does all the heavy
lifting for you.
But I will add documentation for this as well later.ContributingContributions are most welcome!!If you want to change/implement something new, please
create an issue first so we can talk about it!TestingYou need to havepytest==4.4.1to run the tests intests/test_ftree.pyNavigate to root directory of the project and run withpytest -vvto get detailed result of each test.If you implement a new feature, please write comprehensive tests for it.