diff --git a/Makefile b/Makefile index f7b479c..32d9686 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,6 @@ # обновление сборки Docker-контейнера build: docker compose build - # генерация документации docs-html: docker compose run --workdir /docs app /bin/bash -c "make html" diff --git a/README.md b/README.md index 33c0486..cfee11a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ Console application for creating a bibliography list. The application allows you to automate the process of generating a bibliography list according to the specified citation standard. Supported citation styles: -- ГОСТ Р 7.0.5-2008 +- ГОСТ Р 7.0.5-2008 +- Modern Language Association 9th edition ## Installation diff --git a/docs/source/index.rst b/docs/source/index.rst index f552b0d..c6bb77c 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -7,6 +7,7 @@ Поддерживаемые стили цитирования: - ГОСТ Р 7.0.5-2008 + - Modern Language Association 9th edition Установка ========= @@ -85,8 +86,8 @@ docker compose run app python main.py - Запустится программа. Она считает исходный файл `media/input.xlsx`, выполнит обработку данных и сгенерирует выходной файл – `media/output.docx`. - Откройте этот файл и проверьте результат работы приложения. + Запустится программа. Она считает исходный файл `media/input.xlsx`, выполнит обработку данных и сгенерирует выходные файлы – `media/output_gost.docx` и media/output_mla.docx`. + Откройте эти файлы и проверьте результат работы приложения. .. note:: diff --git a/media/template.xlsx b/media/template.xlsx index 2bfee63..6b45ec1 100644 Binary files a/media/template.xlsx and b/media/template.xlsx differ diff --git a/src/formatters/base.py b/src/formatters/base.py index 2dc3ca3..7778666 100644 --- a/src/formatters/base.py +++ b/src/formatters/base.py @@ -2,8 +2,8 @@ Базовые функции форматирования списка источников """ -from formatters.styles.base import BaseCitationStyle -from logger import get_logger +from src.formatters.styles.base import BaseCitationStyle +from src.logger import get_logger logger = get_logger(__name__) diff --git a/src/formatters/models.py b/src/formatters/models.py index c9236ca..c77a072 100644 --- a/src/formatters/models.py +++ b/src/formatters/models.py @@ -54,7 +54,6 @@ class InternetResourceModel(BaseModel): class ArticlesCollectionModel(BaseModel): - """ Модель сборника статей: @@ -78,3 +77,105 @@ class ArticlesCollectionModel(BaseModel): publishing_house: str year: int = Field(..., gt=0) pages: str + + +class ArticleMagazineModel(BaseModel): + """ + Модель статьи из журнала: + + .. code-block:: + + ArticleMagazineModel( + authors="Иванов И.М., Петров С.Н.", + article_title="Наука как искусство", + magazine_title="Сборник научных трудов, + year=2020, + number=10, + pages="25-30", + ) + """ + + authors: str + article_title: str + magazine_title: str + year: int = Field(..., gt=0) + number: int = Field(..., gt=0) + pages: str + + +class LawModel(BaseModel): + """ + Модель закона, нормативного актa и т.п.: + + .. code-block:: + + LawModel( + type="Конституция Российской Федерации", + law_title="Наука как искусство", + passing_date="01.01.2000", + number="1234-56", + source="Парламентская газета", + source_year=2020, + source_number=5, + article_number=15, + start_date="11.09.2002", + ) + """ + + type: str + law_title: str + passing_date: str + number: str + source: str + source_year: int = Field(..., gt=0) + source_number: int = Field(..., gt=0) + article_number: int = Field(..., gt=0) + start_date: str + + +class MLABookModel(BaseModel): + """ + Модель книги MLA: + + .. code-block:: + + MLABookModel( + author_last_name="Smith", + author_first_name="Thomas", + title="The Citation Manual for Students: A Quick Guide", + edition="2nd", + publisher="Wiley", + year=2020, + ) + """ + + author_last_name: str + author_first_name: str + title: str + edition: Optional[str] + publisher: str + year: int = Field(..., gt=0) + + +class MLAInternetResourceModel(BaseModel): + """ + Модель интернет ресурса MLA: + + .. code-block:: + + MLAInternetResourceModel( + author_last_name="Smith", + author_first_name="Thomas", + title="Whales Likely Impacted by Great Pacific Garbage Patch." + website="The Ocean Cleanup" + publication_date="10 Apr. 2019", + url="www.theoceancleanup.com/updates/whales-likely-impacted-by-great-pacific-garbage-patch", + ) + """ + + author_last_name: str + author_first_name: str + title: str + website: str + publication_date: str + url: str diff --git a/src/formatters/styles/gost.py b/src/formatters/styles/gost.py index b237f8a..ecc2a53 100644 --- a/src/formatters/styles/gost.py +++ b/src/formatters/styles/gost.py @@ -5,10 +5,10 @@ from pydantic import BaseModel -from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel -from formatters.styles.base import BaseCitationStyle -from logger import get_logger - +from src.formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel, ArticleMagazineModel, \ + LawModel +from src.formatters.styles.base import BaseCitationStyle +from src.logger import get_logger logger = get_logger(__name__) @@ -27,7 +27,6 @@ def template(self) -> Template: ) def substitute(self) -> str: - logger.info('Форматирование книги "%s" ...', self.data.title) return self.template.substitute( @@ -64,7 +63,6 @@ def template(self) -> Template: ) def substitute(self) -> str: - logger.info('Форматирование интернет-ресурса "%s" ...', self.data.article) return self.template.substitute( @@ -89,7 +87,6 @@ def template(self) -> Template: ) def substitute(self) -> str: - logger.info('Форматирование сборника статей "%s" ...', self.data.article_title) return self.template.substitute( @@ -103,6 +100,62 @@ def substitute(self) -> str: ) +class GOSTMagazineArticle(BaseCitationStyle): + """ + Форматирование для статьи из журнала. + """ + + data: ArticleMagazineModel + + @property + def template(self) -> Template: + return Template( + "$authors $article_title // $magazine_title. – $year. – №$number. – С. $pages." + ) + + def substitute(self) -> str: + logger.info('Форматирование статьи из журнала "%s" ...', self.data.article_title) + + return self.template.substitute( + authors=self.data.authors, + article_title=self.data.article_title, + magazine_title=self.data.magazine_title, + year=self.data.year, + number=self.data.number, + pages=self.data.pages, + ) + + +class GOSTLaw(BaseCitationStyle): + """ + Форматирование для закона, нормативного актa и т.п. + """ + + data: LawModel + + @property + def template(self) -> Template: + return Template( + "$type \"$law_title\" от $passing_date № $number // $source. - $source_year г. - № $source_number. - Ст. " + "$article_number с изм. и допол. в ред. от $start_date." + ) + + def substitute(self) -> str: + logger.info('Форматирование закона, нормативного актa и т.п. "%s" ...', self.data.law_title) + + return self.template.substitute( + type=self.data.type, + law_title=self.data.law_title, + passing_date=self.data.passing_date, + number=self.data.number, + source=self.data.source, + source_year=self.data.source_year, + source_number=self.data.source_number, + article_number=self.data.article_number, + start_date=self.data.start_date, + ) + + class GOSTCitationFormatter: """ Базовый класс для итогового форматирования списка источников. @@ -112,6 +165,8 @@ class GOSTCitationFormatter: BookModel.__name__: GOSTBook, InternetResourceModel.__name__: GOSTInternetResource, ArticlesCollectionModel.__name__: GOSTCollectionArticle, + ArticleMagazineModel.__name__: GOSTMagazineArticle, + LawModel.__name__: GOSTLaw, } def __init__(self, models: list[BaseModel]) -> None: diff --git a/src/formatters/styles/mla.py b/src/formatters/styles/mla.py new file mode 100644 index 0000000..2c6ba89 --- /dev/null +++ b/src/formatters/styles/mla.py @@ -0,0 +1,106 @@ +""" +Стиль цитирования по Modern Language Association 9th edition. +""" +from string import Template + +from pydantic import BaseModel + +from src.formatters.models import MLABookModel, MLAInternetResourceModel +from src.formatters.styles.base import BaseCitationStyle +from src.logger import get_logger + +logger = get_logger(__name__) + + +class MLABook(BaseCitationStyle): + """ + Форматирование для книг. + """ + + data: MLABookModel + + @property + def template(self) -> Template: + return Template( + "$author_last_name, $author_first_name. $title. $edition$publisher, $year." + ) + + def substitute(self) -> str: + logger.info('Форматирование книги MLA "%s" ...', self.data.title) + + return self.template.substitute( + author_last_name=self.data.author_last_name, + author_first_name=self.data.author_first_name, + title=self.data.title, + edition=self.get_edition(), + publisher=self.data.publisher, + year=self.data.year, + ) + + def get_edition(self) -> str: + """ + Получение отформатированной информации об издании. + + :return: Информация об издании. + """ + + return f"{self.data.edition} ed. " if self.data.edition else "" + + +class MLAInternetResource(BaseCitationStyle): + """ + Форматирование для интернет-ресурсов MLA. + """ + + data: MLAInternetResourceModel + + @property + def template(self) -> Template: + return Template( + "$author_last_name, $author_first_name. “$title” $website, $publication_date, $url." + ) + + def substitute(self) -> str: + logger.info('Форматирование интернет-ресурса MLA "%s" ...', self.data.title) + + return self.template.substitute( + author_last_name=self.data.author_last_name, + author_first_name=self.data.author_first_name, + title=self.data.title, + website=self.data.website, + publication_date=self.data.publication_date, + url=self.data.url, + ) + + +class MLACitationFormatter: + """ + Базовый класс для итогового форматирования списка источников. + """ + + formatters_map = { + MLABookModel.__name__: MLABook, + MLAInternetResourceModel.__name__: MLAInternetResource + } + + def __init__(self, models: list[BaseModel]) -> None: + """ + Конструктор. + + :param models: Список объектов для форматирования + """ + + formatted_items = [] + for model in models: + formatted_items.append(self.formatters_map.get(type(model).__name__)(model)) # type: ignore + + self.formatted_items = formatted_items + + def format(self) -> list[BaseCitationStyle]: + """ + Форматирование списка источников. + + :return: + """ + + return sorted(self.formatted_items, key=lambda item: item.formatted) diff --git a/src/logger.py b/src/logger.py index dcd14b6..8af826c 100644 --- a/src/logger.py +++ b/src/logger.py @@ -3,7 +3,7 @@ """ import logging -from settings import LOGGING_FORMAT, LOGGING_LEVEL, LOGGING_PATH +from src.settings import LOGGING_FORMAT, LOGGING_LEVEL, LOGGING_PATH def get_logger( diff --git a/src/main.py b/src/main.py index 7a9fa8e..6bd2856 100644 --- a/src/main.py +++ b/src/main.py @@ -5,11 +5,13 @@ import click -from formatters.styles.gost import GOSTCitationFormatter +from src.formatters.styles.mla import MLACitationFormatter +from src.formatters.styles.gost import GOSTCitationFormatter + from logger import get_logger -from readers.reader import SourcesReader +from readers.reader import SourcesReader, MLASourcesReader from renderer import Renderer -from settings import INPUT_FILE_PATH, OUTPUT_FILE_PATH +from settings import INPUT_FILE_PATH, OUTPUT_FILE_PATH, OUTPUT_MLA_FILE_PATH logger = get_logger(__name__) @@ -53,7 +55,7 @@ class CitationEnum(Enum): show_default=True, help="Путь к выходному файлу", ) -def process_input( +def process_input_gost( citation: str = CitationEnum.GOST.name, path_input: str = INPUT_FILE_PATH, path_output: str = OUTPUT_FILE_PATH, @@ -87,10 +89,45 @@ def process_input( logger.info("Команда успешно завершена.") +def process_input_mla( + citation: str = CitationEnum.MLA.name, + path_input: str = INPUT_FILE_PATH, + path_output: str = OUTPUT_MLA_FILE_PATH, +) -> None: + """ + Генерация файла Word с оформленным библиографическим списком. + + :param str citation: Стиль цитирования + :param str path_input: Путь к входному файлу + :param str path_output: Путь к выходному файлу + """ + + logger.info( + """Обработка команды с параметрами: + - Стиль цитирования: %s. + - Путь к входному файлу: %s. + - Путь к выходному файлу: %s.""", + citation, + path_input, + path_output, + ) + + models = MLASourcesReader(path_input).read() + formatted_models = tuple( + str(item) for item in MLACitationFormatter(models).format() + ) + + logger.info("Генерация выходного файла ...") + Renderer(formatted_models).render(path_output) + + logger.info("Команда успешно завершена.") + + if __name__ == "__main__": try: # запуск обработки входного файла - process_input() + process_input_mla() + process_input_gost() except Exception as ex: logger.error("При обработке команды возникла ошибка: %s", ex) raise diff --git a/src/readers/base.py b/src/readers/base.py index 47485d3..70a547f 100644 --- a/src/readers/base.py +++ b/src/readers/base.py @@ -9,7 +9,7 @@ from openpyxl.workbook import Workbook from pydantic import BaseModel -from logger import get_logger +from src.logger import get_logger logger = get_logger(__name__) diff --git a/src/readers/reader.py b/src/readers/reader.py index 9007a80..0272a82 100644 --- a/src/readers/reader.py +++ b/src/readers/reader.py @@ -7,10 +7,10 @@ import openpyxl from openpyxl.workbook import Workbook -from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel -from logger import get_logger -from readers.base import BaseReader - +from src.formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel, ArticleMagazineModel, \ + LawModel, MLABookModel, MLAInternetResourceModel +from src.logger import get_logger +from src.readers.base import BaseReader logger = get_logger(__name__) @@ -90,6 +90,109 @@ def attributes(self) -> dict: } +class ArticleMagazineReader(BaseReader): + """ + Чтение модели сборника из журнала. + """ + + @property + def model(self) -> Type[ArticleMagazineModel]: + return ArticleMagazineModel + + @property + def sheet(self) -> str: + return "Статья из журнала" + + @property + def attributes(self) -> dict: + return { + "authors": {0: str}, + "article_title": {1: str}, + "magazine_title": {2: str}, + "year": {3: int}, + "number": {4: int}, + "pages": {5: str}, + } + + +class LawReader(BaseReader): + """ + Чтение модели закона, нормативного актa и т.п.. + """ + + @property + def model(self) -> Type[LawModel]: + return LawModel + + @property + def sheet(self) -> str: + return " Закон, нормативный акт и т.п." + + @property + def attributes(self) -> dict: + return { + "type": {0: str}, + "law_title": {1: str}, + "passing_date": {2: date}, + "number": {3: str}, + "source": {4: str}, + "source_year": {5: int}, + "source_number": {6: int}, + "article_number": {7: int}, + "start_date": {8: date}, + } + + +class MLABookReader(BaseReader): + """ + Чтение модели книги MLA. + """ + + @property + def model(self) -> Type[MLABookModel]: + return MLABookModel + + @property + def sheet(self) -> str: + return "Книга MLA" + + @property + def attributes(self) -> dict: + return { + "author_last_name": {0: str}, + "author_first_name": {1: str}, + "title": {2: str}, + "edition": {3: str}, + "publisher": {4: str}, + "year": {5: int}, + } + + +class MLAInternetResourceReader(BaseReader): + """ + Чтение модели интернес-ресурса MLA. + """ + + @property + def model(self) -> Type[MLAInternetResourceModel]: + return MLAInternetResourceModel + + @property + def sheet(self) -> str: + return "Интернет-ресурс MLA" + + @property + def attributes(self) -> dict: + return { + "author_last_name": {0: str}, + "author_first_name": {1: str}, + "title": {2: str}, + "website": {3: str}, + "publication_date": {4: str}, + "url": {5: str}, + } + + class SourcesReader: """ Чтение из источника данных. @@ -100,6 +203,8 @@ class SourcesReader: BookReader, InternetResourceReader, ArticlesCollectionReader, + ArticleMagazineReader, + LawReader, ] def __init__(self, path: str) -> None: @@ -125,3 +230,40 @@ def read(self) -> list: items.extend(reader(self.workbook).read()) # type: ignore return items + + +class MLASourcesReader: + """ + Чтение из источника данных. + """ + + # зарегистрированные читатели + readers = [ + MLABookReader, + MLAInternetResourceReader, + ] + + def __init__(self, path: str) -> None: + """ + Конструктор. + + :param path: Путь к исходному файлу для чтения. + """ + + logger.info("Загрузка рабочей книги ...") + self.workbook: Workbook = openpyxl.load_workbook(path) + + def read(self) -> list: + """ + Чтение исходного файла. + + :return: Список прочитанных моделей (строк). + """ + + items = [] + for reader in self.readers: + logger.info("Чтение %s ...", reader) + items.extend(reader(self.workbook).read()) # type: ignore + + return items + diff --git a/src/settings.py b/src/settings.py index 62d2037..b40e7e3 100644 --- a/src/settings.py +++ b/src/settings.py @@ -9,8 +9,9 @@ # путь к входному файлу INPUT_FILE_PATH: str = os.getenv("INPUT_FILE_PATH", "../media/input.xlsx") -# путь к выходному файлу +# путь к выходным файлам OUTPUT_FILE_PATH: str = os.getenv("OUTPUT_FILE_PATH", "../media/output.docx") +OUTPUT_MLA_FILE_PATH: str = os.getenv("OUTPUT_MLA_FILE_PATH", "../media/output_mla.docx") # путь к директории для логирования LOGGING_PATH: str = os.getenv("LOGGING_PATH", "../logs") diff --git a/src/tests/formatters/test_gost.py b/src/tests/formatters/test_gost.py index c93e1e7..3b4531c 100644 --- a/src/tests/formatters/test_gost.py +++ b/src/tests/formatters/test_gost.py @@ -2,9 +2,11 @@ Тестирование функций оформления списка источников по ГОСТ Р 7.0.5-2008. """ -from formatters.base import BaseCitationFormatter -from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel -from formatters.styles.gost import GOSTBook, GOSTInternetResource, GOSTCollectionArticle +from src.formatters.base import BaseCitationFormatter +from src.formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel, ArticleMagazineModel, \ + LawModel +from src.formatters.styles.gost import GOSTBook, GOSTInternetResource, GOSTCollectionArticle, GOSTMagazineArticle, \ + GOSTLaw class TestGOST: @@ -61,6 +63,40 @@ def test_articles_collection( == "Иванов И.М., Петров С.Н. Наука как искусство // Сборник научных трудов. – СПб.: АСТ, 2020. – С. 25-30." ) + def test_article_magazine( + self, article_magazine_model_fixture: ArticleMagazineModel + ) -> None: + """ + Тестирование форматирования статьи из журнала. + + :param ArticleMagazineModel article_magazine_model_fixture: Фикстура модели статьи из журнала + :return: + """ + + model = GOSTMagazineArticle(article_magazine_model_fixture) + + assert ( + model.formatted + == "Иванов И.М., Петров С.Н. Наука как искусство // Образование и наука. – 2020. – №10. – С. 25-30." + ) + + def test_law( + self, law_model_fixture: LawModel + ) -> None: + """ + Тестирование форматирования закона и т. д. + + :param LawModel law_model_fixture: Фикстура модели закона и т. д. + :return: + """ + + model = GOSTLaw(law_model_fixture) + + assert ( + model.formatted + == "Конституция Российской Федерации \"Наука как искусство\" от 01.01.2000 № 1234-56 // Парламентская газета. - 2020 г. - № 5. - Ст. 15 с изм. и допол. в ред. от 11.09.2002." + ) + def test_citation_formatter( self, book_model_fixture: BookModel, diff --git a/src/tests/formatters/test_mla.py b/src/tests/formatters/test_mla.py new file mode 100644 index 0000000..34cfac8 --- /dev/null +++ b/src/tests/formatters/test_mla.py @@ -0,0 +1,69 @@ +""" +Тестирование функций оформления списка источников по Modern Language Association 9th edition. +""" + +from src.formatters.base import BaseCitationFormatter +from src.formatters.models import MLABookModel, MLAInternetResourceModel +from src.formatters.styles.mla import MLABook, MLAInternetResource + + +class TestMLA: + """ + Тестирование оформления списка источников согласно Modern Language Association 9th edition. + """ + + def test_mla_book(self, book_model_fixture: MLABookModel) -> None: + """ + Тестирование форматирования книги. + + :param BookModel book_model_fixture: Фикстура модели книги MLA + :return: + """ + + model = MLABook(book_model_fixture) + + assert ( + model.formatted + == "Smith, Thomas. The Citation Manual for Students: A Quick Guide. 2nd ed. Wiley, 2020." + ) + + def test_mla_internet_resource( + self, internet_resource_model_fixture: MLAInternetResourceModel + ) -> None: + """ + Тестирование форматирования интернет-ресурса. + + :param InternetResourceModel internet_resource_model_fixture: Фикстура модели интернет-ресурса + :return: + """ + + model = MLAInternetResource(internet_resource_model_fixture) + + assert ( + model.formatted + == "Slat, Boyan. “Whales Likely Impacted by Great Pacific Garbage Patch.” The Ocean Cleanup, " + "10 Apr. 2019, www.theoceancleanup.com/updates/whales-likely-impacted-by-great-pacific-garbage-patch." + ) + + def test_citation_formatter( + self, + book_model_fixture: MLABookModel, + internet_resource_model_fixture: MLAInternetResourceModel, + ) -> None: + """ + Тестирование функции итогового форматирования списка источников. + + :param BookModel book_model_fixture: Фикстура модели книги + :param InternetResourceModel internet_resource_model_fixture: Фикстура модели интернет-ресурса + :return: + """ + + models = [ + MLABook(book_model_fixture), + MLAInternetResource(internet_resource_model_fixture), + ] + result = BaseCitationFormatter(models).format() + + # тестирование сортировки списка источников + assert result[0] == models[0] + assert result[1] == models[1] diff --git a/src/tests/readers/test_readers.py b/src/tests/readers/test_readers.py index 67d863b..2e10e77 100644 --- a/src/tests/readers/test_readers.py +++ b/src/tests/readers/test_readers.py @@ -5,14 +5,19 @@ import pytest -from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel -from readers.reader import ( +from src.formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel, ArticleMagazineModel, \ + LawModel, MLABookModel, MLAInternetResourceModel +from src.readers.reader import ( BookReader, SourcesReader, InternetResourceReader, ArticlesCollectionReader, + ArticleMagazineReader, + LawReader, + MLABookReader, + MLAInternetResourceReader ) -from settings import TEMPLATE_FILE_PATH +from src.settings import TEMPLATE_FILE_PATH class TestReaders: @@ -104,6 +109,109 @@ def test_articles_collection(self, workbook: Any) -> None: # проверка общего количества атрибутов assert len(model_type.schema().get("properties", {}).keys()) == 7 + def test_article_magazine(self, workbook: Any) -> None: + """ + Тестирование чтения статьи из журнала. + + :param workbook: Объект тестовой рабочей книги. + """ + + models = ArticleMagazineReader(workbook).read() + + assert len(models) == 1 + model = models[0] + + model_type = ArticleMagazineModel + + assert isinstance(model, model_type) + assert model.authors == "Иванов И.М., Петров С.Н." + assert model.article_title == "Наука как искусство" + assert model.magazine_title == "Сборник научных трудов" + assert model.year == 2020 + assert model.number == 10 + assert model.pages == "25-30" + + # проверка общего количества атрибутов + assert len(model_type.schema().get("properties", {}).keys()) == 6 + + def test_law(self, workbook: Any) -> None: + """ + Тестирование чтения закона т. д. + + :param workbook: Объект тестовой рабочей книги. + """ + + models = LawReader(workbook).read() + + assert len(models) == 1 + model = models[0] + + model_type = LawModel + + assert isinstance(model, model_type) + assert model.type == "Конституция Российской Федерации" + assert model.law_title == "Наука как искусство" + assert model.passing_date == "01.01.2000" + assert model.number == "1234-56" + assert model.source == "Парламентская газета" + assert model.source_year == 2020 + assert model.source_number == 5 + assert model.article_number == 15 + assert model.start_date == "11.09.2002" + + # проверка общего количества атрибутов + assert len(model_type.schema().get("properties", {}).keys()) == 9 + + def test_mla_book(self, workbook: Any) -> None: + """ + Тестирование чтения иностранной криги. + + :param workbook: Объект тестовой рабочей книги. + """ + + models = MLABookReader(workbook).read() + + assert len(models) == 2 + model = models[0] + + model_type = MLABookModel + + assert isinstance(model, model_type) + assert model.author_last_name == "Smith" + assert model.author_first_name == "Thomas" + assert model.title == "The Citation Manual for Students: A Quick Guide" + assert model.edition == "2nd" + assert model.publisher == "Wiley" + assert model.year == 2020 + + # проверка общего количества атрибутов + assert len(model_type.schema().get("properties", {}).keys()) == 6 + + def test_mla_internet_resource(self, workbook: Any) -> None: + """ + Тестирование чтения иностранной криги. + + :param workbook: Объект тестовой рабочей книги. + """ + + models = MLAInternetResourceReader(workbook).read() + + assert len(models) == 1 + model = models[0] + + model_type = MLAInternetResourceModel + + assert isinstance(model, model_type) + assert model.author_last_name == "Slat" + assert model.author_first_name == "Boyan" + assert model.title == "Whales Likely Impacted by Great Pacific Garbage Patch." + assert model.website == "The Ocean Cleanup" + assert model.publication_date == "10 Apr. 2019" + assert model.url == "www.theoceancleanup.com/updates/whales-likely-impacted-by-great-pacific-garbage-patch" + + # проверка общего количества атрибутов + assert len(model_type.schema().get("properties", {}).keys()) == 6 + def test_sources_reader(self) -> None: """ Тестирование функции чтения всех моделей из источника. @@ -111,7 +219,7 @@ def test_sources_reader(self) -> None: models = SourcesReader(TEMPLATE_FILE_PATH).read() # проверка общего считанного количества моделей - assert len(models) == 8 + assert len(models) == 10 # проверка наличия всех ожидаемых типов моделей среди типов считанных моделей model_types = {model.__class__.__name__ for model in models} @@ -119,4 +227,8 @@ def test_sources_reader(self) -> None: BookModel.__name__, InternetResourceModel.__name__, ArticlesCollectionModel.__name__, + ArticleMagazineModel.__name__, + LawModel.__name__, + MLABookModel.__name__, + MLAInternetResourceModel.__name__, } diff --git a/src/tests/test_renderer.py b/src/tests/test_renderer.py index d2bef8f..a77b97f 100644 --- a/src/tests/test_renderer.py +++ b/src/tests/test_renderer.py @@ -5,7 +5,7 @@ import pytest -from renderer import Renderer +from src.renderer import Renderer class TestRenderer: