From 3f711c79d56ef23b106475539962346946d11f7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B0=D0=BB=D0=B5=D1=80=D0=B8=D1=8F=20=D0=A1=D1=83?= =?UTF-8?q?=D1=85=D0=B8=D0=BD=D0=B8=D0=BD=D0=B0?= Date: Wed, 28 Feb 2024 09:44:54 +0500 Subject: [PATCH 1/5] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=82=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B5=D1=89=D0=B5?= =?UTF-8?q?=20=D0=B4=D0=B2=D1=83=D1=85=20=D0=B2=D0=B8=D0=B4=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=B8=D1=81=D1=82=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=20?= =?UTF-8?q?(=D0=94=D0=B8=D1=81=D1=81=D0=B5=D1=80=D1=82=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8F,=20=D0=B0=D0=B2=D1=82=D0=BE=D1=80=D0=B5=D1=84=D0=B5?= =?UTF-8?q?=D1=80=D0=B0=D1=82)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.sample | 14 --------- .gitignore | 1 + src/formatters/models.py | 53 +++++++++++++++++++++++++++++++++ src/formatters/styles/gost.py | 51 ++++++++++++++++++++++++++++++- src/readers/reader.py | 56 ++++++++++++++++++++++++++++++++++- 5 files changed, 159 insertions(+), 16 deletions(-) delete mode 100644 .env.sample diff --git a/.env.sample b/.env.sample deleted file mode 100644 index 3508a22..0000000 --- a/.env.sample +++ /dev/null @@ -1,14 +0,0 @@ -# путь к файлу шаблона для создания входного файла -TEMPLATE_FILE_PATH=/media/template.xlsx - -# путь к входному файлу -INPUT_FILE_PATH=/media/input.xlsx -# путь к выходному файлу -OUTPUT_FILE_PATH=/media/output.docx - -# путь к директории для логирования -LOGGING_PATH=/logs -# формат для записей логов -LOGGING_FORMAT="%(name)s %(asctime)s %(levelname)s %(message)s" -# уровень логирования -LOGGING_LEVEL=INFO diff --git a/.gitignore b/.gitignore index 5e9eef2..3743051 100644 --- a/.gitignore +++ b/.gitignore @@ -130,3 +130,4 @@ dmypy.json # IDE .idea +/.vs diff --git a/src/formatters/models.py b/src/formatters/models.py index c9236ca..5177dad 100644 --- a/src/formatters/models.py +++ b/src/formatters/models.py @@ -78,3 +78,56 @@ class ArticlesCollectionModel(BaseModel): publishing_house: str year: int = Field(..., gt=0) pages: str + +class DissertationModel(BaseModel): + """ + Модель дисссертации: + + .. code-block:: + + DissertationModel( + author="Иванов И.М.", + title="Наука как искусство", + degree="д-р. / канд.", + branch="экон.", + specialty_code="01.01.01", + city="СПб.", + year=2020, + pages=199, + ) + """ + author: str = Field(..., description="Фамилия и инициалы автора") + title: str = Field(..., description="Название диссертации") + degree: str = Field(..., description="Ученая степень (д-р. / канд.)") + branch: str = Field(..., description="Отрасль наук (сокращённо)") + specialty_code: str = Field(..., description="Код специальности") + city: str = Field(..., description="Город издательства") + year: int = Field(..., gt=0, description="Год защиты") + pages: int = Field(..., gt=0, description="Количество страниц") + +class AbstractModel(BaseModel): + """ + Модель автореферата: + + .. code-block:: + + AbstractModel( + author="Иванов И.М.", + title="Наука как искусство", + degree="д-р. / канд.", + branch="экон.", + specialty_code="01.01.01", + city="СПб.", + year=2020, + pages=199, + ) + """ + + author: str = Field(..., description="Фамилия и инициалы автора") + title: str = Field(..., description="Название диссертации") + degree: str = Field(..., description="Ученая степень (д-р. / канд.)") + branch: str = Field(..., description="Отрасль наук (сокращённо)") + specialty_code: str = Field(..., description="Код специальности") + city: str = Field(..., description="Город издательства") + year: int = Field(..., gt=0, description="Год издания") + pages: int = Field(..., gt=0, description="Количество страниц") \ No newline at end of file diff --git a/src/formatters/styles/gost.py b/src/formatters/styles/gost.py index b237f8a..c8ad67e 100644 --- a/src/formatters/styles/gost.py +++ b/src/formatters/styles/gost.py @@ -5,7 +5,7 @@ from pydantic import BaseModel -from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel +from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel, DissertationModel, AbstractModel from formatters.styles.base import BaseCitationStyle from logger import get_logger @@ -102,6 +102,53 @@ def substitute(self) -> str: pages=self.data.pages, ) +class GOSTDissertation(BaseCitationStyle): + """ + Форматирование для диссертаций. + """ + data: DissertationModel + + @property + def template(self) -> Template: + return Template( + "$author. $title [$degree] : $degree дис. : $branch, $specialty_code / $city, $year. - $pages с." + ) + + def substitute(self) -> str: + return self.template.substitute( + author=self.data.author, + title=self.data.title, + degree=self.data.degree, + branch=self.data.branch, + specialty_code=self.data.specialty_code, + city=self.data.city, + year=self.data.year, + pages=self.data.pages, + ) +class GOSTAbstract(BaseCitationStyle): + """ + Форматирование для автореферата. + """ + + data: AbstractModel + + @property + def template(self) -> Template: + return Template( + "$author. $title [$degree] : $branch, $specialty_code / $city, $year. - $pages с." + ) + + def substitute(self) -> str: + return self.template.substitute( + author=self.data.author, + title=self.data.title, + degree=self.data.degree, + branch=self.data.branch, + specialty_code=self.data.specialty_code, + city=self.data.city, + year=self.data.year, + pages=self.data.pages, + ) class GOSTCitationFormatter: """ @@ -112,6 +159,8 @@ class GOSTCitationFormatter: BookModel.__name__: GOSTBook, InternetResourceModel.__name__: GOSTInternetResource, ArticlesCollectionModel.__name__: GOSTCollectionArticle, + DissertationModel.__name__: GOSTDissertation, + AbstractModel.__name__: GOSTAbstract, } def __init__(self, models: list[BaseModel]) -> None: diff --git a/src/readers/reader.py b/src/readers/reader.py index 9007a80..64d0dc5 100644 --- a/src/readers/reader.py +++ b/src/readers/reader.py @@ -7,7 +7,7 @@ import openpyxl from openpyxl.workbook import Workbook -from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel +from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel, DissertationModel, AbstractModel from logger import get_logger from readers.base import BaseReader @@ -90,6 +90,58 @@ def attributes(self) -> dict: } +class DissertationReader(BaseReader): + """ + Чтение модели диссертации. + """ + + @property + def model(self) -> Type[DissertationModel]: + return DissertationModel + + @property + def sheet(self) -> str: + return "Диссертация" + + @property + def attributes(self) -> dict: + return { + "author": {0: str}, + "title": {1: str}, + "degree": {2: str}, + "branch": {3: str}, + "specialty_code": {4: str}, + "city": {5: str}, + "year": {6: int}, + "pages": {7: str}, + } + +class AbstractReader(BaseReader): + """ + Чтение модели автореферата. + """ + + @property + def model(self) -> Type[AbstractModel]: + return AbstractModel + + @property + def sheet(self) -> str: + return "Автореферат" + + @property + def attributes(self) -> dict: + return { + "author": {0: str}, + "title": {1: str}, + "degree": {2: str}, + "branch": {3: str}, + "specialty_code": {4: str}, + "city": {5: str}, + "year": {6: int}, + "pages": {7: str}, + } + class SourcesReader: """ Чтение из источника данных. @@ -100,6 +152,8 @@ class SourcesReader: BookReader, InternetResourceReader, ArticlesCollectionReader, + DissertationReader, + AbstractReader ] def __init__(self, path: str) -> None: From d9f52f479ca20ed74cf013c41669b68c936174de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B0=D0=BB=D0=B5=D1=80=D0=B8=D1=8F=20=D0=A1=D1=83?= =?UTF-8?q?=D1=85=D0=B8=D0=BD=D0=B8=D0=BD=D0=B0?= Date: Wed, 28 Feb 2024 14:40:47 +0500 Subject: [PATCH 2/5] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=BE=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0=20=D0=B8?= =?UTF-8?q?=D1=81=D1=82=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=20=D0=BF?= =?UTF-8?q?=D0=BE=20=D1=81=D1=82=D0=B0=D0=BD=D0=B4=D0=B0=D1=80=D1=82=D0=B0?= =?UTF-8?q?=D0=BC=20APA=20(=D0=B5=D1=89=D0=B5=20=D0=B2=D0=B5=D1=80=D0=BD?= =?UTF-8?q?=D1=83=D0=BB=D0=B0=20=D1=84=D0=B0=D0=B9=D0=BB=20.env.sample,=20?= =?UTF-8?q?=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B9=20=D1=81=D0=BB=D1=83?= =?UTF-8?q?=D1=87=D0=B0=D0=B9=D0=BD=D0=BE=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B8?= =?UTF-8?q?=D0=BB=D0=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.sample | 14 ++ src/formatters/styles/apa.py | 241 +++++++++++++++++++++++++++++++++++ src/main.py | 17 ++- 3 files changed, 268 insertions(+), 4 deletions(-) create mode 100644 .env.sample create mode 100644 src/formatters/styles/apa.py diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..3508a22 --- /dev/null +++ b/.env.sample @@ -0,0 +1,14 @@ +# путь к файлу шаблона для создания входного файла +TEMPLATE_FILE_PATH=/media/template.xlsx + +# путь к входному файлу +INPUT_FILE_PATH=/media/input.xlsx +# путь к выходному файлу +OUTPUT_FILE_PATH=/media/output.docx + +# путь к директории для логирования +LOGGING_PATH=/logs +# формат для записей логов +LOGGING_FORMAT="%(name)s %(asctime)s %(levelname)s %(message)s" +# уровень логирования +LOGGING_LEVEL=INFO diff --git a/src/formatters/styles/apa.py b/src/formatters/styles/apa.py new file mode 100644 index 0000000..c884118 --- /dev/null +++ b/src/formatters/styles/apa.py @@ -0,0 +1,241 @@ +""" Стиль цитирования по APA. """ +from string import Template + +from pydantic import BaseModel + +from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel, DissertationModel, AbstractModel +from formatters.styles.base import BaseCitationStyle +from logger import get_logger + + +logger = get_logger(__name__) + +class APABookFormatter(BaseCitationStyle): + """ + Форматирование для книг в стиле APA. + """ + + data: BookModel + + @property + def template(self) -> Template: + return Template( + "$authors ($year). $title. $edition. $city: $publishing_house." + ) + + def substitute(self) -> str: + """ + Замена переменных в шаблоне источника. + + :return: Отформатированная строка источника. + """ + + logger.info('Форматирование книги "%s" в стиле APA...', self.data.title) + + return self.template.substitute( + authors=self.get_authors(), + year=self.data.year, + title=self.data.title, + edition=self.get_edition(), + city=self.data.city, + publishing_house=self.data.publishing_house, + ) + + def get_authors(self) -> str: + """ + Получение списка авторов в формате APA. + + :return: Отформатированный список авторов. + """ + authors = self.data.authors.split(", ") # Предполагая, что имена авторов разделены запятой + formatted_authors = [] + for author in authors: + # Разбиваем полное имя автора на фамилию и инициалы + author_parts = author.split(" ") + # Если есть хотя бы фамилия и одна инициала + if len(author_parts) >= 2: + # Форматируем фамилию, инициалы и точку + formatted_author = author_parts[0] + ", " + " ".join([initial[0] + "." for initial in author_parts[1:]]) + formatted_authors.append(formatted_author) + else: + # В случае, если в имени только одно слово (без инициалов) + formatted_authors.append(author) + # Объединяем отформатированных авторов через запятую и пробел + return ", ".join(formatted_authors) + + def get_edition(self) -> str: + """ + Получение отформатированной информации об издании. + + :return: Информация об издании. + """ + return f"({self.data.edition} изд.)" if self.data.edition else "" + +class APAInternetResourceFormatter(BaseCitationStyle): + """ + Форматирование для интернет-ресурсов в стиле APA. + """ + + data: InternetResourceModel + + @property + def template(self) -> Template: + return Template( + "$article (б. д.). $website URL: $link (дата обращения: $access_date)." + ) + + def substitute(self) -> str: + """ + Замена переменных в шаблоне источника. + + :return: Отформатированная строка источника. + """ + + logger.info('Форматирование интернет-ресурса "%s" в стиле APA...', self.data.article) + + return self.template.substitute( + article=self.data.article, + website=self.data.website, + link=self.data.link, + access_date=self.data.access_date, + ) + +class APACollectionArticleFormatter(BaseCitationStyle): + """ + Форматирование для статьи из сборника в стиле APA. + """ + + data: ArticlesCollectionModel + + @property + def template(self) -> Template: + return Template( + "$authors ($year). $article_title. $collection_title (pp. $pages). $city: $publishing_house." + ) + + def substitute(self) -> str: + """ + Замена переменных в шаблоне источника. + + :return: Отформатированная строка источника. + """ + + logger.info('Форматирование статьи из сборника "%s" в стиле APA...', self.data.article_title) + + return self.template.substitute( + authors=self.get_authors(), + year=self.data.year, + article_title=self.data.article_title, + collection_title=self.data.collection_title, + pages=self.data.pages, + city=self.data.city, + publishing_house=self.data.publishing_house, + ) + + def get_authors(self) -> str: + """ + Получение списка авторов в формате APA. + + :return: Отформатированный список авторов. + """ + authors = self.data.authors.split(", ") # Предполагая, что имена авторов разделены запятой + formatted_authors = [] + for author in authors: + # Разбиваем полное имя автора на фамилию и инициалы + author_parts = author.split(" ") + # Если есть хотя бы фамилия и одна инициала + if len(author_parts) >= 2: + # Форматируем фамилию, инициалы и точку + formatted_author = author_parts[0] + ", " + " ".join([initial[0] + "." for initial in author_parts[1:]]) + formatted_authors.append(formatted_author) + else: + # В случае, если в имени только одно слово (без инициалов) + formatted_authors.append(author) + # Объединяем отформатированных авторов через запятую и пробел + return ", ".join(formatted_authors) + +class APADissertationFormatter(BaseCitationStyle): + """ + Форматирование для диссертаций в стиле APA. + """ + data: DissertationModel + + @property + def template(self) -> Template: + return Template( + "$author. ($year). $title ($degree) [Диссертация]. $branch, $specialty_code. $city." + ) + + def substitute(self) -> str: + return self.template.substitute( + author=self.data.author, + year=self.data.year, + title=self.data.title, + degree=self.data.degree, + branch=self.data.branch, + specialty_code=self.data.specialty_code, + city=self.data.city, + ) + +class APAAbstractFormatter(BaseCitationStyle): + """ + Форматирование для автореферата в стиле APA. + """ + + data: AbstractModel + + @property + def template(self) -> Template: + return Template( + "$author. ($year). $title ($degree) [Автореферат]. $branch, $specialty_code. $city." + ) + + def substitute(self) -> str: + return self.template.substitute( + author=self.data.author, + year=self.data.year, + title=self.data.title, + degree=self.data.degree, + branch=self.data.branch, + specialty_code=self.data.specialty_code, + city=self.data.city, + ) + + +class APACitationFormatter: + """ + Базовый класс для итогового форматирования списка источников. + """ + formatters_map = { + BookModel.__name__: APABookFormatter, + InternetResourceModel.__name__: APAInternetResourceFormatter, + ArticlesCollectionModel.__name__: APACollectionArticleFormatter, + DissertationModel.__name__: APADissertationFormatter, + AbstractModel.__name__: APAAbstractFormatter, + } + + 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/main.py b/src/main.py index 7a9fa8e..f1b0b19 100644 --- a/src/main.py +++ b/src/main.py @@ -6,6 +6,7 @@ import click from formatters.styles.gost import GOSTCitationFormatter +from formatters.styles.apa import APACitationFormatter from logger import get_logger from readers.reader import SourcesReader from renderer import Renderer @@ -21,7 +22,7 @@ class CitationEnum(Enum): """ GOST = "gost" # ГОСТ Р 7.0.5-2008 - MLA = "mla" # Modern Language Association + #MLA = "mla" # Modern Language Association APA = "apa" # American Psychological Association @@ -77,9 +78,17 @@ def process_input( ) models = SourcesReader(path_input).read() - formatted_models = tuple( - str(item) for item in GOSTCitationFormatter(models).format() - ) + if citation == CitationEnum.GOST.name: + formatted_models = tuple( + str(item) for item in GOSTCitationFormatter(models).format() + ) + elif citation == CitationEnum.APA.name: + formatted_models = tuple( + str(item) for item in APACitationFormatter(models).format() + ) + else: + logger.error("Неверно указан стиль цитирования: %s", citation_style) + return logger.info("Генерация выходного файла ...") Renderer(formatted_models).render(path_output) From 30e608ae0311ac386c3ac1803777254af4113416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B0=D0=BB=D0=B5=D1=80=D0=B8=D1=8F=20=D0=A1=D1=83?= =?UTF-8?q?=D1=85=D0=B8=D0=BD=D0=B8=D0=BD=D0=B0?= Date: Mon, 4 Mar 2024 16:55:31 +0500 Subject: [PATCH 3/5] =?UTF-8?q?=D0=A0=D0=B0=D0=B7=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=B0=D0=BD=D1=8B=20=D0=B0=D0=B2=D1=82=D0=BE=D0=BC=D0=B0?= =?UTF-8?q?=D1=82=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D0=B5=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=8B=20=D0=B8=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=B2=D0=B0=D1=8F=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BD=D1=8B=D0=B5=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/formatters/models.py | 13 +-- src/formatters/styles/apa.py | 76 ++++++++++++----- src/formatters/styles/gost.py | 23 +++-- src/main.py | 6 +- src/readers/reader.py | 16 +++- src/tests/conftest.py | 46 +++++++++- src/tests/formatters/test_apa.py | 136 ++++++++++++++++++++++++++++++ src/tests/formatters/test_gost.py | 54 +++++++++++- src/tests/readers/test_readers.py | 68 ++++++++++++++- 9 files changed, 394 insertions(+), 44 deletions(-) create mode 100644 src/tests/formatters/test_apa.py diff --git a/src/formatters/models.py b/src/formatters/models.py index 5177dad..b86fe2b 100644 --- a/src/formatters/models.py +++ b/src/formatters/models.py @@ -79,6 +79,7 @@ class ArticlesCollectionModel(BaseModel): year: int = Field(..., gt=0) pages: str + class DissertationModel(BaseModel): """ Модель дисссертации: @@ -90,21 +91,23 @@ class DissertationModel(BaseModel): title="Наука как искусство", degree="д-р. / канд.", branch="экон.", - specialty_code="01.01.01", + speciality_code="01.01.01", city="СПб.", year=2020, pages=199, ) """ + author: str = Field(..., description="Фамилия и инициалы автора") title: str = Field(..., description="Название диссертации") degree: str = Field(..., description="Ученая степень (д-р. / канд.)") branch: str = Field(..., description="Отрасль наук (сокращённо)") - specialty_code: str = Field(..., description="Код специальности") + speciality_code: str = Field(..., description="Код специальности") city: str = Field(..., description="Город издательства") year: int = Field(..., gt=0, description="Год защиты") pages: int = Field(..., gt=0, description="Количество страниц") + class AbstractModel(BaseModel): """ Модель автореферата: @@ -116,7 +119,7 @@ class AbstractModel(BaseModel): title="Наука как искусство", degree="д-р. / канд.", branch="экон.", - specialty_code="01.01.01", + speciality_code="01.01.01", city="СПб.", year=2020, pages=199, @@ -127,7 +130,7 @@ class AbstractModel(BaseModel): title: str = Field(..., description="Название диссертации") degree: str = Field(..., description="Ученая степень (д-р. / канд.)") branch: str = Field(..., description="Отрасль наук (сокращённо)") - specialty_code: str = Field(..., description="Код специальности") + speciality_code: str = Field(..., description="Код специальности") city: str = Field(..., description="Город издательства") year: int = Field(..., gt=0, description="Год издания") - pages: int = Field(..., gt=0, description="Количество страниц") \ No newline at end of file + pages: int = Field(..., gt=0, description="Количество страниц") diff --git a/src/formatters/styles/apa.py b/src/formatters/styles/apa.py index c884118..109c38f 100644 --- a/src/formatters/styles/apa.py +++ b/src/formatters/styles/apa.py @@ -3,13 +3,20 @@ from pydantic import BaseModel -from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel, DissertationModel, AbstractModel +from formatters.models import ( + BookModel, + InternetResourceModel, + ArticlesCollectionModel, + DissertationModel, + AbstractModel, +) from formatters.styles.base import BaseCitationStyle from logger import get_logger logger = get_logger(__name__) + class APABookFormatter(BaseCitationStyle): """ Форматирование для книг в стиле APA. @@ -19,9 +26,7 @@ class APABookFormatter(BaseCitationStyle): @property def template(self) -> Template: - return Template( - "$authors ($year). $title. $edition. $city: $publishing_house." - ) + return Template("$authors ($year). $title. $edition. $city: $publishing_house.") def substitute(self) -> str: """ @@ -47,7 +52,9 @@ def get_authors(self) -> str: :return: Отформатированный список авторов. """ - authors = self.data.authors.split(", ") # Предполагая, что имена авторов разделены запятой + authors = self.data.authors.split( + ", " + ) # Предполагая, что имена авторов разделены запятой formatted_authors = [] for author in authors: # Разбиваем полное имя автора на фамилию и инициалы @@ -55,13 +62,23 @@ def get_authors(self) -> str: # Если есть хотя бы фамилия и одна инициала if len(author_parts) >= 2: # Форматируем фамилию, инициалы и точку - formatted_author = author_parts[0] + ", " + " ".join([initial[0] + "." for initial in author_parts[1:]]) + formatted_author = ( + author_parts[0] + + " " + + " ".join([initial[0] + "." for initial in author_parts[1:]]) + ) formatted_authors.append(formatted_author) else: # В случае, если в имени только одно слово (без инициалов) formatted_authors.append(author) # Объединяем отформатированных авторов через запятую и пробел - return ", ".join(formatted_authors) + if len(formatted_authors) == 1: + return formatted_authors[0] + if len(formatted_authors) == 2: + return formatted_authors[0] + " & " + formatted_authors[1] + else: + # Если авторов больше двух, добавляем "и др." + return formatted_authors[0] + " et al." def get_edition(self) -> str: """ @@ -71,6 +88,7 @@ def get_edition(self) -> str: """ return f"({self.data.edition} изд.)" if self.data.edition else "" + class APAInternetResourceFormatter(BaseCitationStyle): """ Форматирование для интернет-ресурсов в стиле APA. @@ -91,7 +109,9 @@ def substitute(self) -> str: :return: Отформатированная строка источника. """ - logger.info('Форматирование интернет-ресурса "%s" в стиле APA...', self.data.article) + logger.info( + 'Форматирование интернет-ресурса "%s" в стиле APA...', self.data.article + ) return self.template.substitute( article=self.data.article, @@ -100,6 +120,7 @@ def substitute(self) -> str: access_date=self.data.access_date, ) + class APACollectionArticleFormatter(BaseCitationStyle): """ Форматирование для статьи из сборника в стиле APA. @@ -120,7 +141,10 @@ def substitute(self) -> str: :return: Отформатированная строка источника. """ - logger.info('Форматирование статьи из сборника "%s" в стиле APA...', self.data.article_title) + logger.info( + 'Форматирование статьи из сборника "%s" в стиле APA...', + self.data.article_title, + ) return self.template.substitute( authors=self.get_authors(), @@ -138,7 +162,9 @@ def get_authors(self) -> str: :return: Отформатированный список авторов. """ - authors = self.data.authors.split(", ") # Предполагая, что имена авторов разделены запятой + authors = self.data.authors.split( + ", " + ) # Предполагая, что имена авторов разделены запятой formatted_authors = [] for author in authors: # Разбиваем полное имя автора на фамилию и инициалы @@ -146,24 +172,36 @@ def get_authors(self) -> str: # Если есть хотя бы фамилия и одна инициала if len(author_parts) >= 2: # Форматируем фамилию, инициалы и точку - formatted_author = author_parts[0] + ", " + " ".join([initial[0] + "." for initial in author_parts[1:]]) + formatted_author = ( + author_parts[0] + + " " + + " ".join([initial[0] + "." for initial in author_parts[1:]]) + ) formatted_authors.append(formatted_author) else: # В случае, если в имени только одно слово (без инициалов) formatted_authors.append(author) # Объединяем отформатированных авторов через запятую и пробел - return ", ".join(formatted_authors) + if len(formatted_authors) == 1: + return formatted_authors[0] + if len(formatted_authors) == 2: + return formatted_authors[0] + " & " + formatted_authors[1] + else: + # Если авторов больше двух, добавляем "и др." + return formatted_authors[0] + " et al." + class APADissertationFormatter(BaseCitationStyle): """ Форматирование для диссертаций в стиле APA. """ + data: DissertationModel @property def template(self) -> Template: return Template( - "$author. ($year). $title ($degree) [Диссертация]. $branch, $specialty_code. $city." + "$author. ($year). $title ($degree) [Диссертация]. $branch, $speciality_code. $city" ) def substitute(self) -> str: @@ -173,10 +211,11 @@ def substitute(self) -> str: title=self.data.title, degree=self.data.degree, branch=self.data.branch, - specialty_code=self.data.specialty_code, + speciality_code=self.data.speciality_code, city=self.data.city, ) + class APAAbstractFormatter(BaseCitationStyle): """ Форматирование для автореферата в стиле APA. @@ -187,7 +226,7 @@ class APAAbstractFormatter(BaseCitationStyle): @property def template(self) -> Template: return Template( - "$author. ($year). $title ($degree) [Автореферат]. $branch, $specialty_code. $city." + "$author. ($year). $title ($degree) [Автореферат]. $branch, $speciality_code. $city" ) def substitute(self) -> str: @@ -197,7 +236,7 @@ def substitute(self) -> str: title=self.data.title, degree=self.data.degree, branch=self.data.branch, - specialty_code=self.data.specialty_code, + speciality_code=self.data.speciality_code, city=self.data.city, ) @@ -206,6 +245,7 @@ class APACitationFormatter: """ Базовый класс для итогового форматирования списка источников. """ + formatters_map = { BookModel.__name__: APABookFormatter, InternetResourceModel.__name__: APAInternetResourceFormatter, @@ -235,7 +275,3 @@ def format(self) -> list[BaseCitationStyle]: """ return sorted(self.formatted_items, key=lambda item: item.formatted) - - - - diff --git a/src/formatters/styles/gost.py b/src/formatters/styles/gost.py index c8ad67e..463cb6b 100644 --- a/src/formatters/styles/gost.py +++ b/src/formatters/styles/gost.py @@ -5,7 +5,13 @@ from pydantic import BaseModel -from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel, DissertationModel, AbstractModel +from formatters.models import ( + BookModel, + InternetResourceModel, + ArticlesCollectionModel, + DissertationModel, + AbstractModel, +) from formatters.styles.base import BaseCitationStyle from logger import get_logger @@ -102,16 +108,18 @@ def substitute(self) -> str: pages=self.data.pages, ) + class GOSTDissertation(BaseCitationStyle): """ Форматирование для диссертаций. """ + data: DissertationModel @property def template(self) -> Template: return Template( - "$author. $title [$degree] : $degree дис. : $branch, $specialty_code / $city, $year. - $pages с." + "$author. $title [$degree] дис. : $branch, $speciality_code / $city, $year. - $pages с." ) def substitute(self) -> str: @@ -120,11 +128,13 @@ def substitute(self) -> str: title=self.data.title, degree=self.data.degree, branch=self.data.branch, - specialty_code=self.data.specialty_code, + speciality_code=self.data.speciality_code, city=self.data.city, year=self.data.year, pages=self.data.pages, - ) + ) + + class GOSTAbstract(BaseCitationStyle): """ Форматирование для автореферата. @@ -135,7 +145,7 @@ class GOSTAbstract(BaseCitationStyle): @property def template(self) -> Template: return Template( - "$author. $title [$degree] : $branch, $specialty_code / $city, $year. - $pages с." + "$author. $title [$degree] : $branch, $speciality_code / $city, $year. - $pages с." ) def substitute(self) -> str: @@ -144,12 +154,13 @@ def substitute(self) -> str: title=self.data.title, degree=self.data.degree, branch=self.data.branch, - specialty_code=self.data.specialty_code, + speciality_code=self.data.speciality_code, city=self.data.city, year=self.data.year, pages=self.data.pages, ) + class GOSTCitationFormatter: """ Базовый класс для итогового форматирования списка источников. diff --git a/src/main.py b/src/main.py index f1b0b19..bb93a04 100644 --- a/src/main.py +++ b/src/main.py @@ -5,8 +5,8 @@ import click -from formatters.styles.gost import GOSTCitationFormatter from formatters.styles.apa import APACitationFormatter +from formatters.styles.gost import GOSTCitationFormatter from logger import get_logger from readers.reader import SourcesReader from renderer import Renderer @@ -22,7 +22,7 @@ class CitationEnum(Enum): """ GOST = "gost" # ГОСТ Р 7.0.5-2008 - #MLA = "mla" # Modern Language Association + # MLA = "mla" # Modern Language Association APA = "apa" # American Psychological Association @@ -87,7 +87,7 @@ def process_input( str(item) for item in APACitationFormatter(models).format() ) else: - logger.error("Неверно указан стиль цитирования: %s", citation_style) + logger.error("Неверно указан стиль цитирования: %s", citation) return logger.info("Генерация выходного файла ...") diff --git a/src/readers/reader.py b/src/readers/reader.py index 64d0dc5..2f41c2a 100644 --- a/src/readers/reader.py +++ b/src/readers/reader.py @@ -7,7 +7,13 @@ import openpyxl from openpyxl.workbook import Workbook -from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel, DissertationModel, AbstractModel +from formatters.models import ( + BookModel, + InternetResourceModel, + ArticlesCollectionModel, + DissertationModel, + AbstractModel, +) from logger import get_logger from readers.base import BaseReader @@ -110,12 +116,13 @@ def attributes(self) -> dict: "title": {1: str}, "degree": {2: str}, "branch": {3: str}, - "specialty_code": {4: str}, + "speciality_code": {4: str}, "city": {5: str}, "year": {6: int}, "pages": {7: str}, } + class AbstractReader(BaseReader): """ Чтение модели автореферата. @@ -136,12 +143,13 @@ def attributes(self) -> dict: "title": {1: str}, "degree": {2: str}, "branch": {3: str}, - "specialty_code": {4: str}, + "speciality_code": {4: str}, "city": {5: str}, "year": {6: int}, "pages": {7: str}, } + class SourcesReader: """ Чтение из источника данных. @@ -153,7 +161,7 @@ class SourcesReader: InternetResourceReader, ArticlesCollectionReader, DissertationReader, - AbstractReader + AbstractReader, ] def __init__(self, path: str) -> None: diff --git a/src/tests/conftest.py b/src/tests/conftest.py index ac5c9aa..624e20f 100644 --- a/src/tests/conftest.py +++ b/src/tests/conftest.py @@ -3,7 +3,13 @@ """ import pytest -from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel +from formatters.models import ( + BookModel, + InternetResourceModel, + ArticlesCollectionModel, + DissertationModel, + AbstractModel, +) @pytest.fixture @@ -58,3 +64,41 @@ def articles_collection_model_fixture() -> ArticlesCollectionModel: year=2020, pages="25-30", ) + + +@pytest.fixture +def dissertation_fixture() -> DissertationModel: + """ + Фикстура модели диссертации. + :return: DissertationModel + """ + + return DissertationModel( + author="Иванов И.М.", + title="Наука как искусство", + degree="д-р. / канд.", + branch="экон.", + speciality_code="01.01.01", + city="СПб.", + year=2020, + pages=199, + ) + + +@pytest.fixture +def abstract_fixture() -> AbstractModel: + """ + Фикстура модели автореферата. + :return: DissertationModel + """ + + return AbstractModel( + author="Иванов И.М.", + title="Наука как искусство", + degree="д-р. / канд.", + branch="экон.", + speciality_code="01.01.01", + city="СПб.", + year=2020, + pages=199, + ) diff --git a/src/tests/formatters/test_apa.py b/src/tests/formatters/test_apa.py new file mode 100644 index 0000000..909b910 --- /dev/null +++ b/src/tests/formatters/test_apa.py @@ -0,0 +1,136 @@ +""" +Тестирование функций оформления списка источников по APA. +""" +from formatters.base import BaseCitationFormatter +from formatters.models import ( + BookModel, + InternetResourceModel, + ArticlesCollectionModel, + DissertationModel, + AbstractModel, +) +from formatters.styles.apa import ( + APABookFormatter, + APAInternetResourceFormatter, + APACollectionArticleFormatter, + APADissertationFormatter, + APAAbstractFormatter, +) + + +class TestAPA: + """ + Тестирование оформления списка источников согласно стилю APA. + """ + + def test_book(self, book_model_fixture: BookModel) -> None: + """ + Тестирование форматирования книги в стиле APA. + + :param BookModel book_model_fixture: Фикстура модели книги + :return: + """ + + model = APABookFormatter(book_model_fixture) + + assert ( + model.formatted + == "Иванов И. & Петров С. (2020). Наука как искусство. (3-е изд.). СПб.: Просвещение." + ) + + def test_internet_resource( + self, internet_resource_model_fixture: InternetResourceModel + ) -> None: + """ + Тестирование форматирования интернет-ресурса в стиле APA. + + :param InternetResourceModel internet_resource_model_fixture: Фикстура модели интернет-ресурса + :return: + """ + + model = APAInternetResourceFormatter(internet_resource_model_fixture) + + assert ( + model.formatted + == "Наука как искусство (б. д.). Ведомости URL: https://www.vedomosti.ru (дата обращения: 01.01.2021)." + ) + + def test_articles_collection( + self, articles_collection_model_fixture: ArticlesCollectionModel + ) -> None: + """ + Тестирование форматирования сборника статей в стиле APA. + + :param ArticlesCollectionModel articles_collection_model_fixture: Фикстура модели сборника статей + :return: + """ + + model = APACollectionArticleFormatter(articles_collection_model_fixture) + + assert ( + model.formatted + == "Иванов И. & Петров С. (2020). Наука как искусство. Сборник научных трудов (pp. 25-30). СПб.: АСТ." + ) + + def test_dissertation(self, dissertation_fixture: DissertationModel) -> None: + """ + Тестирование форматирования диссертации в стиле APA. + :param DissertationModel dissertation_fixture: Фикстура модели диссертации + :return: + """ + + model = APADissertationFormatter(dissertation_fixture) + + assert ( + model.formatted + == "Иванов И.М.. (2020). Наука как искусство (д-р. / канд.) [Диссертация]. экон., 01.01.01. СПб." + ) + + def test_abstract(self, abstract_fixture: AbstractModel) -> None: + """ + Тестирование форматирования автореферата в стиле APA. + :param AbstractModel abstract_fixture: Фикстура модели автореферата + :return: + """ + + model = APAAbstractFormatter(abstract_fixture) + + assert ( + model.formatted + == "Иванов И.М.. (2020). Наука как искусство (д-р. / канд.) [Автореферат]. экон., 01.01.01. СПб." + ) + + def test_citation_formatter( + self, + book_model_fixture: BookModel, + internet_resource_model_fixture: InternetResourceModel, + articles_collection_model_fixture: ArticlesCollectionModel, + dissertation_fixture: DissertationModel, + abstract_fixture: AbstractModel, + ) -> None: + """ + Тестирование функции итогового форматирования списка источников. + + :param BookModel book_model_fixture: Фикстура модели книги + :param InternetResourceModel internet_resource_model_fixture: Фикстура модели интернет-ресурса + :param ArticlesCollectionModel articles_collection_model_fixture: Фикстура модели сборника статей + :param DissertationModel dissertation_fixture: Фикстура модели диссертации + :param AbstractModel abstract_fixture: Фикстура модели автореферата + :return: + """ + + models = [ + APABookFormatter(book_model_fixture), + APAInternetResourceFormatter(internet_resource_model_fixture), + APACollectionArticleFormatter(articles_collection_model_fixture), + APADissertationFormatter(dissertation_fixture), + APAAbstractFormatter(abstract_fixture), + ] + result = BaseCitationFormatter(models).format() + + # Тестирование сортировки списка источников + assert result[0] == models[0] + assert result[1] == models[2] + assert result[2] == models[4] + assert result[3] == models[3] + assert result[4] == models[1] diff --git a/src/tests/formatters/test_gost.py b/src/tests/formatters/test_gost.py index c93e1e7..c460ad1 100644 --- a/src/tests/formatters/test_gost.py +++ b/src/tests/formatters/test_gost.py @@ -3,8 +3,20 @@ """ from formatters.base import BaseCitationFormatter -from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel -from formatters.styles.gost import GOSTBook, GOSTInternetResource, GOSTCollectionArticle +from formatters.models import ( + BookModel, + InternetResourceModel, + ArticlesCollectionModel, + DissertationModel, + AbstractModel, +) +from formatters.styles.gost import ( + GOSTBook, + GOSTInternetResource, + GOSTCollectionArticle, + GOSTDissertation, + GOSTAbstract, +) class TestGOST: @@ -61,11 +73,41 @@ def test_articles_collection( == "Иванов И.М., Петров С.Н. Наука как искусство // Сборник научных трудов. – СПб.: АСТ, 2020. – С. 25-30." ) + def test_dissertation(self, dissertation_fixture: DissertationModel) -> None: + """ + Тестирование форматирования диссертации. + :param DissertationModel dissertation_fixture: Фикстура модели диссертации + :return: + """ + + model = GOSTDissertation(dissertation_fixture) + + assert ( + model.formatted + == "Иванов И.М.. Наука как искусство [д-р. / канд.] дис. : экон., 01.01.01 / СПб., 2020. - 199 с." + ) + + def test_abstract(self, abstract_fixture: AbstractModel) -> None: + """ + Тестирование форматирования автореферата. + :param AbstractModel abstract_fixture: Фикстура модели автореферата + :return: + """ + + model = GOSTAbstract(abstract_fixture) + + assert ( + model.formatted + == "Иванов И.М.. Наука как искусство [д-р. / канд.] : экон., 01.01.01 / СПб., 2020. - 199 с." + ) + def test_citation_formatter( self, book_model_fixture: BookModel, internet_resource_model_fixture: InternetResourceModel, articles_collection_model_fixture: ArticlesCollectionModel, + dissertation_fixture: DissertationModel, + abstract_fixture: AbstractModel, ) -> None: """ Тестирование функции итогового форматирования списка источников. @@ -73,6 +115,8 @@ def test_citation_formatter( :param BookModel book_model_fixture: Фикстура модели книги :param InternetResourceModel internet_resource_model_fixture: Фикстура модели интернет-ресурса :param ArticlesCollectionModel articles_collection_model_fixture: Фикстура модели сборника статей + :param DissertationModel dissertation_fixture: Фикстура модели диссертации + :param AbstractModel abstract_fixture: Фикстура модели автореферата :return: """ @@ -80,10 +124,14 @@ def test_citation_formatter( GOSTBook(book_model_fixture), GOSTInternetResource(internet_resource_model_fixture), GOSTCollectionArticle(articles_collection_model_fixture), + GOSTDissertation(dissertation_fixture), + GOSTAbstract(abstract_fixture), ] result = BaseCitationFormatter(models).format() # тестирование сортировки списка источников assert result[0] == models[2] assert result[1] == models[0] - assert result[2] == models[1] + assert result[2] == models[4] + assert result[3] == models[3] + assert result[4] == models[1] diff --git a/src/tests/readers/test_readers.py b/src/tests/readers/test_readers.py index 67d863b..98d6d75 100644 --- a/src/tests/readers/test_readers.py +++ b/src/tests/readers/test_readers.py @@ -5,12 +5,20 @@ import pytest -from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel +from formatters.models import ( + BookModel, + InternetResourceModel, + ArticlesCollectionModel, + DissertationModel, + AbstractModel, +) from readers.reader import ( BookReader, SourcesReader, InternetResourceReader, ArticlesCollectionReader, + DissertationReader, + AbstractReader, ) from settings import TEMPLATE_FILE_PATH @@ -104,6 +112,60 @@ def test_articles_collection(self, workbook: Any) -> None: # проверка общего количества атрибутов assert len(model_type.schema().get("properties", {}).keys()) == 7 + def test_abstract(self, workbook: Any) -> None: + """ + Тестирование чтения автореферата. + + :param workbook: Объект тестовой рабочей книги. + """ + + models = AbstractReader(workbook).read() + + assert len(models) == 1 + model = models[0] + + model_type = AbstractModel + + assert isinstance(model, model_type) + assert model.author == "Иванов И.М." + assert model.title == "Наука как искусство" + assert model.degree == "д-р. / канд." + assert model.branch == "экон." + assert model.speciality_code == "01.01.01" + assert model.city == "СПб." + assert model.year == 2020 + assert model.pages == 199 + + # проверка общего количества атрибутов + assert len(model_type.schema().get("properties", {}).keys()) == 8 + + def test_dissertation(self, workbook: Any) -> None: + """ + Тестирование чтения диссертации. + + :param workbook: Объект тестовой рабочей книги. + """ + + models = DissertationReader(workbook).read() + + assert len(models) == 1 + model = models[0] + + model_type = DissertationModel + + assert isinstance(model, model_type) + assert model.author == "Иванов И.М." + assert model.title == "Наука как искусство" + assert model.degree == "д-р. / канд." + assert model.branch == "экон." + assert model.speciality_code == "01.01.01" + assert model.city == "СПб." + assert model.year == 2020 + assert model.pages == 199 + + # проверка общего количества атрибутов + assert len(model_type.schema().get("properties", {}).keys()) == 8 + def test_sources_reader(self) -> None: """ Тестирование функции чтения всех моделей из источника. @@ -111,7 +173,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 +181,6 @@ def test_sources_reader(self) -> None: BookModel.__name__, InternetResourceModel.__name__, ArticlesCollectionModel.__name__, + DissertationModel.__name__, + AbstractModel.__name__, } From 4a63b5d0ea612738556025e93cc2cea1074d2e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B0=D0=BB=D0=B5=D1=80=D0=B8=D1=8F=20=D0=A1=D1=83?= =?UTF-8?q?=D1=85=D0=B8=D0=BD=D0=B8=D0=BD=D0=B0?= Date: Tue, 5 Mar 2024 10:31:53 +0500 Subject: [PATCH 4/5] =?UTF-8?q?=D0=94=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8F=20(README.md=20=D0=B8=20Sphinx)=20?= =?UTF-8?q?=D0=B2=20=D1=81=D0=BE=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82?= =?UTF-8?q?=D0=B2=D0=B8=D0=B8=20=D1=81=20=D0=B2=D0=BD=D0=B5=D1=81=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=BC=D0=B8=20=D0=B4=D0=BE=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=BA=D0=B0=D0=BC=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +++ docs/source/index.rst | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 33c0486..ce933d7 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ The application allows you to automate the process of generating a bibliography Supported citation styles: - ГОСТ Р 7.0.5-2008 +- American Psychological Association 7 ## Installation @@ -57,6 +58,8 @@ to fill it without changing the original template: docker compose run app python main.py --citation gost --path_input /media/input.xlsx --path_output /media/output.docx ``` + The command is given for GOST formatting, to change the citation style you need to change the citation parameter ('gost' or 'apa' for GOST or APA7 style citation respectively). + Also, it is possible to omit the arguments to use their defaults: ```shell docker compose run app python main.py diff --git a/docs/source/index.rst b/docs/source/index.rst index f552b0d..908ccde 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -7,6 +7,7 @@ Поддерживаемые стили цитирования: - ГОСТ Р 7.0.5-2008 + - American Psychological Association 7 Установка ========= @@ -95,7 +96,7 @@ docker compose run app python main.py --citation gost --path_input /media/input.xlsx --path_output /media/output.docx - Таким образом можно определять стиль цитирования и пути ко входному и выходному файлам. + Таким образом можно определять стиль цитирования (`gost` - для ГОСТ Р 7.0.5-2008 и `apa` - для APA 7) и пути ко входному и выходному файлам. Автоматизация ============= From 29a5ac8a4519762422858f37359124ad92914e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B0=D0=BB=D0=B5=D1=80=D0=B8=D1=8F=20=D0=A1=D1=83?= =?UTF-8?q?=D1=85=D0=B8=D0=BD=D0=B8=D0=BD=D0=B0?= Date: Tue, 5 Mar 2024 12:38:37 +0500 Subject: [PATCH 5/5] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=D0=B0=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=20=D0=BB=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=B4=D0=BB=D1=8F=20=D0=BD=D0=BE=D0=B2=D1=8B?= =?UTF-8?q?=D1=85=20=D0=B2=D0=B8=D0=B4=D0=BE=D0=B2=20=D0=B8=D1=81=D1=82?= =?UTF-8?q?=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/formatters/styles/apa.py | 6 ++++++ src/formatters/styles/gost.py | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/formatters/styles/apa.py b/src/formatters/styles/apa.py index 109c38f..c789ee6 100644 --- a/src/formatters/styles/apa.py +++ b/src/formatters/styles/apa.py @@ -205,6 +205,9 @@ def template(self) -> Template: ) def substitute(self) -> str: + + logger.info('Форматирование диссертации "%s" ...', self.data.title) + return self.template.substitute( author=self.data.author, year=self.data.year, @@ -230,6 +233,9 @@ def template(self) -> Template: ) def substitute(self) -> str: + + logger.info('Форматирование автореферата "%s" ...', self.data.title) + return self.template.substitute( author=self.data.author, year=self.data.year, diff --git a/src/formatters/styles/gost.py b/src/formatters/styles/gost.py index 463cb6b..3a4dff2 100644 --- a/src/formatters/styles/gost.py +++ b/src/formatters/styles/gost.py @@ -123,6 +123,9 @@ def template(self) -> Template: ) def substitute(self) -> str: + + logger.info('Форматирование диссертаций "%s" ...', self.data.title) + return self.template.substitute( author=self.data.author, title=self.data.title, @@ -149,6 +152,9 @@ def template(self) -> Template: ) def substitute(self) -> str: + + logger.info('Форматирование автореферата "%s" ...', self.data.title) + return self.template.substitute( author=self.data.author, title=self.data.title,