4
\$\begingroup\$

I have been working on some code for a basic inventory management system and I have all the features that I believe are need like adding parts displaying parts list and the such as you can see. I believe I have worked out all the bugs I can find. I'm looking to see if I got all the bugs out and maybe some optimizations that I am not seeing. The code is fully working and I'm just making sure I am not overlooking anything before I start using this code.

dict_member = {}
parts = dict_member
class Parts():
    def __init__(self, part, part_number, quantity):
        self.part = part
        self.part_number = part_number
        self.quantity = quantity
    def display (self):
        for part_number, parts in dict_member.items():
            print('Part Name:', parts.part + ', ''Part Number:' + parts.part_number + ', ''Quantity:' + parts.quantity)
            if parts == 0:
                print('No Parts Found in List')
    def add(self):
            part = input("Enter Name of Part:\n ")
            part_number = input("Enter Part Number:\n ")
            quantity = input("Enter Quantity:\n ")
            dict_member[part] = Parts(part, part_number, quantity)
    def remove(self):
            part = str(input("Enter Part Name to Remove\n"))
            if part in parts:
                del parts[part]
            else:
                print("Part Not Found.")
    def edit(self, part):
            if part in parts:
                par = input("Enter New Part\n")
                num = input("Enter New Part Number\n ")
                quan = input("Enter New Quantity\n ")
                del dict_member[part]
                dict_member[part] = Parts(par, num, quan)
            else:
                print("No such Part exists")

    def saveData(self):
        filename = input("Filename to save: ")
        out_file = open(filename, "wt")
        for part_number, parts in dict_member.items():
            out_file.write(parts.part + "," + parts.part_number + "," + parts.quantity + "\n")
        out_file.close()
        print("File Saved")

    def loadData(self):
        try:
            filename = input("Filename to load: ")
            in_file = open(filename, "rt")
            while True:
                in_line = in_file.readline()
                if not in_line:
                    break
                in_line = in_line[:-1]
                part, part_number, quantity = in_line.split(",")
                dict_member[part] = Parts(part, part_number, quantity)
            in_file.close()
        except FileNotFoundError:
            print("File Not Found.")
        return parts

def display_menu():
    try:
        print("")
        print("1. Parts ")
        print("2. Add Part")
        print("3. Remove Part ")
        print("4. Edit Part")
        print("5. Save Part List")
        print("6. Load Part List")
        print("9. Exit ")
        print("")
        return int(input("Selection> "))
    except ValueError:
        print("Selection Not Valid.")
    return parts

print("Welcome Sticks&Stones Inventory System")
part_instance = Parts(None, None, None)
menu_item = display_menu()
while menu_item != 9:
    if menu_item == 1:
        part_instance.display()
    elif menu_item == 2:
        part_instance.add()
    elif menu_item == 3:
        part_instance.remove()
    elif menu_item == 4:
        m = input("Enter Part Name to Edit\n")
        part_instance.edit(m)
    elif menu_item == 5:
        part_instance.saveData()
    elif menu_item == 6:
        part_instance.loadData()
    menu_item = display_menu()
print("Exiting Program...")
\$\endgroup\$
  • 2
    \$\begingroup\$ What exactly do you expect parts = dict_member to do? \$\endgroup\$ – jonrsharpe Jan 2 '17 at 9:01
  • \$\begingroup\$ why did you use exceptions for display menu? what are you trying to catch? exceptions are expensive. \$\endgroup\$ – ChrisIkeokwu Jan 2 '17 at 11:36
  • \$\begingroup\$ @ChrisIkeokwu I used the exception for the display menu just on the off chance the end user tried to enter something other then a number for the main menu. \$\endgroup\$ – Jason Ray Jan 2 '17 at 16:13
2
\$\begingroup\$

You are mixing two very different objects and tasks in your Parts class. On the one side there is the object of a Part and on the other hand there is a dictionary of parts which is your inventory system. You should separate the two:

import sys
from collections import namedtuple


class Part(namedtuple("Part", "name part_number quantity")):
    def __str__(self):
        return ", ".join(self)


class Parts(dict):
    def display (self):
        if not self:
            print('No Parts Found in List')
            return
        print()
        print('Name, Part Number, Quantity')
        for part in self.values():
            print(part)
        print()

    def add(self, *args):
        try:
            name, part_number, quantity = args
        except ValueError:
            name = input("Enter Name of Part:\n ")
            part_number = input("Enter Part Number:\n ")
            quantity = input("Enter Quantity:\n ")
        self[name] = Part(name, part_number, quantity)

    def remove(self, part=""):
        if not part:
            part = input("Enter Part Name to Remove\n")
        try:
            del self[part]
        except Keyerror:
            print("Part {} not found.".format(part))

    def edit(self, part=""):
        if not part:
            part = input("Enter Part Name to Edit\n")
        try:
            new_name = input("Enter new part name\n")
            number = input("Enter new part number\n ")
            quantity = input("Enter new quantity\n ")
            self[part] = Part(new_name, number, quantity)
        except KeyError:
            print("No such Part exists: {}".format(part))

    def save(self, filename=""):
        if not filename:
            filename = input("Filename to save: ")
        with open(filename, "wt") as out_file:
            for part in self.values():
                out_file.write("{}\n".format(part))
        print("File saved")

    def load(self, filename=""):
        if not filename:
            filename = input("Filename to load: ")
        try:
            with open(filename, "rt") as in_file:
                for line in in_file:
                    if not line:
                        break
                    part, part_number, quantity = line.strip().split(",")
                    self.add(part, part_number, quantity)
        except FileNotFoundError:
            print("File Not Found.")


def menu(inventory):
    menu_list = [("Parts", inventory.display),
                 ("Add Part", inventory.add),
                 ("Remove Part", inventory.remove),
                 ("Edit Part", inventory.edit),
                 ("Save Part List", inventory.save),
                 ("Load Part List", inventory.load),
                 ("Exit", sys.exit)]
    while True:
        for i, (name, _) in enumerate(menu_list, 1):
            print("{}. {}".format(i, name))
        try:
            user = int(input("Selection> "))
            menu_list[user-1][1]()
        except (ValueError, IndexError):
            print("Selection Not Valid.")

def main():
    print("Welcome to Sticks&Stones Inventory System")
    inventory = Parts()
    while True:
        menu(inventory)

if __name__ == '__main__':
    try:
        main()
    except (KeyboardInterrupt, SystemExit):
        print("Exiting Program...")

Here I made two classes. I also made the inventory a sub-class of dict. This way you don't have to keep an external dictionary (and could even have two different inventories at the same time, maybe for different things?).

All methods of the inventory take parameters if you want to, and ask for them if they are not supplied.

A dict has dict.values which directly gives you a list (or iterable) of all values.

The Part is just a data container, so I used collections.namedtuple here, and just added nicer printing by overriding the magic __str__ method, which is invoked when calling e.g. print(part).

\$\endgroup\$
  • \$\begingroup\$ On the edit part portion of the code I noticed you changed it to where it just adds parts to the inventory instead of actually editing the said part. Could you explain why its doing this now? \$\endgroup\$ – Jason Ray Jan 2 '17 at 16:26
  • \$\begingroup\$ @Jason You are right, it should manually set the key because otherwise it will be saved under new_name. \$\endgroup\$ – Graipher Jan 2 '17 at 17:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.