Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ada S19 - Anh Huynh #77

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
32 changes: 30 additions & 2 deletions swap_meet/clothing.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,30 @@
class Clothing:
pass
import uuid
from swap_meet.item import Item


class Clothing(Item):
# Define attributes for Clothing instances
def __init__(self, id = None, fabric = None, condition = None):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use the string literal default for fabric, since strings don't have the same problem that [] has.

Suggested change
def __init__(self, id = None, fabric = None, condition = None):
def __init__(self, id = None, fabric = "Unknown", condition = None):

# User inheritance logic to inherit certain attributes of Item class
super().__init__(id, condition)
# If no value provided for fabric, attribute fabric takes on "Unknown"
if fabric is None:
self.fabric = "Unknown"
else:
self.fabric = fabric

def get_category(self):
# Return class name "Clothing"
return Clothing.__name__

# Stringify Clothing instances
def __str__(self):
# Read id attribute
id_value = self.id
# Read fabric attribute
fabric_value = self.fabric
# Return expected string
return f"An object of type Clothing with id {id_value}. It is made from {fabric_value} fabric."



37 changes: 35 additions & 2 deletions swap_meet/decor.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,35 @@
class Decor:
pass
import uuid
from swap_meet.item import Item


class Decor(Item):
# Define attributes for Decor instances
def __init__(self, id = None, width = None, length = None, condition = None):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integer defaults are fine, too!

Suggested change
def __init__(self, id = None, width = None, length = None, condition = None):
def __init__(self, id = None, width = 0, length = 0, condition = None):

# User inheritance logic to inherit certain attributes of Item class
super().__init__(id, condition)
# If no value provided for width, attribute width takes on 0
if width is None:
self.width = 0
else:
self.width = width

# If no value provided for length, attribute length takes on 0
if length is None:
self.length = 0
else:
self.length = length

def get_category(self):
# Return class name "Decor"
return Decor.__name__

#Stringify Decor instances
def __str__(self):
# Read id attribute
id_value = self.id
# Read width attribute
width_value = self.width
# Read length attribute
length_value = self.length
# Return expected string

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[suggestion] Try to make sure your comments add clarity. If they repeat what the code does without adding any color, you can remove them.

return f"An object of type Decor with id {id_value}. It takes up a {width_value} by {length_value} sized space."
29 changes: 27 additions & 2 deletions swap_meet/electronics.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,27 @@
class Electronics:
pass
import uuid

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't use uuid in this file, so you can remove it.

from swap_meet.item import Item


class Electronics(Item):
# Define attributes for Electronics instances
def __init__(self, id = None, type = None, condition = None):
# User inheritance logic to inherit certain attributes of Item class
super().__init__(id, condition)
# If no value provided for type, attribute type takes on "Unknown"
if type is None:
self.type = "Unknown"
else:
self.type = type

def get_category(self):
# Return class name "Electronics"
return Electronics.__name__

# Stringify Electronics instances
def __str__(self):
# Read id attribute
id_value = self.id
# Read type attribute
type_value = self.type
# Return expected string
return f"An object of type Electronics with id {id_value}. This is a {type_value} device."
45 changes: 44 additions & 1 deletion swap_meet/item.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,45 @@
import uuid

class Item:
pass
# Define attributes for Item instances
def __init__(self, id = None, condition = None):
# If no value provided for id, attribute id takes on randomly generated unique number
if id is None:
self.id = int(uuid.uuid4())
else:
self.id = id
Comment on lines +7 to +10

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A ternary is also fine here:

        self.id = id if id else uuid.uuid4().int


# If no value provided for condition, attribute condition takes on 0
if condition is None:
self.condition = 0
else:
self.condition = condition

def get_category(self):
# Return class name "Item"
return Item.__name__

# Stringify Item instances
def __str__(self):
# Read id attribute
item_id = self.id
# Return expected string
return f"An object of type Item with id {item_id}."

# Read condition attribute and return a string corresponding to attribute value
def condition_description(self):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that this handles a wide range of values, even things like 2.4. You might consider adding a default as well, since condition is unconstrained and could be less than 0 or more than 5.

if 0 <= self.condition < 1:
return "fair"
elif 1 <= self.condition < 2:
return "good"
elif 2 <= self.condition < 3:
return "excellent"
elif 3 <= self.condition < 4:
return "near-mint"
elif 4 <= self.condition <= 5:
return "new"





