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

Niambi P - Sapphire #88

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions swap_meet/clothing.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,38 @@
class Clothing:
pass
from swap_meet.item import Item

class Clothing(Item):
# May have to change fabric default values to None

Choose a reason for hiding this comment

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

You didn't have to do it for the string "Unknown" because strings are immutable and it's okay for the same instance of a string to be shared. Same with integers. Only the empty list ([]) ends up being a problem in the swap meet project.

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

Choose a reason for hiding this comment

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

[opinion] I prefer spaces around = signs like id = None instead of id=None

super().__init__(id, condition)
if fabric == None:
self.fabric = "Unknown"
else:
self.fabric = fabric

def clothing(self):
self.clothing = self.fabric
Comment on lines +12 to +13

Choose a reason for hiding this comment

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

[nit] Looks like this is unneeded?


def get_category(self):
return "Clothing"
Comment on lines +15 to +16

Choose a reason for hiding this comment

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

None of your derived classes need to implement get_category because you have implemented it in their base class (Item)!


def __str__(self):
return f"An object of type {self.get_category()} with id {self.id}. It is made from {self.fabric} fabric."

# if self.fabric == "unknown":
# return f"An object of type {self.get_category()} with id {self.id}. It is made from Unknown fabric."
# else:
# return f"An object of type {self.clothing()} with id {self.id}. It is made from {self.fabric} fabric."
Comment on lines +21 to +24

Choose a reason for hiding this comment

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

[nit] You can remove unused code


def condition_description(self):
if self.condition == 0:
return f"Item condition is rated 0. This item is barely holding on!"
elif self.condition == 1:
return f"Items condition is rated 1. This item is hanging on by a thread!"
elif self.condition == 2:
return f"Items condition is rated 2. This item is living on a prayer."
elif self.condition == 3:
return f"Items condition is rated 3. This item is in working order."
elif self.condition == 4:
return f"Items condition is rated 4. This item is in good condition."
else:
return f"Items condition is rated 5. This item is in excellent condition."
39 changes: 37 additions & 2 deletions swap_meet/decor.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,37 @@
class Decor:
pass
from swap_meet.item import Item

class Decor (Item):
def __init__(self, id=None, condition=0, width=0, length=0):
super().__init__(id, condition)
self.width = width
self.length = length


def condition_description(self):
if self.condition == 0:
return f"Item condition is rated 0. This item is barely holding on!"
elif self.condition == 1:
return f"Items condition is rated 1. This item is hanging on by a thread!"
elif self.condition == 2:
return f"Items condition is rated 2. This item is living on a prayer."
elif self.condition == 3:
return f"Items condition is rated 3. This item is in working order."
elif self.condition == 4:
return f"Items condition is rated 4. This item is in good condition."
else:
return f"Items condition is rated 5. This item is in excellent condition."

def get_category(self):
return self.__class__.__name__

def __str__(self):
return f"An object of type {self.get_category()} with id {self.id}. It takes up a {self.width} by {self.length} sized space."

# ------------------ WAVE 5 -----------------------
# Has an attribute id that is by default a unique integer
# Holds 2 integer attributes width and length
# Both of these values should be 0 by default
# When we instantiate an instance of Decor, we can optionally pass in integers with the keyword arguments width and length
# Has a function get_category that returns "Decor"
# Has a stringify method that returns "An object of type Decor with id <id value>. It takes up a <width value> by <length value> sized space."
# For example, if we had a Decor instance with an id of 123435, width of 3, and length of 7, its stringify method should return "An object of type Decor with id 12345. It takes up a 3 by 7 sized space."
39 changes: 37 additions & 2 deletions swap_meet/electronics.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,37 @@
class Electronics:
pass
from swap_meet.item import Item

class Electronics(Item):
def __init__(self, id=None, type="Unknown", condition=0):
super().__init__(id, condition)
self.type = type

def get_category(self):
return self.__class__.__name__

def __str__(self):
return f"An object of type {self.get_category()} with id {self.id}. This is a {self.type} device."

def condition_description(self):
if self.condition == 0:
return f"Item condition is rated 0. This item is barely holding on!"
elif self.condition == 1:
return f"Items condition is rated 1. This item is hanging on by a thread!"
elif self.condition == 2:
return f"Items condition is rated 2. This item is living on a prayer."
elif self.condition == 3:
return f"Items condition is rated 3. This item is in working order."
elif self.condition == 4:
return f"Items condition is rated 4. This item is in good condition."
else:
return f"Items condition is rated 5. This item is in excellent condition."

#electronics = "Stereo" key="type"


# ------------------ WAVE 5 -----------------------
# Has an attribute id that is by default a unique integer
# Has an attribute type that is by default the string "Unknown"
# This attribute describes what kind of electronic device this is. Some example values might be “Kitchen Appliance”, “Game Console”, or “Health Tracker”
# When we initialize an instance of Electronics, we can optionally pass in a string with the keyword argument type
# Has an function get_category that returns "Electronics"
# Has a stringify method that returns "An object of type Electronics with id <id value>. This is a <type value> device."
32 changes: 31 additions & 1 deletion swap_meet/item.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,32 @@
import uuid

