diff --git a/final_task/MANIFEST.in b/final_task/MANIFEST.in new file mode 100644 index 0000000..b9e970f --- /dev/null +++ b/final_task/MANIFEST.in @@ -0,0 +1 @@ +include rss_reader/ARIALUNI.ttf \ No newline at end of file diff --git a/final_task/README.md b/final_task/README.md index 7af281f..d29bbd7 100644 --- a/final_task/README.md +++ b/final_task/README.md @@ -1,3 +1,101 @@ -# Your readme here -Some text. -Checkout how to write this file using *markdown*. +RSS-reader +============================= +Pure Python command-line RSS reader. + +INSTALLATION +------------ +First of all open command line and install setuptools, just write 'pip install -u setuptools'. +After that you can install our app, enter 'python setup.py install' in command line opened as an administrator +in folder final_task, where setup.py is lying. +By this point if you want to launch the application, enter 'rss-reader [arguments]'. + +For work with conversion, in your folder rss_reader should be ARIALUNI.ttf. + +USING +------------ +rss_reader.py [--help] [--source SOURCE] [--version] [--json] [--verbose] [--limit LIMIT] [--date DATE] [--to-html PATH] + [--to-pdf TO_PDF] + + +positional arguments: + + source RSS url + +optional arguments: + + -h, --help show this help message and exit + + --limit LIMIT Limit news topics if this parameter provided + + --version Print version info + + --json Print result as JSON in stdout + + --verbose Outputs verbose status messages + + --date Print the new from the specified day, YYYYMMDD format + + --to-html TO_HTML Convert news in html format, need path, where the file + will be saved + + --to-pdf TO_PDF Convert news in pdf format, need path, where the file + will be saved + +FORMAT OF PRESENTING NEWS +------------ +Feed: [feed] +__________________________________________________________________ +Title: [title] + +Date: [date of publishing] + +Link: [link of news] + +[[image: alt of image][2]description of news] # if the image exists + +[description of news] # if doesn't + +Links: + +[1]: [link of news] + +[2]: [link of image, if it exists] +__________________________________________________________________ +... + +JSON FORMAT +------------ +If arguments '--json' is provided, news will be presented in json format, the structure will be like this: + +[ + + { + + "Feed": [feed], + + "Title": [title], + + "Date": [date of publishing], + + "Description": [description], + + "Link [1]": [link of news], + + "Link [2]": [link of image, if it exists] + + }, + + ... + +] + +Description will be in format [[image: alt of image][2]description of news], if the image exists, +or in format [description of news], if it doesn't. + +CONVERTING TO HTML OR PDF FORMAT +------------ +You can download news in one of those formats, news can be read from the website or from the cache. +For doing that you should enter directory, and if it's correct, news will be converted and you will see a message, +which tells, if converting was successful or not. +In prepared file (it is named news.pdf or news.html) will be all information about news, if there is no connection +to the Internet, instead of image there will be url of it. \ No newline at end of file diff --git a/final_task/rss_reader/ARIALUNI.TTF b/final_task/rss_reader/ARIALUNI.TTF new file mode 100644 index 0000000..51a18bc Binary files /dev/null and b/final_task/rss_reader/ARIALUNI.TTF differ diff --git a/final_task/rss_reader/console_interface.py b/final_task/rss_reader/console_interface.py new file mode 100644 index 0000000..2518d8a --- /dev/null +++ b/final_task/rss_reader/console_interface.py @@ -0,0 +1,54 @@ +import argparse +import logging + + +def parse_args(): + parser = argparse.ArgumentParser(description="Pure Python command-line RSS reader.") + parser.add_argument("source", help="RSS url") + parser.add_argument("--limit", type=int, help="Limit news topics if this parameter provided") + parser.add_argument("--version", action="version", version="Version 1.4.2", help="Print version info") + parser.add_argument("--json", action="store_true", help="Print result as JSON in stdout") + parser.add_argument("--verbose", action="store_true", help="Outputs verbose status messages") + parser.add_argument("--date", type=str, help="Print the new from the specified day, YYYYMMDD format") + parser.add_argument("--to-html", type=str, + help="Convert news in html format, need path, where the file will be saved") + parser.add_argument("--to-pdf", type=str, + help="Convert news in pdf format, need path, where the file will be saved") + args = parser.parse_args() + return args + + +def get_args(args): + source = args.source + json = False + date = None + path = None + to_html = False + to_pdf = False + limit = -1 + if args.limit: + limit = args.limit + if args.json: + json = True + if args.verbose: + verbose = True + logging.basicConfig(level=logging.DEBUG, format='%(process)d-%(levelname)s-%(message)s') + else: + logging.basicConfig(filename='app.log', level=logging.DEBUG, filemode='w', + format='%(name)s - %(levelname)s - %(message)s') + if args.date: + date = args.date + logging.debug("Check in interface") + if args.to_html: + to_html = True + path = args.to_html + if args.to_pdf: + to_pdf = True + path = args.to_pdf + return {"url": source, + "lim": limit, + "json": json, + "date": date, + "path": path, + "html": to_html, + "pdf": to_pdf} diff --git a/final_task/rss_reader/conversion_functions.py b/final_task/rss_reader/conversion_functions.py new file mode 100644 index 0000000..6c61208 --- /dev/null +++ b/final_task/rss_reader/conversion_functions.py @@ -0,0 +1,154 @@ +import os +import logging +import requests +from pkg_resources import resource_filename +from yattag import Doc +from fpdf import FPDF +from database_functions import put_into_db +from information_about_news import taking_information_from_feedparser, InfoAboutNews + + +def get_path(path_to_file, expansion): + """ Checks if the directory is correct or not""" + + if not os.path.exists(path_to_file): + print("Invalid directory") + logging.error("Directory doesn't exist") + return None + filename = os.path.join(path_to_file, "news." + expansion) + logging.debug("Directory exists") + return filename + + +def convert_into_html_format(feed, dict_of_args): + """ Creates html file in specified directory and puts information in database, if it was read from website""" + + # openning html-file to write + filename = get_path(dict_of_args.get("path"), "html") + if not filename: + return None + file = open(filename, 'w') + logging.debug("File was opened successfully") + + doc, tag, text, line = Doc().ttl() + line('h1', 'News from ' + dict_of_args.get("url")) + + for feed_entry in feed: + # getting list of tags + if dict_of_args.get("date") is None: + list_of_tags = taking_information_from_feedparser(feed_entry, dict_of_args) + else: + list_of_tags = feed_entry + news_info = InfoAboutNews(list_of_tags) + + with tag('item'): + with tag('h2'): + text(news_info.title) + with tag('link'): + text(news_info.link) + with tag('p'): + text(news_info.date) + with tag('h3'): + if news_info.link_of_img: + with tag('img', src=news_info.link_of_img, alt=news_info.link_of_img, + border="0", align="left", hspace="5"): + pass + text(news_info.description) + with tag('br'): + with tag('br'): + pass + + # putting news in database + if not dict_of_args.get("date"): + put_into_db(news_info.feed, news_info.title, + feed_entry.get("published_parsed", feed_entry.published_parsed), + news_info.description, news_info.link, news_info.link_of_img) + try: + file.write(doc.getvalue()) + print("News were written in html file") + except Exception: + logging.error(Exception) + print("Can't write information in html file") + finally: + file.close() + return doc.getvalue() + + +def get_image(link_of_img, count, pdf): + """ Downloads image from the Internet and puts it into pdf file""" + + try: + img = requests.get(link_of_img) + out = open("img" + str(count) + ".jpg", "wb") + out.write(img.content) + out.close() + pdf.image("img" + str(count) + ".jpg", x=100, w=20) + except requests.exceptions.ConnectionError: + print("Can't download image, because of connection to the Internet") + pdf.multi_cell(0, 8, txt=link_of_img, align="C") + logging.error(requests.exceptions.ConnectionError) + except Exception as e: + logging.error("Something wrong with format of image") + pdf.multi_cell(0, 8, txt=link_of_img, align="C") + logging.error(e) + + +def adding_text_in_pdf(pdf, text, size_of_font, indent): + """ Puts text of specified size in pdf file""" + + pdf.set_font('FreeSans', size=size_of_font) + pdf.multi_cell(200, indent, txt=(text), align="C") + + +def get_font(pdf) -> bool: + """ Gets information about path to font and adds it, if it's possible""" + + pdf.add_font('FreeSans', '', resource_filename(__name__, "ARIALUNI.ttf"), True) + return True + + +def convert_into_pdf_format(feed, dict_of_args): + """ Creates pdf file in specified directory and puts information in database, if it was read from website""" + + filename = get_path(dict_of_args.get("path"), "pdf") + if not filename: + return None + logging.debug("File was opened successfully") + + pdf = FPDF() + pdf.add_page(('P', 'A4')) + if not get_font(pdf): + return None + pdf.set_margins(10, 10, 10) + + count = 0 + for feed_entry in feed: + if dict_of_args.get("date") is None: + list_of_tags = taking_information_from_feedparser(feed_entry, dict_of_args) + else: + list_of_tags = feed_entry + news_info = InfoAboutNews(list_of_tags) + + adding_text_in_pdf(pdf, news_info.title + "\n", 14, 10) + adding_text_in_pdf(pdf, news_info.date, 10, 8) + adding_text_in_pdf(pdf, news_info.link, 8, 8) + if news_info.link_of_img: + get_image(news_info.link_of_img, count, pdf) + count += 1 + adding_text_in_pdf(pdf, news_info.description, 10, 6) + adding_text_in_pdf(pdf, "_________________\n", 10, 10) + + # putting news in database + if dict_of_args.get("date") is None: + put_into_db(news_info.feed, news_info.title, + feed_entry.get("published_parsed", feed_entry.published_parsed), + news_info.description, news_info.link, news_info.link_of_img) + try: + pdf.output(filename) + print("News were written in pdf file") + + for i in range(count): + os.remove("img" + str(i) + ".jpg") + except Exception: + logging.error(Exception) + print("Can't write information in pdf file") diff --git a/final_task/rss_reader/database_functions.py b/final_task/rss_reader/database_functions.py new file mode 100644 index 0000000..43209c5 --- /dev/null +++ b/final_task/rss_reader/database_functions.py @@ -0,0 +1,73 @@ +import logging +import sqlite3 +import json +from contextlib import closing +from information_about_news import InfoAboutNews + + +def check_existance(name) -> bool: + with closing(open_database()) as con: + flag = False + try: + if con: + cur = con.cursor() + cur.execute("SELECT * from " + name) + logging.debug("Table exists") + flag = True + except Exception: + flag = False + return flag + + +def create_table(): + con = open_database() + if con: + cur = con.cursor() + cur.execute("CREATE TABLE cache(feed TEXT, title TEXT, date TEXT, description TEXT, link1 TEXT, link2 TEXT," + "UNIQUE (title, date) ON CONFLICT IGNORE)") + con.commit() + con.close() + + +def open_database(): + con = None + try: + con = sqlite3.connect("mydatabase.db") + logging.debug("Database opened successfully") + cur = con.cursor() + return con + except (sqlite3.DatabaseError) as error: + logging.error(error) + return None + + +def put_into_db(url, title, date, text, link, link_of_img): + """ Writes infomation about news in database""" + + exists = check_existance("cache") + if not exists: + create_table() + with closing(open_database()) as con: + if con: + cur = con.cursor() + date_of_publishing = (str(date.tm_year) + (str(date.tm_mon)) + (str(date.tm_mday))) + cur.execute("INSERT INTO cache VALUES (?, ?, ?, ?, ?, ?)", (url, title, date_of_publishing, text, link, + link_of_img)) + con.commit() + + +def json_from_cashe(rows): + """ Convets news from cache in json format""" + + list_to_json_format = [] + for row in rows: + news_info = InfoAboutNews(row) + dictionary = {"Title": news_info.title, + "Date": news_info.date, + "Description": news_info.description, + "Link [1]": news_info.link} + if news_info.link_of_img: + dictionary.update({"Link [2]": news_info.link_of_img}) + list_to_json_format.append(dictionary) + json_data = json.dumps(list_to_json_format, indent=5, ensure_ascii=False) + print(json_data) diff --git a/final_task/rss_reader/information_about_news.py b/final_task/rss_reader/information_about_news.py new file mode 100644 index 0000000..a085e94 --- /dev/null +++ b/final_task/rss_reader/information_about_news.py @@ -0,0 +1,63 @@ +import html + +def find_description(description) -> str: + """ Parses description in readable format, return description""" + + text = description + index_of_text_beginning = description.find(">") + while index_of_text_beginning != -1: + if index_of_text_beginning != len(description) - 1: + if description[index_of_text_beginning + 1] != "<": + text = description[index_of_text_beginning + 1:] + text = text[: text.find('<')] + break + description = description[index_of_text_beginning + 1:] + index_of_text_beginning = description.find(">") + return text + +def taking_information_from_feedparser(feed, dict_of_args) -> list: + """ Creates a list with arguments: title, date, link, description, link of image and description of image, if + they exist for each news""" + + list_of_args = [dict_of_args.get("url"), html.unescape(feed.get("title", "")), + feed.get("published", "")] + description = feed.get("description", "") + description_to_put = find_description(description) + + # trying to get link of image and description of image + index_of_link = description.find("src") + link_of_img = "" + if index_of_link != -1: + link_of_img = description[index_of_link + 5:] + link_of_img = link_of_img[: link_of_img.find('"')] + + index_of_link = description.find("alt") + alt_of_img = description[index_of_link + 5:] + alt_of_img = alt_of_img[: alt_of_img.find('"')] + + description_to_put = "[image: " + alt_of_img + "][2]" + description_to_put + list_of_args.append(html.unescape(description_to_put)) + list_of_args.append(feed.get("link", "")) + list_of_args.append(link_of_img) + return list_of_args + +def printing(args): + """ Just prints news""" + + if args.link_of_img: + print("Title: %s\nDate: %s\nLink: %s\n\n%s\n\nLinks:\n[1]: %s\n[2]: %s" % + (args.title, args.date, args.link, args.description, args.link, args.link_of_img)) + else: + print("Title: %s\nDate: %s\nLink: %s\n\n%s\n\nLinks:\n[1]: %s" % + (args.title, args.date, args.link, args.description, args.link)) + print("__________________________________________________________________") + +class InfoAboutNews(): + + def __init__(self, list_of_args): + self.feed = list_of_args[0] + self.title = list_of_args[1] + self.date = list_of_args[2] + self.description = list_of_args[3] + self.link = list_of_args[4] + self.link_of_img = list_of_args[5] \ No newline at end of file diff --git a/final_task/rss_reader/requirements.txt b/final_task/rss_reader/requirements.txt index e69de29..ee05289 100644 --- a/final_task/rss_reader/requirements.txt +++ b/final_task/rss_reader/requirements.txt @@ -0,0 +1,5 @@ +feedparser == 5.2.1 +doc == 0.1.0 +yattag == 1.12.2 +fpdf == 1.7.2 +requests == 2.22.0 diff --git a/final_task/rss_reader/rss_parser.py b/final_task/rss_reader/rss_parser.py new file mode 100644 index 0000000..b464b26 --- /dev/null +++ b/final_task/rss_reader/rss_parser.py @@ -0,0 +1,106 @@ +from contextlib import closing +import feedparser +import json +import logging +from database_functions import put_into_db, check_existance, json_from_cashe +from database_functions import open_database +from conversion_functions import convert_into_html_format, convert_into_pdf_format +from information_about_news import InfoAboutNews, taking_information_from_feedparser, printing + + +def print_cache(dict_of_args): + """ Prints news from database from the specified day.""" + + exists = check_existance("cache") + if not exists: + print("There is no cache soon") + logging.error("Database doesn't exist") + return None + with closing(open_database()) as con: + if con: + cur = con.cursor() + if dict_of_args.get("lim") > 0: + cur.execute("SELECT * from cache WHERE feed = ? AND date = ? LIMIT ?", + (dict_of_args.get("url"), dict_of_args.get("date"), str(dict_of_args.get("lim")))) + else: + cur.execute("SELECT * from cache WHERE feed = ? AND date = ?", + (dict_of_args.get("url"), dict_of_args.get("date"))) + + rows = cur.fetchall() + if not rows: + print("No results\nTry to enter another date or url") + logging.debug("No news from this date or url") + return None + if dict_of_args.get("json"): + json_from_cashe(rows) + elif dict_of_args.get("html"): + convert_into_html_format(rows, dict_of_args) + elif dict_of_args.get("pdf"): + convert_into_pdf_format(rows, dict_of_args) + else: + for row in rows: + news_info = InfoAboutNews(row) + printing(news_info) + else: + print("Can't connect to database") + logging.error("No connection to database") + + +def printing_news(feed, dict_of_args): + """ Prints news""" + + print(feed) + print("Feed: " + feed.feed.get("title", "")) + print("__________________________________________________________________") + for index, feed_entry in enumerate(feed.entries): + list_of_args = taking_information_from_feedparser(feed_entry, dict_of_args) + news_info = InfoAboutNews(list_of_args) + printing(news_info) + put_into_db(news_info.feed, news_info.title, + feed_entry.get("published_parsed", feed.feed.published_parsed), + news_info.description, news_info.link, news_info.link_of_img) + + +def parse_to_json_format(feed, dict_of_args): + """ Converts to json format and prints""" + + list_to_json = [] + for feed_entry in feed.entries: + list_of_args = taking_information_from_feedparser(feed_entry, dict_of_args) + news_info = InfoAboutNews(list_of_args) + dictionary = {"Title": news_info.title, "Date": news_info.date, + "Description": news_info.description, "Link [1]": news_info.link} + if news_info.link_of_img: + dictionary.update({"Link [2]": news_info.link_of_img}) + list_to_json.append(dictionary) + put_into_db(news_info.feed, news_info.title, + feed_entry.get("published_parsed", feed.feed.published_parsed), + news_info.description, news_info.link, news_info.link_of_img) + + # converts to json + json_data = json.dumps(list_to_json, indent=5, ensure_ascii=False) + print(json_data) + + +def parse(dict_of_args): + """ Parses news""" + + feed = feedparser.parse(dict_of_args.get("url")) + if feed.get('bozo') == 1: + string_exception = feed.get('bozo_exception') + logging.error(string_exception) + print(string_exception) + return None + + logging.debug("Parsing from website was successful") + if dict_of_args.get("lim") > -1: + feed.entries = feed.entries[:dict_of_args.get("lim")] + if dict_of_args.get("json"): + parse_to_json_format(feed, dict_of_args) + elif dict_of_args.get("html"): + convert_into_html_format(feed.entries, dict_of_args) + elif dict_of_args.get("pdf"): + convert_into_pdf_format(feed.entries, dict_of_args) + else: + printing_news(feed, dict_of_args) + return None diff --git a/final_task/rss_reader/rss_reader.py b/final_task/rss_reader/rss_reader.py index e69de29..a358fdb 100644 --- a/final_task/rss_reader/rss_reader.py +++ b/final_task/rss_reader/rss_reader.py @@ -0,0 +1,28 @@ +from console_interface import parse_args +import logging +import sqlite3 +from rss_parser import * +from console_interface import get_args + + +def main(): + args = parse_args() + dict_of_args = get_args(args) + logging.debug("Check in main") + try: + if dict_of_args.get("date"): + print_cache(dict_of_args) + else: + parse(dict_of_args) + except sqlite3.OperationalError: + print("Something wrong with database") + except OSError: + print("Some problems") + logging.error(OSError) + logging.error("File can't be opened") + except Exception: + print("Sorry, for some reason the app can't work") + + +if __name__ == '__main__': + main() diff --git a/final_task/setup.py b/final_task/setup.py index e69de29..42ab25e 100644 --- a/final_task/setup.py +++ b/final_task/setup.py @@ -0,0 +1,21 @@ +from setuptools import setup, find_packages +import os + +setup(name='Rss reader', + version='1.4.3', + description='Pure Python command-line RSS reader.', + author='Marina Romanchuk', + author_email='marina-romanchuk-2015@mail.ru', + data_files=[('rss_reader', ['rss_reader/ARIALUNI.ttf'])], + install_requires=['feedparser', 'doc', 'yattag', 'requests', 'fpdf'], + include_package_data=True, + zip_safe=False, + packages=find_packages(), + scripts=['rss_reader/rss_parser.py', + 'rss_reader/console_interface.py', + 'rss_reader/database_functions.py', + 'rss_reader/rss_reader.py', + 'rss_reader/conversion_functions.py', + 'rss_reader/information_about_news.py'], + entry_points={'console_scripts': ['rss-reader=rss_reader:main']} +) \ No newline at end of file diff --git a/final_task/tests/test_console_interface.py b/final_task/tests/test_console_interface.py new file mode 100644 index 0000000..2dc5b6a --- /dev/null +++ b/final_task/tests/test_console_interface.py @@ -0,0 +1,28 @@ +import sys +sys.path.insert(1, 'final_task/rss_reader') +from console_interface import * +import unittest +import argparse +from unittest import mock + + +class TestParsArgs(unittest.TestCase): + @mock.patch('argparse.ArgumentParser.parse_args', + return_value=argparse.Namespace(source="https://news.yahoo.com/rss/", version='1.4.2', json=False, + verbose=False, limit=5, date="20191123", to_html=False, to_pdf=True, + path=r"C:\Users\Lenovo\PycharmProjects\final_task\FinalTaskRssParser\final_task")) + + def test_parsing(self, mock_args): + args = parse_args() + self.assertEqual(args.source, "https://news.yahoo.com/rss/") + self.assertEqual(args.limit, 5) + self.assertEqual(args.date, "20191123") + self.assertEqual(args.version, "1.4.2") + self.assertEqual(args.json, False) + self.assertEqual(args.verbose, False) + self.assertEqual(args.to_pdf, True) + self.assertEqual(args.to_html, False) + self.assertEqual(args.path, r"C:\Users\Lenovo\PycharmProjects\final_task\FinalTaskRssParser\final_task") + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/final_task/tests/test_conversion_functions.py b/final_task/tests/test_conversion_functions.py new file mode 100644 index 0000000..97d15f5 --- /dev/null +++ b/final_task/tests/test_conversion_functions.py @@ -0,0 +1,55 @@ +import sys +sys.path.insert(1, 'final_task/rss_reader') +from conversion_functions import * +import unittest +from unittest.mock import patch + +class TestDatabaseFunctions(unittest.TestCase): + + def setUp(self): + + self.dict_of_args = { + "url": "https://news.yahoo.com/rss/", + "lim": 1, + "json": False, + "date": "20191125", + "path": r"C:\Users\Lenovo\PycharmProjects\final_task\FinalTaskRssParser\final_task\tests", + "html": True, + "pdf": False} + + self.news = ["https://news.yahoo.com/rss/", "Protests after snake kills Indian schoolgirl in class", + "Fri, 22 Nov 2019 08:55:59 -0500", "[image: Protests after snake kills Indian schoolgirl in class]" + "[2]Students at an Indian school protested Friday after a 10-year-old pupil died after being " + "bitten by a snake lurking in a hole under her desk.", "https://news.yahoo.com/protests-snake-" + "kills-indian-schoolgirl-class-135559540.html", "http://l2.yimg.com/uu/api/res/1.2/iKaHCLlg9vdX0PD" + "Z4ZGHYA--/YXBwaWQ9eXRhY2h5b247aD04Njt3PTEzMDs-/http://media.zenfs.com/en_us/News/afp.com/41e95a0b" + "70637cceca42280de069ef90ce41026d.jpg"] + + self.path = r"C:\Users\Lenovo\PycharmProjects\final_task\FinalTaskRssParser\final_task\tests" + + self.result_of_conversion = '