117 changes: 116 additions & 1 deletion swap_meet/vendor.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,117 @@
from .item import Item

class Vendor:
pass
# Define attributes for Vendor instances
def __init__(self, inventory = None):
# If no value provided for inventory, attribute inventory takes on an empty list
if inventory is None:
self.inventory = []
else:
self.inventory = inventory

def add(self, item_add):
# Add item provided to attribute inventory
self.inventory.append(item_add)
# Return this added item
return item_add

def remove(self, item_remove):
# If item to be removed doesn't exist in attribute inventory, return False.
# Otherwise, remove this item from inventory and return this removed item
if item_remove not in self.inventory:
return False
else:
self.inventory.remove(item_remove)
return item_remove

def get_by_id(self, id):
# Create an Item instance passing in an id value
test_item = Item(id)
# Loop through list of instances stored in attribute inventory
for item in self.inventory:
# If attribute id in an instance has same value as attribute id in Item instance
# Return this instance. Otherwise, return None
if item.id == test_item.id:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend not creating the fake Item with id. You could just make this:

Suggested change
if item.id == test_item.id:
if item.id == id:

return item
return None


def swap_items(self, other_vendor, my_item, their_item):
# If user's Item instance doesn't exist in own inventory or friend's Item instance doesn't exist
# in friend's inventory, return False
if my_item not in self.inventory or their_item not in other_vendor.inventory:
return False
# Otherwise, remove user's Item instance and add it to friend's inventory
# Remove friend's Item instance and add it to user's inventory
# Return True
else:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The else: isn't strictly necessary here because the return False above will exclude anything outside the if statement.

self.inventory.remove(my_item)
other_vendor.inventory.append(my_item)
other_vendor.inventory.remove(their_item)
self.inventory.append(their_item)
return True

def swap_first_item(self, other_vendor):
# If user's own inventory or friend's inventory is empty, return False
if len(self.inventory) == 0 or len(other_vendor.inventory) == 0:
return False
else:
# Otherwise, grab first Item instance in user's and friend's inventories
user_first_item = self.inventory[0]
friend_first_item = other_vendor.inventory[0]
# Call on the swap_items method to swap these first Item instances between user and friend
self.swap_items(other_vendor, user_first_item, friend_first_item)
# self.inventory.remove(user_first_item)
# other_vendor.inventory.remove(friend_first_item)
# other_vendor.inventory.append(user_first_item)
# self.inventory.append(friend_first_item)
Comment on lines +64 to +67

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove old code. If you commit before changing it, too, git will remember it for you.

return True

def get_by_category(self, category):
# Note: category of type string
# Create an empty list called "resulting_list"
resulting_list = []
# Loop through each Item instance in inventory
for item in self.inventory:
# If an instance's category (aka class name) same as provided category,
# add this instance to resulting_list
if item.get_category() == category:
resulting_list.append(item)
# Return updated resulting_list
return resulting_list
Comment on lines +73 to +81

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notice this pattern of:

result_list = []
for element in source_list:
    if some_condition(element):
        result_list.append(element)

can be rewritten using a list comprehension as:

result_list = [element for element in source_list if some_condition(element)]

Which here would look like:

resulting_list = [item for item in self.inventory if item.get_category() == category]
return resulting_list

At first, this may seem more difficult to read, but comprehensions are a very common python style, so I encourage y’all to try working with them!


def get_best_by_category(self, category):
# Call on get_by_category method to get a list of instances matching provided category
resulting_list = self.get_by_category(category)
# If resulting_list is empty, aka no matching instances, return None
if len(resulting_list) == 0:
return None
else:
# Otherwise, grab first instance in resulting_list and store in best_item
best_item = resulting_list[0]
# Read first instance's attribute condition and store in best_condition
best_condition = resulting_list[0].condition
# Loop thru each instance in resulting_list
for item in resulting_list:
# If an instance's attribute condition shares same value as best_condition's value
# re-assign this instance to best_item and its attribute condition to best_condition
if item.condition > best_condition:
best_item = item
best_condition = item.condition
# Return updated instance with best condition matching provided category
return best_item

