Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions src/formatters/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,56 @@ class ArticlesCollectionModel(BaseModel):
publishing_house: str
year: int = Field(..., gt=0)
pages: str


class AutoabstractModel(BaseModel):
"""
Модель автореферата:

.. code-block::

AutoabstractModel(
author="Иванов И.М.",
dissertation_title="д-р. / канд.",
author_title="Сборник научных трудов",
science_field="экон.",
speciality_code="01.01.01",
city="СПб.",
year=2020,
page="199",
)
"""

author: str
dissertation_title: str
author_title: str
science_field: str
speciality_code: str
city: str
year: int = Field(..., gt=0)
page: int


class JournalArticleModel(BaseModel):

"""
Модель статьи из журнала:

.. code-block::

JournalArticleModel(
authors="Иванов И.М., Петров С.Н.",
article_title="Наука как искусство",
journal="Образование и наука",
year=2020,
issue="10",
pages="25-30",
)
"""

authors: str
article_title: str
journal: str
year: int = Field(..., gt=0)
issue: int = Field(..., gt=0)
pages: str
111 changes: 111 additions & 0 deletions src/formatters/styles/apa.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
"""
American Psychological Association
"""
from string import Template

from pydantic import BaseModel

from formatters.models import (
BookModel,
InternetResourceModel,
ArticlesCollectionModel,
AutoabstractModel,
JournalArticleModel,
)
from formatters.styles.base import BaseCitationStyle
from logger import get_logger


logger = get_logger(__name__)


class APABook(BaseCitationStyle):
"""
Форматирование для книг:
"""

data: BookModel

@property
def template(self) -> Template:
return Template(
"$authors ($year) $title ($edition) $city: $publishing_house, $pages с."
)

def substitute(self) -> str:

logger.info('Форматирование книги "%s" ...', self.data.title)

return self.template.substitute(
authors=self.data.authors,
title=self.data.title,
edition=self.get_edition(),
city=self.data.city,
publishing_house=self.data.publishing_house,
year=self.data.year,
pages=self.data.pages,
)

def get_edition(self) -> str:
"""
Получение отформатированной информации об издательстве.

:return: Информация об издательстве.
"""

return f"{self.data.edition} изд. – " if self.data.edition else ""


class APAInternetResource(BaseCitationStyle):
"""
Форматирование для интернет-ресурса:
"""

data: InternetResourceModel

@property
def template(self) -> Template:
return Template("$website ($access_date) $article $link")

def substitute(self) -> str:

logger.info('Форматирование интернет-ресурса "%s" ...', 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 APACitationFormatter:
"""
Базовый класс для итогового форматирования списка источников.
"""

formatters_map = {
BookModel.__name__: APABook,
InternetResourceModel.__name__: APAInternetResource,
}

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)
67 changes: 66 additions & 1 deletion src/formatters/styles/gost.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@

from pydantic import BaseModel

from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel
from formatters.models import (
BookModel,
InternetResourceModel,
ArticlesCollectionModel,
AutoabstractModel,
JournalArticleModel,
)
from formatters.styles.base import BaseCitationStyle
from logger import get_logger

Expand Down Expand Up @@ -103,6 +109,63 @@ def substitute(self) -> str:
)


class GOSTAutoabstract(BaseCitationStyle):
"""
Форматирование для автореферата.
"""

data: AutoabstractModel

@property
def template(self) -> Template:
return Template(
"$author $dissertation_title: $author_title $science_field: $speciality_code $city $year. $page c."
)

def substitute(self) -> str:
logger.info(
'Форматирование автореферата "%s" ...', self.data.dissertation_title
)

return self.template.substitute(
author=self.data.author,
dissertation_title=self.data.dissertation_title,
author_title=self.data.author_title,
science_field=self.data.science_field,
speciality_code=self.data.speciality_code,
city=self.data.city,
year=self.data.year,
page=self.data.page,
)


class GOSTJournalArticle(BaseCitationStyle):
"""
Форматирование для статьи из журнала.
"""

