Question
Problem 2. Non-interactive Text Editing A non-interactive text editor executes simple editing commands on a text file using a programming interface (i.e. functions or object
Problem 2. Non-interactive Text Editing
A non-interactive text editor executes simple editing commands on a text file using a programming interface (i.e. functions or object methods) in some programming language, like Python. All commands take as input, at minimum, the file name as a parameter, then perform their job (reading or modifying the file), and end returning some results. For this problem we assume the text files have the utf-8 encoding (the default in Python) and they are not too large. Therefore, its OK to read the file entirely to memory, execute the operations required, then overwrite the file with the modified file content, as a string. This is not the only approach, but its the simpler one and it works for smaller files.
Here are the editing commands, with the corresponding function signatures:
ed_read(filename, from=0, to=-1): returns as a string the content of the file named filename, with file positions in the half-open range [from, to). If to == -1, the content between from and the end of
the file will be returned. If parameter to exceeds the file length, then the function raises exception ValueError with a corresponding error message.
ed_find(filename, search_str): finds string search_str in the file named by filename and returns a list with index positions in the file text where the string search_str is located. E.g. it returns [4, 100] if the string was found at positions 4 and 100. It returns [] if the string was not found.
ed_replace(filename, search_str, replace_with, occurrence=-1): replaces search_str in the file named by filename with string replace_with. If occurrence==-1, then it replaces ALL occurrences.
If occurrence>=0, then it replaces only the occurrence with index occurrence, where 0 means the first, 1 means the second, etc. If the occurrence argument exceeds the actual occurrence index in the file of that string, the function does not do the replacement. The function returns the number of times the string was replaced.
ed_append(filename, string): appends string to the end of the file. If the file does not exist, a new file is created with the given file name. The function returns the number of characters written to the file.
ed_write(filename, pos_str_col): for each tuple (position, s) in collection pos_str_col (e.g. a list) this function writes to the file at position pos the string s. This function overwrites some of the existing file content. If any position parameter is invalid (< 0) or greater than the file contents size, the function does not change the file and raises ValueError with a proper error message. In case of no errors, the function returns the number of strings written to the file. Assume the strings to be written do not overlap.
ed_insert(filename, pos_str_col): for each tuple (position, s) in collection pos_str_col (e.g. a list) this function inserts into to the file content the string s at position pos. This function does not
overwrite the existing file content, as seen in the examples below. If any position parameters is invalid (< 0) or greater than the original file content length, the function does not change the file at all and raises ValueError with a proper error message. In case of no errors, the function returns the number of strings inserted to the file.
For all the functions above, the file should not be changed in case of an error. If an error related to file I/O (e.g. FileNotFoundError or IOError) occurs in one of these functions, it should be passed to the caller. This means that these functions should not catch (except:) file IO errors.
Examples:
fn = ed_append(fn, ed_append(fn,
# assume this file does not exist yet.
"file1.txt"
print(ed_read(fn, 3, 9)) print(ed_read(fn, 3))
lst = ed_find(fn, "345") print(lst) print(ed_find(fn, "356"))
"0123456789" "0123456789"
) )
# this will create a new file # the file content is: 01234567890123456789
# prints 345678. Notice that the interval excludes index to (9) # prints from 3 to the end of the file: 34567890123456789
# prints [3, 13] # prints []
ed_replace(fn, "345", "ABCDE", 1) # changes the file to 0123456789012ABCDE6789 # assume we reset the file content to 01234567890123456789 (not shown)
ed_replace(fn, "345", "ABCDE") # changes the file to 012ABCDE6789012ABCDE6789
# assume we reset the file content to 01234567890123456789 (not shown) # this function overwrites original content: ed_write(fn, ((2, "ABC"), (10, "DEFG"))) # changes file to: 01ABC56789DEFG456789 # this should work with lists as well: [(2, "ABC"), (10, "DEFG")]
# assume we reset the file content to 01234567890123456789 (not shown) ed_write(fn, ((2, "ABC"), (30, "DEFG"))) # fails. raises ValueError("invalid position 30")
# assume we reset the file content to 01234567890123456789 (not shown) # this function inserts new text, without overwriting: ed_insert(fn, ((2, "ABC"), (10, "DEFG"))) # changed file to: 01ABC23456789DEFG0123456789
Here are your tasks for this problem:
a) Implement in Python all functions listed on the previous page in file p2.py. Write the contracts for each function in its docstring. Ensure precondition errors are handled properly and ValueError is raised in case the precondition is not met. All errors related to file I/O (e.g. FileNotFoundError or IOError) should be passed to the caller.
b) Write test functions for functions ed_write and ed_replace using the testif() function we used for homework 3, listed in Appendix A. These test functions should be named test_x , where x is the name of the function tested. E.g. test_ed_write() should use testif() to test ed_write(). In general, this type of test functions are called unit tests as they test just one function (or one method in a class). In Appendix B there is a sample unit test for ed_append(). Use that as a template.
c) Write a main() function where you show how to use all ed_.... functions written for part a). d) EXTRA CREDIT for 5 points
Write a function ed_search(path, search_string) that searches for search_string in all files in directory path and its immediate subdirectories using the os.walk function.
The ed_search function must use the ed_find() function from part a). ed_search must return the list of full (absolute) path names where files in which search_string is found or the empty list [] if the string is not found in any files. The ed_search function should not proceed recursively to all subdirectories.
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started