- Following directions and reading comprehension
- Reading tests
- Creating classes
- Classes have attributes and instance methods
- Importing modules
- Working with attributes that are lists of instances
- Implementing instance methods that interact with other instances and objects
- Implementing inheritance
- Overriding methods from superclasses and Object
You want to organize a swap meet! You have a bunch of stuff. So do your friends! It would be awesome if each person could swap one of their things with another person's things.
For this event, you want each person to register online as a vendor. Also, they should list an inventory list of things.
You envision an app where vendors can swap items between different inventories. But what would that backend logic look like?
For this project, given some features that the vendors want, create a set of classes, following the directions below. The directions will lead you to create many class definitions, their attributes and instance methods, and some other cool features. Vendors will be able to swap their top item and swap items by category!
Follow these directions once, a the beginning of your project:
- Navigate to your projects folder named
projects
$ cd ~/Developer/projects- "Clone" (download a copy of this project) into your projects folder. This command makes a new folder called
swap-meet, and then puts the project into this new folder.
$ git clone ...Use ls to confirm there's a new project folder
- Move your location into this project folder
$ cd swap-meet- Create a virtual environment named
venvfor this project:
$ python3 -m venv venv- Activate this environment:
$ source venv/bin/activateVerify that you're in a python3 virtual environment by running:
$ python --versionshould output a Python 3 version$ pip --versionshould output that it is working with Python 3
- Install dependencies once at the beginning of this project with
# Must be in activated virtual environment
$ pip install -r requirements.txtSummary of one-time project setup:
-
cdinto yourprojectsfolder - Clone the project onto your machine
-
cdinto theviewing-partyfolder - Create the virtual environment
venv - Activate the virtual environment
venv - Install the dependences with
pip
- When you want to begin work on this project, ensure that your virtual environment is activated:
$ source venv/bin/activate-
Find the test file that contains the test you want to run.
- Check the
testsfolder, and find the test file you want to run - In that test file, read through each test case
- Check the
-
Run the tests for your specific wave
# Must be in activated virtual environment
$ pytest tests/test_wave_01.py-
Focus on the top test failure. Read through the test failure, and understand why the failure is happening. Confirm your findings with a classmate.
-
Make a plan to fix the test failure.
-
Write code to fix the test failure.
-
Re-run the tests.
-
Repeat steps 5-7 until that test passes!
-
Repeats steps 4-8 until you have finished all tests in the file.
-
Begin using the test file of the next wave!
-
When you are finished working for the day, deactivate your environment with deactivate or closing the Terminal tab/window
$ deactivateRun all tests that exist in this project with:
# Must be in activated virtual environment
$ pytestIf you want to run all tests that exist in one file, use:
# Must be in activated virtual environment
$ pytest tests/test_file_name.py... where test_file_name.py is relpaced with the correct test file name.
If you want to see any print statements print to the console, add -s to the end of any pytest command:
# Must be in activated virtual environment
$ pytest -sThe goal of this project is to write code in various files in the swap_meet directory so that as many of the tests pass as possible.
To complete this project, use the above workflow and follow these steps:
- Start with making the tests in
test_wave_01.pypass. - Review your code in the
swap_meetdirectory and see if there are ways you can make the code more readable. - Then, work on making the tests in
test_wave_02.pypass. - Review your code in the
swap_meetdirectory - Repeat on all test files until submission time.
At submission time, no matter where you are, submit the project via Learn.
This project is designed such that one could puzzle together how to implement this project without many directions.Being able to use tests to drive project completion is a skill that needs to be developed; programmers often take years to develop this skill competently.
When our test failures leave us confused and stuck, let's use the detailed project requirements below.
The first two tests in wave 1 imply:
- There is a module (file) named
vendor.pyinside of theswap_meetpackage (folder) - Inside this module, there is a class named
Vendor - Each
Vendorwill have an attribute namedinventory, which is an empty list by default - When we create initialize an instance of
Vendor, we can optionally pass in a list with the keyword argumentinventory
The remaining tests in wave 1 imply:
-
Every instance of
Vendorhas an instance method namedadd, which takes in one item -
This method adds the item to the
inventory -
This method returns the item that was added
-
Similarly, every instance of
Vendorhas an instance method namedremove, which takes in one item -
This method removes the matching item from the
inventory -
This method returns the item that was removed
-
If there is no matching item in the
inventory, the method should returnFalse
The first tests in wave 2 imply:
-
There is a module (file) named
item.pyinside of theswap_meetpackage (folder) -
Inside this module, there is a class named
Item -
Each
Itemwill have an attribute namedcategory, which is an empty string by default -
When we initialize an instance of
Item, we can optionally pass in a string with the keyword argumentcategory -
Instances of
Vendorhave an instance method namedget_by_category- It takes one argument: a string, representing a category
- This method returns a list of
Items in the inventory with that category
The first test in wave 3 implies:
- When we stringify an instance of
Itemusingstr(), it returns"Hello World!"- This implies
Itemoverrides its stringify method
- This implies
The remaining 5 tests in wave 3 imply:
- Instances of
Vendorhave an instance method namedswap_items- It takes 3 arguments:
- an instance of another
Vendor, representing the friend that the vendor is swapping with - an instance of an
Item(my_item), representing the item thisVendorinstance plans to give - an instance of an
Item(their_item), representing the item the friendVendorplans to give
- an instance of another
- It removes the
my_itemfrom thisVendor's inventory, and adds it to the friend's inventory - It removes the
their_itemfrom the otherVendor's inventory, and adds it to thisVendor's inventory - It returns
True - If this
Vendor's inventory doesn't containmy_itemor the friend's inventory doesn't containtheir_item, the method returnsFalse
- It takes 3 arguments:
The tests in wave 4 imply:
- Instances of
Vendorhave an instance method namedswap_first_item- It takes one argument: an instance of another
Vendor, representing the friend that the vendor is swapping with - This method considers the first item in the instance's
inventory, and the first item in the friend'sinventory - It removes the first item from its
inventory, and adds the friend's first item - It removes the first item from the friend's
inventory, and adds the instances first item - It returns
True - If either itself or the friend have an empty
inventory, the method returnsFalse
- It takes one argument: an instance of another
The tests in Wave 5 imply there are three new modules with three new classes:
-
Clothing- Has an attribute
categorythat is"Clothing" - Its stringify method returns
"The finest clothing you could wear."
- Has an attribute
-
Decor- Has an attribute
categorythat is"Decor" - Its stringify method returns
"Something to decorate your space."
- Has an attribute
-
Electronics- Has an attribute
categorythat is"Electronics" - Its stringify method returns
"A gadget full of buttons and secrets."
- Has an attribute
-
All three classes and the
Itemclass have an attribute calledcondition, which can be optionally provided in the initializer. The default value should be0. -
All three classes and the
Itemclass have an instance method namedcondition_description, which should describe the condition in words based on the value, assuming they all range from 0 to 5. These can be basic descriptions (eg. 'mint', 'heavily used') but feel free to have fun with these (e.g. 'You probably want a glove for this one..."). The one requirement is that thecondition_descriptionfor all three classes above have the same behavior.
Now, we may notice that these four classes hold the same types of state and have the same behavior. That makes this is a great opportunity to use inheritance! If you haven't already, go back and implement the Clothing, Decor, and Electronics classes so that they inherit from the Item class. This should eliminate repetition in your code and greatly reduce the total number of lines code in your program!
Now the these three classes hold the same state and have the same behavior, this is a great opportunity to use inheritance! If you haven't already, go back and implement the Clothing, Decor, and Electronics classes so that they inherit from the Item class. This should eliminate repetition in your code and greatly reduce the total number of lines code in your program!
You'll need to refer to Item in order to declare it as a parent. To reference the Item class into these modules, try this import line:
If you need to import the Item class into these modules, try this import line:
from swap_meet.item import ItemThe first three tests in wave 6 imply:
Vendors have a method namedget_best_by_category, which will get the item with the best condition in a certain category- It takes one argument: a string that represents a category
- This method looks through the instance's
inventoryfor the item with the highestconditionand matchingcategory- It returns this item
- If there are no items in the
inventorythat match the category, it returnsNone - It returns a single item even if there are duplicates (two or more of the same item with the same condition)
The last three tests in wave 5 imply:
Vendors have a method namedswap_best_by_category, which will swap the best item of certain categories with anotherVendor- It takes in three arguments
other, which represents anotherVendorinstance to trade withmy_priority, which represents a category that theVendorwants to receivetheir_priority, which represents a category thatotherwants to receive
- The best item in my inventory that matches
their_prioritycategory is swapped with the best item inother's inventory that matchesmy_priority- It returns
True - If the
Vendorhas no item that matchestheir_prioritycategory, swapping does not happen, and it returnsFalse - If
otherhas no item that matchesmy_prioritycategory, swapping does not happen, and it returnsFalse
- It returns
- It takes in three arguments
The further reduce the amount of repeated code in your project, consider how swap_best_by_category and swap_first_item might be able to make use of swap_items. Is there a way that these methods could incorporate a call to swap_items into the body of these methods?
Try it out and see if the tests still pass! If you can't get them to pass with this refactor, you can always return to the most recent working commit before you submit the project!
Should a project be completed before submission, and there is a desire for optional enhancements, consider this idea:
- Items have age
- Add an
ageattribute to all Items - Implement a
Vendormethod namedswap_by_newest, using any logic that seems appropriate
- Add an