data: JournalArticleModel

@property
def template(self) -> Template:
return Template(
"$authors $article_title // $journal. $year. № $issue. С. $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,
journal=self.data.journal,
year=self.data.year,
issue=self.data.issue,
pages=self.data.pages,
)


class GOSTCitationFormatter:
"""
Базовый класс для итогового форматирования списка источников.
Expand All @@ -112,6 +175,8 @@ class GOSTCitationFormatter:
BookModel.__name__: GOSTBook,
InternetResourceModel.__name__: GOSTInternetResource,
ArticlesCollectionModel.__name__: GOSTCollectionArticle,
AutoabstractModel.__name__: GOSTAutoabstract,
JournalArticleModel.__name__: GOSTJournalArticle,
}

def __init__(self, models: list[BaseModel]) -> None:
Expand Down
14 changes: 11 additions & 3 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import click

from formatters.styles.apa import APACitationFormatter
from formatters.styles.gost import GOSTCitationFormatter
from logger import get_logger
from readers.reader import SourcesReader
Expand Down Expand Up @@ -77,9 +78,16 @@ def process_input(
)

models = SourcesReader(path_input).read()
formatted_models = tuple(
str(item) for item in GOSTCitationFormatter(models).format()
)

if citation == CitationEnum.GOST.name:
formatter_class = GOSTCitationFormatter
elif citation == CitationEnum.APA.name:
formatter_class = APACitationFormatter
else:
logger.error("Validation error : Unsupported input")
exit()

formatted_models = tuple(str(item) for item in formatter_class(models).format())

logger.info("Генерация выходного файла ...")
Renderer(formatted_models).render(path_output)
Expand Down
62 changes: 61 additions & 1 deletion src/readers/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
import openpyxl
from openpyxl.workbook import Workbook

from formatters.models import BookModel, InternetResourceModel, ArticlesCollectionModel
from formatters.models import (
BookModel,
InternetResourceModel,
ArticlesCollectionModel,
AutoabstractModel,
JournalArticleModel,
)
from logger import get_logger
from readers.base import BaseReader

Expand Down Expand Up @@ -90,6 +96,58 @@ def attributes(self) -> dict:
}


class AutoabstractReader(BaseReader):
"""
Чтение модели автореферата.
"""

@property
def model(self) -> Type[AutoabstractModel]:
return AutoabstractModel

@property
def sheet(self) -> str:
return "Автореферат"

@property
def attributes(self) -> dict:
return {
"author": {0: str},
"dissertation_title": {1: str},
"author_title": {2: str},
"science_field": {3: str},
"speciality_code": {4: str},
"city": {5: str},
"year": {6: int},
"page": {7: int},
}


class JournalArticleReader(BaseReader):
"""
Чтение модели статьи из журнала.
"""

@property
def model(self) -> Type[JournalArticleModel]:
return JournalArticleModel

@property
def sheet(self) -> str:
return "Статья из журнала"

@property
def attributes(self) -> dict:
return {
"authors": {0: str},
"article_title": {1: str},
"journal": {2: str},
"year": {3: int},
"issue": {4: int},
"pages": {5: str},
}


class SourcesReader:
"""
Чтение из источника данных.
Expand All @@ -100,6 +158,8 @@ class SourcesReader:
BookReader,
InternetResourceReader,
ArticlesCollectionReader,
AutoabstractReader,
JournalArticleReader,
]

def __init__(self, path: str) -> None:
Expand Down
2 changes: 2 additions & 0 deletions src/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
# путь к файлу шаблона для создания входного файла
TEMPLATE_FILE_PATH: str = os.getenv("TEMPLATE_FILE_PATH", "../media/template.xlsx")

# Стиль цитирования
# CITATION:
# путь к входному файлу
INPUT_FILE_PATH: str = os.getenv("INPUT_FILE_PATH", "../media/input.xlsx")
# путь к выходному файлу
Expand Down
Loading