News from https://news.yahoo.com/rss/

' \ + '

Protests after snake kills Indian schoolgirl in class

' \ + 'https://news.yahoo.com/protests-snake-kills-indian-schoolgirl-class-135' \ + '559540.html' \ + '

Fri, 22 Nov 2019 08:55:59 -0500

' \ + '

' \ + '[image: Protests after snake kills Indian schoolgirl in class][2]Students at' \ + ' an Indian school protested Friday after a 10-year-old pupil died after being ' \ + 'bitten by a snake lurking in a hole under her desk.





' + + def test_get_path_to_file(self): + self.assertEqual(get_path(self.path, "pdf"), + r"C:\Users\Lenovo\PycharmProjects\final_task\FinalTaskRssParser\final_task\tests\news.pdf") + self.assertEqual(get_path("dch", "pdf"), None) + + def test_convert(self): + document = convert_into_html_format([self.news], self.dict_of_args) + self.assertEqual(document, self.result_of_conversion) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/final_task/tests/test_database_functions.py b/final_task/tests/test_database_functions.py new file mode 100644 index 0000000..9a04db4 --- /dev/null +++ b/final_task/tests/test_database_functions.py @@ -0,0 +1,41 @@ +import sys +sys.path.insert(1, 'final_task/rss_reader') +from database_functions import * +import unittest +from io import StringIO +from unittest.mock import patch + +class TestDatabaseFunctions(unittest.TestCase): + + def setUp(self): + + self.news = ["https://news.yahoo.com/rss/", "Protests after snake kills Indian schoolgirl in class", + "Fri, 22 Nov 2019 08:55:59 -0500", "[image: Protests after snake kills Indian schoolgirl in class]" + "[2]Students at an Indian school protested Friday after a 10-year-old pupil died after being " + "bitten by a snake lurking in a hole under her desk.", "https://news.yahoo.com/protests-snake-" + "kills-indian-schoolgirl-class-135559540.html", "http://l2.yimg.com/uu/api/res/1.2/iKaHCLlg9vdX0PD" + "Z4ZGHYA--/YXBwaWQ9eXRhY2h5b247aD04Njt3PTEzMDs-/http://media.zenfs.com/en_us/News/afp.com/41e95a0b" + "70637cceca42280de069ef90ce41026d.jpg"] + + def test_exist_table(self): + self.assertEqual(check_existance("new"), False) + + def test_print_in_json_format(self): + self.result = "[\n {\n" + self.result += ' "Title": "Protests after snake kills Indian schoolgirl in class",\n' + self.result += ' "Date": "Fri, 22 Nov 2019 08:55:59 -0500",\n' + self.result += ' "Description": "[image: Protests after snake kills Indian schoolgirl in class][2]' \ + 'Students at an Indian school protested Friday after a 10-year-old pupil died after being bi' \ + 'tten by a snake lurking in a hole under her desk.",\n' + self.result += ' "Link [1]": "https://news.yahoo.com/protests-snake-kills-indian-schoolgirl-class-' \ + '135559540.html",\n' + self.result += ' "Link [2]": "http://l2.yimg.com/uu/api/res/1.2/iKaHCLlg9vdX0PDZ4ZGHYA--/YXBwaWQ9e' \ + 'XRhY2h5b247aD04Njt3PTEzMDs-/http://media.zenfs.com/en_us/News/afp.com/41e95a0b70637cceca422' \ + '80de069ef90ce41026d.jpg"\n' + self.result += " }\n]" + with patch('sys.stdout', new=StringIO()) as fake_out_put: + json_from_cashe([self.news]) + self.assertEqual(fake_out_put.getvalue().strip(), self.result) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/final_task/tests/test_information_about_news.py b/final_task/tests/test_information_about_news.py new file mode 100644 index 0000000..750082e --- /dev/null +++ b/final_task/tests/test_information_about_news.py @@ -0,0 +1,63 @@ +import sys + +sys.path.insert(1, 'final_task/rss_reader') +from information_about_news import * +import unittest +from io import StringIO +from unittest.mock import patch + +class TestInformationAboutNews(unittest.TestCase): + + def setUp(self): + self.description_from_website = '

