Пример #1
0
def test_shopping_list_add_smartphones(smartphones):
    shopping_list = ShoppingList()
    size = 0
    for smartphone in smartphones:
        shopping_list.add_smartphone(smartphone)
        size += 1
        assert shopping_list.items() == size
        assert shopping_list.item(size - 1) == smartphone
Пример #2
0
def test_shopping_list_add_computers(computers):
    shopping_list = ShoppingList()
    size = 0
    for computer in computers:
        shopping_list.add_computer(computer)
        size += 1
        assert shopping_list.items() == size
        assert shopping_list.item(size - 1) == computer
Пример #3
0
def test_shopping_list_remove_item(smartphones, computers):
    shopping = ShoppingList()
    for computer in computers:
        shopping.add_computer(computer)
    for smartphone in smartphones:
        shopping.add_smartphone(smartphone)

    shopping.remove_item(0)
    assert shopping.item(0) == computers[1]

    with pytest.raises(ValidationError):
        shopping.remove_item(-1)
    with pytest.raises(ValidationError):
        shopping.remove_item(shopping.items())

    while shopping.items():
        shopping.remove_item(0)
    assert shopping.items() == 0
Пример #4
0
def test_shopping_list_change_quantity(smartphones):
    shopping = ShoppingList()
    shopping.add_smartphone(smartphones[0])
    shopping.change_quantity(0, Quantity(1))

    with pytest.raises(ValidationError):
        shopping.change_quantity(-1, Quantity(1))
    with pytest.raises(ValidationError):
        shopping.change_quantity(shopping.items(), Quantity(1))

    assert shopping.item(0).quantity.value == 1
