Skip to main content

Read/Write python files

Project description

PyPI - License PyPI

What and why

This library's creation was motivated by my deep thirst to automate everything.

It enables you to programmatically read, change and write python files.

Short explanation

In simple words, an FTree object 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 -1 and 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)

Installation

Install using pip package manager

pip install pyfiletree

Usage

Example 1

Simple, but useless use of this library

from pyfiletree.ftree import FTree

file = FTree(read_file_path)
file.write_to(write_file_path)

Example 2

Using the transformer parameter to change every line of the input file

from pyfiletree.ftree import FTree

transformer = [
    lambda x: x.replace(" ", "_"),
    lambda x: x.replace("self.", "MyClass."),
    lambda x: x.lower(),
]
file = FTree(read_file_path, transformer)
file.apply_transformer()
file.write_to(write_file_path)

Example 3

Concatenating two python files.

Here you have the option to append the second file at a certain line using the line parameter of the append method.

This way of appending keeps the existing level of indentation intact.

from pyfiletree.ftree import FTree

file = 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 works

FTree parameters

file_path

File from which to read and create the code tree. You have to ensure this is a .py file. For now, no restrictions are applied to the file type.

transformer

This is the end goal I had in mind when developing this library. Based on this parameter, your file will change.

The transformer parameter takes a list of functions, i.e.:

transformer = [
    lambda x: x.replace("3", "4"),
    before_declared_func,
    lambda y: y.lower()
]

f = FTree(file_path, transformer=transformer)

Both named functions and lambda functions are allowed.

In order for these changes to take place, the apply_transformer method needs to be called.

f.apply_transformer()

New Feature

If your function returns a tuple as (None, Boolean), that node will be deleted from the file tree, i.e.

transformer = [
    lambda x: (None, True) if "def" in x else x,
    lambda x: None if "return" in x else x
]

The boolean value is optional(defaults to True) and signals if the node's children should be deleted too or not. If True then the children are appended to node's father.

Restriction: The functions provided apply to each line in the file, hence the functions need to expect only one parameter(the line).

Observations:

  • Functions are applied in their appearance order.
Incoming features
  • Specify list of lines/ threshold line for where to apply the transformer

debug

This boolean value influences what is printed by the print_tree method.

When True, the logs will show:

  • level of indentation
  • father node

test

The same as debug, but it only shows the value of each node, without indent.

FTree methods

print_tree()

Prints tree to console, formatting is dependent on debug and test values.

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.

  • path is not restricted to only .py files yet, you have to handle this
  • mode -> mode in which the file is opened, default is to append
  • apply_transformer -> Boolean to apply the transformer before writing. Convenient to skip additional call to apply_transformer()

append(obj, line=-1, transformer=None)

Using this method you can append another file to a certain line.

  • line is by default -1 which appends at the end of file, under the root parent
  • When line is specified, obj will be appended at said line, but under the parent of the current node that is found at that line
  • obj can 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 existing transformer
Example

File to append to -> path: "usr/file1"

import os  # line 1
# line 2
def func():  # line 3
    x = 1  # line 4
    y = 0  # line 5
    if x == 1:  # line 6
        y = x + 2  # line 7
    return x + y  # line 8

File to be appended -> path: "usr/file2"

y = 1

FTree code:

from pyfiletree import FTree

main_file = FTree("usr/file1")
main_file.append("usr/file2", line=6)
main_file.write_to("usr/file3")

This example attempts to append file2 at line 6, this leads to y = 1 getting assigned as the children of the father node of if x == 1:, which currently is at line 6. Father node being def func():

File after append -> path: "usr/file3"

import os  # line 1
# line 2
def func():  # line 3
    x = 1  # line 4
    y = 0  # line 5
    y = 1  # <- new line appended
    if x == 1:  # line 7
        y = x + 2  # line 8
    return x + y  # line 9
Incoming features:
  • Append just a node
  • apply_transformer=False boolean to apply the current transformer to just the appended tree

apply_transformer()

Applies the functions in the transformer parameter to each line in the tree.

set_transformer(new_transformer)

new_transformer is appended to the existing transformer, if it exists, else acts like a basic setter.

Node class

You 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.

Contributing

Contributions are most welcome!!

If you want to change/implement something new, please create an issue first so we can talk about it!

Testing

You need to have pytest==4.4.1 to run the tests in tests/test_ftree.py

Navigate to root directory of the project and run with pytest -vv to get detailed result of each test.

If you implement a new feature, please write comprehensive tests for it.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyfiletree-0.1.6-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

Details for the file pyfiletree-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: pyfiletree-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 8.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/3.7.3 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.59.0 CPython/3.7.10

File hashes

Hashes for pyfiletree-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 c08db20f15b4fe5e673c47dcbb9e27344da9354c19e8ecb7c9cb9d327c9cc57c
MD5 5fb6b26c254de8efad0d74b8833ca2fb
BLAKE2b-256 329e47c3243cf6f6643830588000edad249ba1e28edaf9ef219b261217934fda

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page