Protests after snake kills Indian schoolgirl i' \
+                                        'n classStudents at an Indian school protested Friday ' \ + 'after a 10-year-old pupil died after being bitten by a snake lurking in a' \ + ' hole under her desk.


' + + self.news = InfoAboutNews(["https://news.yahoo.com/rss/", + + "Protests after snake kills Indian schoolgirl in class", + + "Fri, 22 Nov 2019 08:55:59 -0500", + + "[image: Protests after snake kills Indian schoolgirl in class][2]Students at an " + "Indian school protested Friday after a 10-year-old pupil died after being bitten " + "by a snake lurking in a hole under her desk.", + + "https://news.yahoo.com/protests-snake-kills-indian-schoolgirl-class-135559540.html", + + "http://l2.yimg.com/uu/api/res/1.2/iKaHCLlg9vdX0PDZ4ZGHYA--/YXBwaWQ9eXRhY2h5b247aD04" + "Njt3PTEzMDs-/http://media.zenfs.com/en_us/News/afp.com/41e95a0b70637cceca42280de069" + "ef90ce41026d.jpg"]) + + self.output = "Title: Protests after snake kills Indian schoolgirl in class\n" + self.output += "Date: Fri, 22 Nov 2019 08:55:59 -0500\n" + self.output += "Link: https://news.yahoo.com/protests-snake-kills-indian-schoolgirl-class-135559540.html\n" + self.output += "\n[image: Protests after snake kills Indian schoolgirl in class][2]" + self.output += "Students at an Indian school protested Friday after a 10-year-old pupil died after being " \ + "bitten by a snake lurking in a hole under her desk.\n" + self.output += "\nLinks:\n" + self.output += "[1]: https://news.yahoo.com/protests-snake-kills-indian-schoolgirl-class-135559540.html\n" + self.output += "[2]: http://l2.yimg.com/uu/api/res/1.2/iKaHCLlg9vdX0PDZ4ZGHYA--/YXBwaWQ9eXRhY2h5b247aD04" \ + "Njt3PTEzMDs-/http://media.zenfs.com/en_us/News/afp.com/41e95a0b70637cceca42280de069" \ + "ef90ce41026d.jpg\n" + self.output += '__________________________________________________________________' + + def test_find_description(self): + self.assertEqual(find_description(self.description_from_website), "Students at an Indian school protested " + "Friday after a 10-year-old pupil died " + "after being bitten by a snake lurking " + "in a hole under her desk.") + + def test_print_news(self): + with patch('sys.stdout', new=StringIO()) as fake_out_put: + printing(self.news) + self.assertEqual(fake_out_put.getvalue().strip(), self.output) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/final_task/tests/test_rss_parser.py b/final_task/tests/test_rss_parser.py new file mode 100644 index 0000000..d499673 --- /dev/null +++ b/final_task/tests/test_rss_parser.py @@ -0,0 +1,27 @@ +import sys +sys.path.insert(1, 'final_task/rss_reader') +from rss_parser import * +from database_functions import * +import unittest +from io import StringIO +from unittest.mock import patch + +class TestParseFunctions(unittest.TestCase): + def setUp(self): + + self.dict_of_args = { + "url": "https://news.yahoo.com/rss/", + "lim": 1, + "json": False, + "date": "20191122", + "path": r"C:\Users\Lenovo\PycharmProjects\final_task\FinalTaskRssParser\final_task\tests", + "html": True, + "pdf": False} + + def test_read_news(self): + with patch('sys.stdout', new=StringIO()) as fake_out_put: + print_cache(self.dict_of_args) + self.assertEqual(fake_out_put.getvalue().strip(), 'No results\nTry to enter another date or url') + +if __name__ == '__main__': + unittest.main() \ No newline at end of file