class Item:
pass
def __init__(self, id=None, condition=0):
self.condition = condition
#if id is not manually assigned
if id == None:
self.id = uuid.uuid4().int
#if id is manually assigned
else:
self.id = id
Comment on lines +7 to +11

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



def get_category(self):
return self.__class__.__name__

def __str__(self):
return f"An object of type {self.get_category()} with id {self.id}."

def condition_description(self):

Choose a reason for hiding this comment

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

Be careful about indentation! The only reason that you had to copy/paste this function into your Decor, Clothing, and Electronics classes is the missing indentation before this function. If you had indented here, it would have made condition_description a member of Item, and this function would automatically have been inherited by all the other derived classes.

if self.condition == 0:
return f"Item condition is rated 0. This item is barely holding on!"
elif self.condition == 1:
return f"Items condition is rated 1. This item is hanging on by a thread!"
elif self.condition == 2:
return f"Items condition is rated 2. This item is living on a prayer."
elif self.condition == 3:
return f"Items condition is rated 3. This item is in working order."
elif self.condition == 4:
return f"Items condition is rated 4. This item is in good condition."
else:
return f"Items condition is rated 5. This item is in excellent condition."
84 changes: 83 additions & 1 deletion swap_meet/vendor.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,84 @@
import uuid

#from item import Item


class Vendor:
pass
def __init__(self, inventory=[]):
self.inventory = inventory #each vendor will have an attribute named :inventory (an empty list)
Comment on lines +7 to +8

Choose a reason for hiding this comment

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

This is what's failing your integration tests. In Python, when you assign a "mutable" object like a list as a default value, every time the function uses that default value it will share the same instance of that object. The workaround is to use None as a default for lists and check for None in the initializer:

    def __init__(self, inventory = None):
        self.inventory = inventory if inventory else []

^-- if you do this instead, your integration tests will pass (after you unskip them).


def add(self, item):
self.inventory.append(item)
print(self.inventory)
print(item)
Comment on lines +12 to +13

Choose a reason for hiding this comment

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

You can remove prints once you're through with debugging.

return item

def remove(self, item):

if item not in self.inventory:
return False
else:
self.inventory.remove(item)
return item
Comment on lines +18 to +22

Choose a reason for hiding this comment

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

[suggestion] If your if body has a return, you technically don't need the else:. You could do:

        if item not in self.inventory:
            return False
        self.inventory.remove(item)
        return item


def get_by_id(self, id):
for item in self.inventory:
print(item.id)
print(id)
if item.id == id:
return item
return None


def swap_items(self, other_vendor, my_item, their_item):
if not my_item in self.inventory or not their_item in other_vendor.inventory:
return False
else:
self.remove(my_item)
self.add(their_item)
other_vendor.remove(their_item)
other_vendor.add(my_item)
return True
# these functions will return uuid objects **(not int)**

Choose a reason for hiding this comment

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

[nit] This comment seems out of date?


def swap_first_item(self, other_vendor):
if other_vendor.inventory == [] or self.inventory == []:
return False
else:
#look at the syntax here
other_vendor.add(self.inventory[0])
self.remove(self.inventory[0])
self.add(other_vendor.inventory[0])
other_vendor.remove(other_vendor.inventory[0])
Comment on lines +49 to +52

Choose a reason for hiding this comment

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

[nit] This looks a lot like swap_items. You could call self.swap_items instead of rewriting very similar logic. 😄

return True

def get_by_category(self, category):
objects = []

for item in self.inventory:
if item.get_category() == category:
objects.append(item)
return objects
Comment on lines +56 to +61

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:

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

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):

items = self.get_by_category(category)
if items == []:
return None
else:
highest_condition = items[0]
for item in items:
if item.condition >= highest_condition.condition:
highest_condition = item
return highest_condition
Comment on lines +69 to +73

Choose a reason for hiding this comment

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

Great job using loops for this! Once you're comfortable with them, you can do this same sort of thing with the max function:

return max(items, key=lambda item: item.condition)


def swap_best_by_category(self, other_vendor, my_priority, their_priority):
my_best_item = self.get_best_by_category(their_priority)

their_best_item = other_vendor.get_best_by_category(my_priority)

if my_best_item == None or their_best_item == None:
return False
else:
self.swap_items(other_vendor, my_best_item, their_best_item)
return True
Comment on lines +80 to +84

Choose a reason for hiding this comment

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

[suggestion] You could also simply return self.swap_items(other_vendor, my_best_item, their_best_item), since swap_items handles None.

1 change: 1 addition & 0 deletions tests/integration_tests/test_wave_01_02_03.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

@pytest.mark.skip

Choose a reason for hiding this comment

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

You should remove the skips on your integration tests. If you do, you'll see there are some errors. See my comment in vendor.py for what's going on there.

@pytest.mark.integration_test

def test_integration_wave_01_02_03():
# make a vendor
vendor = Vendor()
Expand Down
15 changes: 6 additions & 9 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,7 +40,7 @@ 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(
Expand All @@ -49,7 +49,4 @@ def test_removing_not_found_is_false():

result = vendor.remove(item)

raise Exception("Complete this test according to comments below.")
# *********************************************************************
# ****** Complete Assert Portion of this test **********
# *********************************************************************
assert result == False
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