def swap_best_by_category(self, other_vendor, my_priority, their_priority):
# Call on get_best_by_category method to get user's best instance matching friend's category
# and to get friend's best instance matching user's category
user_best_match = self.get_best_by_category(their_priority)
other_best_match = other_vendor.get_best_by_category(my_priority)
# If user has no instance matching friend's category or vice versa, return False
if user_best_match is None or other_best_match is None:
return False
else:
# Otherwise, call on swap_items method to swap user's and friend's
# matching best instances with each other
self.swap_items(other_vendor, user_best_match, other_best_match)
# return True
return True
Comment on lines +110 to +117

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since swap_items can handle items that are None, you could also defer to it:

        return self.swap_items(other_vendor, user_best_match, other_best_match)

4 changes: 2 additions & 2 deletions tests/integration_tests/test_wave_01_02_03.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from swap_meet.vendor import Vendor
from swap_meet.item import Item

@pytest.mark.skip
@pytest.mark.integration_test
#@pytest.mark.skip
#@pytest.mark.integration_test

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to remove the integration_test mark

def test_integration_wave_01_02_03():
# make a vendor
vendor = Vendor()
Expand Down
4 changes: 2 additions & 2 deletions tests/integration_tests/test_wave_04_05_06.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from swap_meet.decor import Decor
from swap_meet.electronics import Electronics

@pytest.mark.skip
@pytest.mark.integration_test
#@pytest.mark.skip
#@pytest.mark.integration_test
def test_integration_wave_04_05_06():
camila = Vendor()
valentina = Vendor()
Expand Down
14 changes: 8 additions & 6 deletions tests/unit_tests/test_wave_01.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
import pytest
from swap_meet.vendor import Vendor

@pytest.mark.skip
#@pytest.mark.skip
def test_vendor_has_inventory():
vendor = Vendor()
assert len(vendor.inventory) == 0

@pytest.mark.skip
#@pytest.mark.skip
def test_vendor_takes_optional_inventory():
inventory = ["a", "b", "c"]
vendor = Vendor(inventory=inventory)
Expand All @@ -16,7 +16,7 @@ def test_vendor_takes_optional_inventory():
assert "b" in vendor.inventory
assert "c" in vendor.inventory

@pytest.mark.skip
#@pytest.mark.skip
def test_adding_to_inventory():
vendor = Vendor()
item = "new item"
Expand All @@ -27,7 +27,7 @@ def test_adding_to_inventory():
assert item in vendor.inventory
assert result == item

@pytest.mark.skip
#@pytest.mark.skip
def test_removing_from_inventory_returns_item():
item = "item to remove"
vendor = Vendor(
Expand All @@ -40,16 +40,18 @@ def test_removing_from_inventory_returns_item():
assert item not in vendor.inventory
assert result == item

@pytest.mark.skip
#@pytest.mark.skip
def test_removing_not_found_is_false():
item = "item to remove"
vendor = Vendor(
inventory=["a", "b", "c"]
)

result = vendor.remove(item)

assert result is False

raise Exception("Complete this test according to comments below.")
#raise Exception("Complete this test according to comments below.")
# *********************************************************************
# ****** Complete Assert Portion of this test **********
# *********************************************************************
12 changes: 6 additions & 6 deletions tests/unit_tests/test_wave_02.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,30 @@
from swap_meet.vendor import Vendor
from swap_meet.item import Item

@pytest.mark.skip
#@pytest.mark.skip
def test_items_have_default_uuid_length_id():
item = Item()
assert isinstance(item.id, int)
assert len(str(item.id)) >= 32

@pytest.mark.skip
#@pytest.mark.skip
def test_item_instances_have_different_default_ids():
item_a = Item()
item_b = Item()
assert item_a.id != item_b.id

@pytest.mark.skip
#@pytest.mark.skip
def test_items_use_custom_id_if_passed():
item = Item(id=12345)
assert isinstance(item.id, int)
assert item.id == 12345

@pytest.mark.skip
#@pytest.mark.skip
def test_item_obj_returns_text_item_for_category():
item = Item()
assert item.get_category() == "Item"

@pytest.mark.skip
#@pytest.mark.skip
def test_get_item_by_id():
test_id = 12345
item_custom_id = Item(id=test_id)
Expand All @@ -36,7 +36,7 @@ def test_get_item_by_id():
result_item = vendor.get_by_id(test_id)
assert result_item is item_custom_id

@pytest.mark.skip
#@pytest.mark.skip
def test_get_item_by_id_no_matching():
test_id = 12345
item_a = Item()
Expand Down
Loading