Assignment 1: File Explorer

Introduction

For the rest of the assignments in this course, you will be building a distributed social communication platform. The final version of the program will allow you to send and receive encrypted messages with other students in the class. You will start with a command line interface and end with an encrypted graphical interface. Along the way you will learn about many of the processes that programmers use to develop software. For now though, you’ll get started with a simple file management program.

Summary of program requirements for this assignment:

  1. Navigate a computer file system

  2. Search for files by full name or suffix

  3. Output content of text file

  4. Load file contents

  5. Create new file

Learning Goals

  1. Working with files and file systems

  2. Understand Recursion

  3. Error handling

  4. Tests

Program Requirements

Part 1

User input for this program will take the following format:

[COMMAND] [INPUT] [[-]OPTION] [INPUT]

For the first part of the assignment, you will support two commands:

Program Feature

L - List the contents of the user specified directory.
Q - Quit the program.

The ‘Q’ command is straightforward, when your program receives the ‘Q’ input it should cleanly stop operation. The ‘L’ command will instruct your program to list the contents of a directory. So for example, if we want to list the content of a particular directory in our file system:

L c:\users\mark\a1

which will print:

c:\users\mark\a1\test.py
c:\users\mark\a1\readme.txt
c:\users\mark\a1\assets
c:\users\mark\a1\doc

So by running this command, we discover that there are two files and two directories contained within the directory we specified. Notice that the results are sorted by files first and then directories. Your first attempt to print the contents of a directory will not look like this, so you will have to take care to ensure your code properly sorts results into files first, followed by directories.

Program Feature

The results of the ‘L’ command must print results in a files first, directories last format. If the path specified does not contain any files or directories, then you do not not need to print anything.

Now let’s add some options to refine our directory listing. There are four options that you will need your program to support:

Program Feature

-r Output directory content recursively.
-f Output only files, excluding directories in the results.
-s Output only files that match a given file name.
-e Output only files that match a give file extension.

Applying the ‘r’ option to the directory list command, will print the contents of the source directory as well as all subdirectories:

L c:\users\mark\a1 -r

And the resulting output:

c:\users\mark\a1\test.py
c:\users\mark\a1\readme.txt
c:\users\mark\a1\assets
c:\users\mark\a1\assets\image1.jpg
c:\users\mark\a1\assets\image2.jpg
c:\users\mark\a1\assets\logos
c:\users\mark\a1\assets\logos\logo1.jpg
c:\users\mark\a1\assets\logos\logo2.jpg
c:\users\mark\a1\doc
c:\users\mark\a1\doc\help.doc
c:\users\mark\a1\doc\readme.txt

Notice how that in addition to the output of files within the ‘assets’ directory, the subdirectory ‘logos’ is also printed along with the files contained within.

Okay, so far so good. Now let’s see what happens when we apply the ‘f’ option:

L c:\users\mark\a1 -f

And the resulting output:

c:\users\mark\a1\test.py
c:\users\mark\a1\readme.txt

Or with the recursion option:

L c:\users\mark\a1 -r -f

And the resulting output:

c:\users\mark\a1\test.py
c:\users\mark\a1\readme.txt
c:\users\mark\a1\assets\image1.jpg
c:\users\mark\a1\assets\image2.jpg
c:\users\mark\a1\assets\logos\logo1.jpg
c:\users\mark\a1\assets\logos\logo2.jpg
c:\users\mark\a1\doc\help.doc
c:\users\mark\a1\doc\readme.txt

As you may have expected, by adding the ‘f’ option to the ‘L’ command, the program will only list the files in the specified directory.

The two remaining options, ‘s’ and ‘e’, allow us to further refine our results by specifying search parameters. Unlike the ‘r’ and ‘f’ options, these options will also need to accept a user input parameter. So let’s say we want to find all files in a given directory with the name ‘readme.txt’:

L c:\users\mark\a1 -s readme.txt

And the resulting output:

c:\users\mark\a1\readme.txt

Or with the recursion option:

L c:\users\mark\a1 -r -s readme.txt

And the resulting output:

c:\users\mark\a1\readme.txt
c:\users\mark\a1\doc\readme.txt

Notice that we combined options here to recursively check all subdirectories as well, so our results return two instances of the file ‘readme.txt’ that exist within the ‘a1’ directory.

Now let’s try another search using the ‘e’ option. As I described earlier, the ‘e’ option allows us to filter results by file extension, so:

L c:\users\mark\a1\assets -e jpg

And the resulting output:

c:\users\mark\a1\assets\image1.jpg
c:\users\mark\a1\assets\image2.jpg

Or with the recursion option:

L c:\users\mark\a1 -r -e jpg

And the resulting output:

c:\users\mark\a1\assets\image1.jpg
c:\users\mark\a1\assets\image2.jpg
c:\users\mark\a1\assets\logos\logo1.jpg
c:\users\mark\a1\assets\logos\logo2.jpg

Note

You can safely assume that when a program feature is combined with the ‘-r’ option, that the ‘-r’ option will always come first.

The results now only return files who have the extension or suffix ‘jpg’. Okay, so once you have created a program that is able to execute all of the operations described in this section you will be ready for Part 2.

Part 2

Now that we have a way to look for files in our file system, we need to actually do something with those files! So for this part of the assignment you will add three additional commands to your program:

Program Feature

C - Create a new file in the specified directory.
D - Delete the file.
R - Read the contents of a file.

