Source code for items.api

"""
The API for the items project
"""
from dataclasses import asdict, dataclass, field

from .db import DB

__all__ = [
    "Item",
    "ItemsDB",
    "ItemsException",
    "MissingSummary",
    "InvalidItemId",
]


[docs] @dataclass class Item: """Defines the items type with the attributes summary, owner and state. Attributes: summary (str): Summary of an item. Defaults to None. owner (str): The person working on an item. Defaults to None. state (str): The status of a task. Defaults to *todo*. """ summary: str = None owner: str = None state: str = "todo" id: int = field(default=None, compare=False)
[docs] @classmethod def from_dict(cls, d): """Returns an item instance from a dict.""" return Item(**d)
[docs] def to_dict(self): """Returns a dict from an item instance.""" return asdict(self)
[docs] class ItemsException(Exception): """Exception class used by the :class:`MissingSummary` and :class:`InvalidItemId` exceptions. """ pass
[docs] class MissingSummary(ItemsException): """Exception if an item does not have a summary when calling :func:`items.api.ItemsDB.add_item`.""" pass
[docs] class InvalidItemId(ItemsException): """Exception if an item has no summary.""" pass
[docs] class ItemsDB: """Database class to access the :file:`items_db` file.""" def __init__(self, db_path): self._db_path = db_path self._db = DB(db_path, ".items_db")
[docs] def add_item(self, item: Item): """Adds an item to the database. Args: item (Item): The arguments of the :class:`Item` class. Returns: int: The item id. Raises: MissingSummary: if there is no summary. """ if not item.summary: raise MissingSummary if item.owner is None: item.owner = "" item_id = self._db.create(item.to_dict()) self._db.update(item_id, {"id": item_id}) return item_id
[docs] def get_item(self, item_id: int): """Returns an item for the corresponding id. Args: item_id: (int): id of the item Returns: Item: Item instance from a dict. Raises: InvalidItemId: if None is returned. """ db_item = self._db.read(item_id) if db_item is not None: return Item.from_dict(db_item) else: raise InvalidItemId(item_id)
[docs] def list_items(self, owner=None, state=None): """Returns a list of all items. Args: owner: (str): Defaults to None. state: (str): Defaults to None. Returns: list: List of all :class:`Item` instances to which ``owner`` and ``state`` apply. """ all_items = self._db.read_all() if (owner is not None) and (state is not None): return [ Item.from_dict(t) for t in all_items if (t["owner"] == owner and t["state"] == state) ] elif owner is not None: return [ Item.from_dict(t) for t in all_items if t["owner"] == owner ] elif state is not None: return [ Item.from_dict(t) for t in all_items if t["state"] == state ] else: return [Item.from_dict(t) for t in all_items]
[docs] def count(self): """Returns the number of items in the db. Returns: int: The number of items in the db. """ return self._db.count()
[docs] def update_item(self, item_id: int, item_mods: Item): """Update an item with modifications. Args: item_id: (int): The id of the item that is to be updated. item_mods: (Item): The modifications to be made to this item. Raises: InvalidItemId: if a KeyError is raised. """ try: self._db.update(item_id, item_mods.to_dict()) except KeyError as exc: raise InvalidItemId(item_id) from exc
[docs] def start(self, item_id: int): """Sets an item state to in progress.""" self.update_item(item_id, Item(state="in progress"))
[docs] def finish(self, item_id: int): """Sets an item state to done.""" self.update_item(item_id, Item(state="done"))
[docs] def delete_item(self, item_id: int): """Removes an item from db with a given item id.""" try: self._db.delete(item_id) except KeyError as exc: raise InvalidItemId(item_id) from exc
[docs] def delete_all(self): """Removes all items from the db.""" self._db.delete_all()
[docs] def close(self): """Closes the db connection.""" self._db.close()
[docs] def path(self): """Prints the path to the db.""" return self._db_path