main.py 6.3 KB
Newer Older
1
"""
2
This program gathers information from the temp_data.csv file about temperature
3 4
"""

5
from pkg_resources import resource_filename
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
from typing import List
from uuid import uuid4
from sqlalchemy import create_engine
from sqlalchemy import and_
from sqlalchemy.sql import func, asc, desc
from sqlalchemy.orm import sessionmaker
from treelib import Tree
from project.modules.models import Author
from project.modules.models import Book
from project.modules.models import Publisher


def get_total_number_of_books_by_publishers(session, direction: str) -> List:
    """
    Get a list of publishers and the total number of books
    they've published

    :param session:             database session to work with
    :param direction:
    :return:
    """
    if direction not in ["asc", "desc"]:
        raise Exception(f"Unknown direction: {direction}")

    dir = desc if direction == "desc" else asc

    return (
        session.query(
            Publisher.name, func.count(Book.title).label("total_books")
        )
        .join(Publisher.books)
        .group_by(Publisher.name)
        .order_by(dir("total_books"))
    )
40 41


42
def get_total_number_of_authors_by_publishers(session, direction: str) -> List:
43
    """
44 45
    Get a list of publishers and the total number of authors
    they've published
46

47 48 49
    :param session:             database session to work with
    :param direction:
    :return:
50
    """
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
    if direction not in ["asc", "desc"]:
        raise Exception(f"Unknown direction: {direction}")

    dir = desc if direction == "desc" else asc

    return (
        session.query(
            Publisher.name, func.count(Author.fname).label("total_authors")
        )
        .join(Publisher.authors)
        .group_by(Publisher.name)
        .order_by(dir("total_authors"))
    )


def get_authors(session) -> List:
67
    """
68
    This function returns a list of author objects
69

70 71 72 73
    :param session:             database session to work with
    :return:                    list of Author objects
    """
    return session.query(Author).order_by(Author.lname).all()
74 75


76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
def add_new_item(session, author_name, book_title, publisher_name):
    """
    This function adds a new item to the database

    :param session:             database session to work with
    :param author_name:         authors full name
    :param book_title:          book title
    :param publisher_name:      publisher of book
    :return:                    None
    """
    # Get the author if exists
    fname, lname = author_name.split(" ")
    author = (
        session.query(Author)
        .filter(and_(Author.fname == fname, Author.lname == lname))
        .one_or_none()
    )

    # Get the book if exists
    book = (
        session.query(Book)
        .filter(Book.title == book_title)
        .one_or_none()
    )

    # Get the publisher if exists
    publisher = (
        session.query(Publisher)
        .filter(Publisher.name == publisher_name)
        .one_or_none()
    )
    # Does new item exist?
    if author is not None and book is not None and publisher is not None:
        raise Exception(
            "New item exists",
            author_name,
            book_title,
            publisher_name
        )
    # Create the author if didn't exist
    if author is None:
        author = Author(fname=fname, lname=lname)

    # Create the book if didn't exist
    if book is None:
        book = Book(title=book_title)

    # Create the publisher if didn't exist
    if publisher is None:
        publisher = Publisher(name=publisher_name)

    # Add the book to the author's books collection if didn't exist
    if book not in author.books:
        author.books.append(book)

    # Add the author to the publisher's collection if didn't exist
    if author not in publisher.authors:
        publisher.authors.append(author)

    # Add the book to the publisher's collection if didn't exist
    if book not in publisher.books:
        publisher.books.append(book)

    # Commit to the database
    session.commit()


def output_hierarchical_author_data(authors):
    """
    This function outputs the author/book/publisher information in
    a hierarchical manner
147

148 149
    :param authors:         the collection of root author objects
    :return:                None
150
    """
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
    authors_tree = Tree()
    authors_tree.create_node("Authors", "authors")
    for author in authors:
        authors_tree.create_node(
            f"{author.fname} {author.lname}",
            f"{author.fname} {author.lname}",
            parent="authors",
        )
        for book in author.books:
            authors_tree.create_node(
                f"{book.title}",
                f"{book.title}",
                parent=f"{author.fname} {author.lname}",
            )
            for publisher in book.publishers:
                authors_tree.create_node(
                    f"{publisher.name}", uuid4(), parent=f"{book.title}"
                )
    # Output the hierarchical authors data
    authors_tree.show()
171 172 173


def main():
174 175 176
    """
    Main entry point of program
    """
177 178
    print("starting")

179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
    # Connect to the database using SqlAlchemy
    sqlite_filepath = resource_filename(
        "project.data", "author_book_publisher.db"
    )
    engine = create_engine(f"sqlite:///{sqlite_filepath}")
    Session = sessionmaker()
    Session.configure(bind=engine)
    session = Session()

    # Get the total number of books printed by each publisher
    total_books_by_publisher = get_total_number_of_books_by_publishers(
        session, "desc"
    )
    for row in total_books_by_publisher:
        print(f"Publisher: {row.name}, total books: {row.total_books}")
194 195
    print()

196 197 198 199 200 201
    # Get the total number of authors each publisher publishes
    total_authors_by_publisher = get_total_number_of_authors_by_publishers(
        session, "desc"
    )
    for row in total_authors_by_publisher:
        print(f"Publisher: {row.name}, total authors: {row.total_authors}")
202 203
    print()

204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
    # Output hierarchical authors data
    authors = get_authors(session)
    output_hierarchical_author_data(authors)

    # Add a new book
    add_new_item(
        session,
        author_name="Stephen King",
        book_title="The Stand",
        publisher_name="Random House",
    )

    # Output the updated hierarchical authors data
    authors = get_authors(session)
    output_hierarchical_author_data(authors)

220 221 222 223 224
    print("finished")


if __name__ == "__main__":
    main()