Creating a new file is exactly as it sounds, when the user issues the C command, your program will read the input and create a new file:

C c:\users\mark\a1 -n mark

Program Feature

-n Specify the name to be used for a new file.

The ‘C’ command must also accept a single option ‘n’ that allows the user to specify the name of the file. Note that we do not require the use of an extension. Instead, since we will be using this program in the future to create users for our distributed social platform, the program will control the types of files it creates. So whenever a file is created, it must append the user specified name with a distributed social user extension, or ‘dsu’. So when the previous command is run, it will create a new file in the specified directory, with the specified name, and the ‘dsu’ extension. The program output should look like the following to confirm to the user that the file was created:

c:\users\mark\a1\mark.dsu

Program Feature

New files created with the ‘C’ command must automatically be created with the ‘dsu’ extension or suffix.

The ‘D’ command will allow the user to delete a DSU file. If the user specified file is not a DSU file, then the program should print ERROR and wait for corrected input from the user. Once the DSU file has been successfully deleted, the program should print a confirmation:

D c:\users\mark\a1\mark.dsu

And the resulting output:

c:\users\mark\a1\mark.dsu DELETED

Program Feature

A the output after deleting a file should print the directory and file name with the word ‘DELETED’ at the end of the line.

The ‘R’ command will print the contents of a DSU file. As with the ‘D’ command, if the user specified file is not a DSU file, the program should print ERROR and wait for corrected input from the user. If the file is empty, then the program should print EMPTY and wait for corrected input from the user:

R c:\users\mark\a1\mark.dsu

And the resulting output:

EMPTY

Otherwise, the program will print the contents of the file:

R c:\users\mark\a1\mark.dsu

And the resulting output:

Hello World!

Program Feature

The program must handle errors gracefully. When an error occurs, the program should inform the user by printing ‘ERROR’ and wait for additional input from the user.

Finally, and this applies to both Parts 1 and 2, your program should handle errors gracefully. If a user enters commands, inputs, or options that are not understood by the program, the program should simply print ERROR and wait for additional input from the user.

A Few Rules

The majority of the work you will need to do for this assignment will center around the pathlib library. Start by familiarizing yourself with the various functions that the library provides. Path is a powerful type that will help you manipulate the file system, so use as much of it as you can to reduce the complexity of your program. There are, however, a few functions in the library that you will not be allowed to use for this assignment. os.walk, os.fwalk, glob, and rglob abstract away much of the functionality that we want you to learn through this assignment. Generally, if you find yourself using library functions to locate files rather than writing your own recursive function, then you are probably using the library inappropriately.

Other Considerations

  1. You do not need to concern yourself with rare edge cases. Your code should work with most commonly used file and directory paths. Situations where a path or filename makes use of the options used by your program can be ignored.

  2. You do need to concern yourself with whitespace. A program that splits the input command by whitespace will not pass our grading tool! This means that you are going to have to get a bit clever about how to process your input. We will discuss some strategies during live class.

  3. You do need to support functionality on both Windows and Posix file systems! This means you should not hard code conventions common to one particular operating system (e.g., ‘C:\’) or use concatenation to build your paths. The pathlib module takes care of this work for you, so as long as you use it properly your code will run on both systems.

Submitting Your Assignment

Naming and organizational requirements

How you organize your program is up to you, but there are a couple of requirements that you’ll need to follow.

Your program must be written entirely in a single Python module, in a file named a1.py. Note that capitalization and spacing are important here (i.e., no letters in the filename are capitalized and there are no spaces); they’re part of the requirement.

Executing your a1 module — by, for example, pressing F5 or selecting Run Module from the Run menu in IDLE — must cause your program to read its input and then print its output. It must not be necessary to call a function manually to make your program run.

Other than that, anything goes; you can organize your solution in any way you’d like. Note that future assignments will take what we call “quality of solution” a lot more seriously, but the name of the game in this warm-up assignment is simply to submit a program that works.

Validation-checking your output

The validity checker for this assignment works just like the one you used for assignment 0. Place the validity checker in the same directory as your a1.py module and run it.

Interpreting Validity Checker Output

The validity checker will exit operation when it encounters an unexpected output from your program. Your instincts might lead you to run the last input operation reported by the validity checker prior to the error directly from your program. While this is a good first step, and one that can help you understand what went wrong, there is a good chance that the same input command will work for you. This does not mean that there is something wrong with the validity checker! Rather, it is an indication that the internal state of your code is changing after certain input commands are run in a certain order.

If you find yourself in this situation, the first thing you should do is review the output from the validity checker, taking note of each of the input commands that were executed. Next, run your program (debug mode helps here) and input the exact same commands in the same order. You WILL find that your program output matches the validity checker perfectly. Use this knowledge to work through your code until you discover what is causing the error.

So before you reach out to a course instructor and say “but it works for me”, perform the tests described above! (because if you don’t, we’ll tell you to anyway :) )

How we will grade your submission

This assignment will be graded on a 100 point scale, with the 100 points being allocated completely to whether or not you submitted something that meets all of the above requirements. The following rubric will be used:

Requirements and Function | 90 pts

Does the program do what it is supposed to do?

Are there any bugs or errors?

Quality and Design | 10 pts

Is the code well designed?

Is the code clearly documented?

As this is your first assignment using the following grading rubric, we will make an effort to draw attention to where your program fails to meet the grading criteria. However, as we move on, you will be expected to learn from our feedback and address the concerns that we raise in your code.