Пример #5
0
class App:
    __filename = Path(__file__).parent.parent / 'shoppingList.csv'
    __delimiter = '\t'
    __logged = False
    __key = None
    __id_dictionary = []

    def __init__(self):
        self.__first_menu = self.init_first_menu()
        self.__menu = self.__init_shopping_list_menu()
        self.__shoppinglist = ShoppingList()

    def init_first_menu(self) -> Menu:
        return Menu.Builder(MenuDescription('SIGN IN'), auto_select=lambda: print('Welcome!')) \
            .with_entry(Entry.create('1', 'Login', is_logged=lambda: self.__login())) \
            .with_entry(Entry.create('2', 'Register', on_selected=lambda: self.__register())) \
            .with_entry(Entry.create('0', 'Exit', on_selected=lambda: print('Bye!'), is_exit=True)) \
            .build()

    def __init_shopping_list_menu(self) -> Menu:
        return Menu.Builder(MenuDescription('SHOPPING LIST'), auto_select=lambda: self.__print_items()) \
            .with_entry(Entry.create('1', 'Add Smartphone', on_selected=lambda: self.__add_smartphone())) \
            .with_entry(Entry.create('2', 'Add Computer', on_selected=lambda: self.__add_computer())) \
            .with_entry(Entry.create('3', 'Remove Item', on_selected=lambda: self.__remove_item())) \
            .with_entry(Entry.create('4', 'Change quantity', on_selected=lambda: self.__change_quantity())) \
            .with_entry(Entry.create('5', 'Sort by Manufacturer', on_selected=lambda: self.__sort_by_manufacturer())) \
            .with_entry(Entry.create('6', 'Sort by Price', on_selected=lambda: self.__sort_by_price())) \
            .with_entry(Entry.create('0', 'Exit', on_selected=lambda: print('Bye!'), is_exit=True)) \
            .build()

    def __login(self) -> bool:
        username = self.__read("Username", Username)
        password = self.__read("Password", Password)
        res = requests.post(url=f'{api_server}auth/login/', data={'username': username, 'password': password})
        if res.status_code != 200:
            print('This user does not exist!')
            return False
        self.__key = res.json()['key']
        return True

    def __register(self) -> None:
        username = self.__read("Username", Username)
        email = self.__read("Email", Email)
        password = self.__read("Password", Password)

        res = requests.post(url=f'{api_server}auth/registration/',
                            data={'username': username, 'email': email, 'password1': password,
                                  'password2': password})
        if res.status_code == 400:
            print('This user already exists!')

    def __print_items(self) -> None:
        print_sep = lambda: print('-' * 200)
        print_sep()
        fmt = '%-3s %-30s %-30s %-30s %-30s %-30s %-50s'
        print(fmt % ('#', 'CATEGORY', 'NAME', 'MANUFACTURER', 'PRICE', 'QUANTITY', 'DESCRIPTION'))
        print_sep()
        for index in range(self.__shoppinglist.items()):
            item = self.__shoppinglist.item(index)
            print(fmt % (index + 1, item.category, item.name, item.manufacturer, item.price, item.quantity,
                         item.description))

        print_sep()

    def __add_smartphone(self) -> None:
        smartphone = Smartphone(*self.__read_item())
        try:
            self.__shoppinglist.add_smartphone(smartphone)
            self.__save(smartphone)
            print('Smartphone added!')
        except ValueError:
            print('Smartphone already present in the list!')

    def __add_computer(self) -> None:
        computer = Computer(*self.__read_item())
        try:
            self.__shoppinglist.add_computer(computer)
            self.__save(computer)
            print('Computer added!')
        except ValueError:
            print('Computer already present in the list!')

    def __remove_item(self) -> None:
        def builder(value: str) -> int:
            validate('value', int(value), min_value=0, max_value=self.__shoppinglist.items())
            return int(value)

        index = self.__read('Index (0 to cancel operation)', builder)
        if index == 0:
            print('Operation cancelled!')
            return
        self.__delete(self.__shoppinglist.item(index - 1))
        self.__shoppinglist.remove_item(index - 1)
        print('Item removed!')

    def __change_quantity(self) -> None:
        def builder(value: str) -> int:
            validate('value', int(value), min_value=0, max_value=self.__shoppinglist.items())
            return int(value)

        index = self.__read('Index (0 to cancel operation)', builder)
        if index == 0:
            print('Operation cancelled!')
            return

        quantity = self.__read('New Quantity', Quantity.cast)
        self.__shoppinglist.change_quantity(index - 1, quantity)
        self.__update(self.__shoppinglist.item(index - 1))
        print('Quantity changed!')

    def __sort_by_manufacturer(self) -> None:
        self.__shoppinglist.sort_by_manufacturer()

    def __sort_by_price(self) -> None:
        self.__shoppinglist.sort_by_price()

    def __run(self) -> None:
        while not self.__first_menu.run() == (True, False):
            try:
                self.__fetch()
            except ValueError as e:
                print('Continuing with an empty list of items...')
            except RuntimeError:
                print('Failed to connect to the server! Try later!')
                return
            self.__menu.run()

    def run(self) -> None:
        try:
            self.__run()
        except Exception as e:
            print(e)
            print('Panic error!', file=sys.stderr)

    def __fetch(self) -> None:
        res = requests.get(url=f'{api_server}shopping-list/', headers={'Authorization': f'Token {self.__key}'})

        if res.status_code != 200:
            raise RuntimeError()

        json = res.json()
        for item in json:
            validate('row length', item, length=7)

            item_id = int(item['id'])
            name = Name(str(item['name']))
            category = str(item['category'])
            manufacturer = Manufacturer(str(item['manufacturer']))
            price = Price.create(int(int(item['price']) / 100), int(item['price']) % 100)
            quantity = Quantity(int(item['quantity']))

            self.__id_dictionary.append([item_id, name.value, manufacturer.value])

            description = Description(str(item['description']))

            if category == 'Smartphone':
                self.__shoppinglist.add_smartphone(Smartphone(name, manufacturer, price, quantity, description))
            elif category == 'Computer':
                self.__shoppinglist.add_computer(Computer(name, manufacturer, price, quantity, description))
            else:
                raise ValueError('Unknown item category in your shopping list')

    def __save(self, item: Any) -> None:
        req = requests.post(url=f'{api_server}shopping-list/add/',
                            headers={'Authorization': f'Token {self.__key}'},
                            data={'name': item.name.value, 'category': item.category,
                                  'manufacturer': item.manufacturer.value, 'price': item.price.value_in_cents,
                                  'quantity': item.quantity.value, 'description': item.description.value})

        self.__id_dictionary.append([req.json()['id'], item.name.value, item.manufacturer.value])

    def __update(self, item: Any) -> None:
        for i in range(len(self.__id_dictionary)):
            if (item.name.value, item.manufacturer.value) == (self.__id_dictionary[i][1], self.__id_dictionary[i][2]):
                requests.patch(url=f'{api_server}shopping-list/edit/{self.__id_dictionary[i][0]}',
                               headers={'Authorization': f'Token {self.__key}'}, data={'quantity': item.quantity.value})
                break

    def __delete(self, item: Any) -> None:
        index = None
        for i in range(len(self.__id_dictionary)):
            if (item.name.value, item.manufacturer.value) == (self.__id_dictionary[i][1], self.__id_dictionary[i][2]):
                requests.delete(url=f'{api_server}shopping-list/edit/{self.__id_dictionary[i][0]}',
                                headers={'Authorization': f'Token {self.__key}'})
                index = i
                break
        self.__id_dictionary.pop(index)

    @staticmethod
    def __read(prompt: str, builder: Callable) -> Any:
        while True:
            try:
                if prompt != 'Password':
                    line = input(f'{prompt}: ')
                else:
                    line = input(f'{prompt}: ')
                    # line = getpass(f'{prompt}: ')

                res = builder(line.strip())
                return res
            except (TypeError, ValueError, ValidationError) as e:
                print(e)

    def __read_item(self) -> Tuple[Name, Manufacturer, Price, Quantity, Description]:
        item = self.__read('Name', Name)
        manufacturer = self.__read('Manufacturer', Manufacturer)
        quantity = self.__read('Quantity', Quantity.cast)
        price = self.__read('Price', Price.parse)
        description = self.__read('Description', Description)
        return item, manufacturer, price, quantity, description