« Back to the main CSCI1660 website
This guide is designed to help you get started with setting up the development environment for the Dropbox project.
In this project, you'll build a client for a simulated version of a secure storage system that uses end-to-end encryption. This project has significantly less infrastructure compared to other projects: you'll reuse our existing development container and build your implementation entirely in Python.
This guide will describe how to set up your development container environment for this project and how to work with the stencil code for this project.
New to docker? If you do not have Docker installed from the last project, or you have not used the development container from Project 1, you can set up your environment using this guide and then skip this section.
If you've had issues with the container environment in the past (slow performance, files not syncing, etc.), please take a look at the following notes for our most common fixes:
If you experienced exceptionally slow filesystem performance on MacOS, see here for instructions on how to update your docker settings for a fix.
If you still encounter poor filesystem performance, or you have issues after the fix, please let us know!
See these instructions for a full writeup of the problem and a list of workarounds that we think will help. If you encountered issues with Docker during project 1, we strongly recommend that you do the following steps from this guide now:
The instructions also list some workarounds you can use at times to help reduce Docker/WSL's memory usage when they start to get problematic–skim these over and then keep them in mind in case you run into issues!
If you've finished with Project 3, you will likely no longer need to use the handin container for this project. To save on disk space, you can remove the image for the Handin container as follows:
cd
to your Handin project stencil directory and run the following:This will delete only the container image, freeing up disk space on your host machine. Any files you had in your home
directory (ie, /home/alice
in the container) will be preserved.
If you have not yet cleaned up your containers from the Flag project, see these instructions
We recommend working on this project using our development container, which is the container we used in Project 1. In the next few sections, we'll describe how to set up your container to develop for Dropbox and how to work with the stencil in VSCode.
Don't want to use the container? Since this project is in Python, you can technically work on it using any system with Python >= 3.9 that can load our virtual environment. However, our course staff may only be able to provide support if you use the development container as your base system.
As with the other stencils, we recommend cloning the stencil so you can access it from your development container.
To do this, we recommend cloning the stencil in your DEV-ENVIRONMENT/home
directory, where DEV-ENVIRONMENT
is the name of the folder you used when you cloned the development container.
Here's an example of what your filesystem might look like (based on what you might have from Projects 1 and 2):
Task: Go clone the stencil repo! You should have received a link to clone the stencil in the email with your team assignment. If you didn't receive an email, please post on Ed or contact Nick.
Now that your container environment is configured, we can set up our Dropbox environment for development. Our stencil contains a Makefile
that automates the most important tasks like this. To use it:
If you haven't done so already, start a terminal inside the container. That is, in a terminal on your host machine (or a WSL terminal on Windows), run the comand ./run-container
cd
to your Dropbox stencil directory
Run the following command, which sets up our environment:
After the setup finishes, your terminal output should end with Successfully installed...
. If it does not, please let us know on Ed.
Finally, we need to configure our terminal to run Python with our virtual environment. To do this, Python provides a script that sets various shell environment variables (including $PATH
) to point to the version of python inside the virtual environment–-this is called "activating" the environment. To do this:
cd
to your Dropbox stencil directory (if you're not there already)source env/bin/activate
Once you do this, there won't be any output, but your terminal prompt should change, like this:
If your terminal prompt shows (env)
it means your environment is loaded, yay!
Important note: Every time you open a new terminal to run Python, you will need to activate your environment like this. As you work on the project, don't forget this step!
Before we setup VSCode, it's important to make sure our test environment works. As you work on the project, you'll write unit tests to check the functionality of your implementation of your client.
We've provided a starter test file that imports the stencil code and contains some initial tests in the file test_client.py
. You can run these tests from any container terminal with the virtual environment setup, as follows:
If you haven't modified your stencil at all, you should see a bunch of output as each test runs, along with several failing tests:
If your output looks like this, your environment is working properly! It's okay to see failing tests for the reason support.util.DropboxError
at this point–these are TODOs for you to fill in.
Your stencil contains two files that contain tests:
test_client.py
: contains some basic tests and a sufficient framework to add your own tests. We recommend running these tests first.test_functionality.py
: contains a more comprehensive test suite, with nearly all the tests run by the autograder. Once your implementation is more complete, we recommend running these tests as well. (Why doesn't this include all the tests? Some tests require a more significant test harndes we can only provide on Gradescope–you can see the results of these tests after submittting to the autograder.)If you encounter issues with this process, make sure you're using the virtual environment and that it was set up correctly–otherwise, post on Ed and we can help!
VSCode has some great features for developing with containers. While it's not required for this project, if you like using VSCode you can connect it to the container and use it to write your Python code for this project. To do this:
/home/cs1660-user/...
Warning: When opening your Dropbox stencil directory, do NOT use the Show Local button in the open file dialog–for some reason, this will open the folder outside the container, which is not what we want!
client.py
When VSCode starts, it should automatically find our Python virtual environment. To check, look in the lower-right corner of the VSCode window, which should look like this:
If your VSCode does not show the virtual environment, click on the Python version number (in the red box above) and select "env" in the prompt at the top. Your VSCode is now configured correctly!
To run your code from VSCode, we recommend using VSCode's builtin terminal. To use it:
In VSCode, open a new terminal from the menu using Terminal > New Terminal
VSCode should open a container terminal and automatically enter your virtual environment, which should look like this (if not, see the previous section):
You can use this terminal to run the tests or any Python commands. You're also welcome to use VSCode's built-in features for running unit tests, debugging, etc. For now, try to run the tests with python3 -m unittest test_client.py
. For more tips on how to run tests, see this section.
If your test output looks the same as when you were running in the terminal, your VSCode is now properly configured for development, yay! If you encounter errors with modules, check your interpreter settings and feel free to post on Ed.
At the start of the project, you should be focusing on understanding the specification and thinking about how you will implement each component. To get started, we recommend the following resources:
This section contains some useful tools and resources you may find useful as you build your design and get started on your implementation:
Get(alice@somefile)
While the dataserver allows you to store arbitrary data, it doesn't understand types–similar to writing to a raw file, you can only read and write bytes()
objects to the Dataserver. To store any more complex data, you'll need to serialize it into bytes first. We've provided several utility methods and examples to help with this process:
util.BytesToObject
and util.ObjectToBytes
serialize some basic Python typesFor examples on how to use these, see this file in the Dropbox Examples repository. See the comments on each test for examples on how to use util.BytesToObject
and util.ObjectToBytes
to serialize different types of data.
Note: We'll provide a demo of this part in Gearup II.
You can think of the dataserver as a Map[Memloc,Data]
where Memloc
is an arbitrary 16-byte value and Data
is a bytes
object of any size.
Since 16-byte values are kind of unwieldy, you may want to store data in the Dataserver using a friendly name so you can easily look it up later without storing a random memory location. For example, you might want to store info about user Alice at the key "user_info:alice". To do this, we recommend hashing the name and then truncating the hash to 16-bytes, which produces a deterministic memory location from a friendly name.
Here's an example of how you can do this, packaged as a convenient helper function:
For examples on how to use this, see the serialization examples and the Gearup II recording.
We've provided a reference version of the client you can use for testing. This client is provided as a compiled Python library, which you can import and test in a similar manner to your client. You can use this to get an idea of how the client API should work and how you can interact with it.
We've provided a file test_reference.py
that imports the reference library and runs runs similar tests to those in test_client.py
. You can run these tests by running (from a terminal in your virtual environment):
Since this version is complete, you should see output with all the tests passing.
Note: This binary-compiled version of the client is for testing purposes only–you cannot use it in your actual implementation. When we review your final design document, we will also manually review your code–so even if you do manage to circumvent our autograder we'll know about it.
We recommend writing your own tests in test_reference.py
to try stuff out and see how the implementation works.
If you prefer to play around in a REPL, you can just run the file and type in code directly, like this:
Note: Once a user calls create_user
, the user is also authenticated. You don't have to call authenticate_user
after calling create_user
. This listing is just an example of what example API calls look like. For more examples of how to use the client API, see test_client.py
.
Python's unittest
has a few useful options that can make testing faster. Here are some examples of some of our favorites:
python3 -m unittest test_file.py -v
: Show tests as they runpython3 -m unittest test_functionality.py -v test_functionality.TestUserCreation.test_bad_username
: Run a specific testpython3 -m unittest test_file.py -f
: Stop on the first test failurepython3 -m unittest --help
: Show more optionsYou can also run your tests directly in VSCode instead of the terminal. Here's how to set up VSCode to do this:
Make sure you have configured VSCode to use your virtual environment, as described in this section.
Open VSCode's testing panel by clicking on the beaker in the sidebar, which looks like this:
VSCode will probaly ask you to configure testing, which tells VSCode how to find the tests. To do this:
a. Click Configure Python Tests:
b. A menu will open at the top of the VSCode window like the picture below. In this menu, select unittest
:
c. Next, you will be prompted to select where the tests are located. Select ". Root Directory":
d. Finally, you will be asked what types of files contain tests. Select "test_*.py":
After you have configured the tests, your testing pane should look like the picture below. If you don't see any tests, see this section.
To run the tests, expand the list and hover over any test (or set of tests) and clck "Run Test" or "Debug test", as shown in the figure above, to run your tests! You should see the tests results show up in the sidebar, yay!
Note that most tests will fail at the start of your project, since most methods haven't been implemented yet. If you want to test your work against a complete implementation, see this section for how to use the our reference client (just run the tests from VSCode instead!).
If you don't see your tests in the list, try the following:
This guide has provided an overview of the most important mechanics you need to work with the environment for this project. If you have questions, please feel free to come to hours or post on Ed. Have fun, and happy hacking!
If you see errors along the lines of bash: '\r': command not found
or bash: /home/cs1660-user/.bash_profile: line 5: syntax error: unexpected end of file
, see this section for common fixes.