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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

## Installation

Expand Down
83 changes: 82 additions & 1 deletion src/formatters/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ class InternetResourceModel(BaseModel):


class ArticlesCollectionModel(BaseModel):

"""
Модель сборника статей:

Expand All @@ -78,3 +77,85 @@ class ArticlesCollectionModel(BaseModel):
publishing_house: str
year: int = Field(..., gt=0)
pages: str


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

.. code-block::

ArticlesCollectionModel(
author="Иванов И.М.",
abstract_title="Наука как искусство",
author_status="д-р. / канд.",
science_field="экон.",
specialty_code="01.01.01",
city="Спб.",
year=2020,
pages="199",
)
"""

author: str
abstract_title: str
author_status: str
science_field: str
specialty_code: str
city: str
year: int = Field(..., gt=0)
pages: str


class RegulationModel(BaseModel):
"""
Модель нормативного акта:

.. code-block::

ArticlesCollectionModel(
regulation_title="Наука как искусство",
source="Конституция Российской Федерации",
publishing_source="Парламентская газета",
regulation_id="1234-56",
acceptance_date="1/1/2000",
publishing_year="2020",
publishing_source_id="5",
publishing_article_id="15",
modification_date="9/11/2002"
)
"""

regulation_title: str
source: str
publishing_source: str
regulation_id: str
acceptance_date: str
publishing_year: int = Field(..., gt=0)
publishing_source_id: str
publishing_article_id: str
modification_date: str


class NewsPaperModel(BaseModel):
"""
Модель газеты:

.. code-block::

NewsPaperModel(
article_title="Наука как искусство",
authors="Иванов И.М., Петров С.Н.",
news_title="Южный Урал",
publishing_year="1980",
publishing_date="01.10",
publishing_number="5"
)
"""

article_title: str
authors: str
news_title: str
publishing_year: int = Field(..., gt=0)
publishing_date: str
publishing_number: int = Field(..., gt=0)
115 changes: 115 additions & 0 deletions src/formatters/styles/apa.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
"""
Стиль цитирования по American Psychological Association
"""
from string import Template

from pydantic import BaseModel

from formatters.models import BookModel, InternetResourceModel, NewsPaperModel
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. $publishing_house.")

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

return self.template.substitute(
authors=self.data.authors,
title=self.data.title,
publishing_house=self.data.publishing_house,
year=self.data.year,
)


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

data: InternetResourceModel

@property
def template(self) -> Template:
return Template("$article ($access_date) $website $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 APANewsPaperResource(BaseCitationStyle):
"""
Форматирование для газеты.
"""

data: NewsPaperModel

@property
def template(self) -> Template:
return Template(
"$authors ($publishing_year, $publishing_date). $article_title. $news_title."
)

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

return self.template.substitute(
article_title=self.data.article_title,
authors=self.data.authors,
news_title=self.data.news_title,
publishing_year=self.data.publishing_year,
publishing_date=self.data.publishing_date,
)


class APACitationFormatter:
"""
Базовый класс для итогового форматирования списка источников.
"""

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

def __init__(self, models: list[BaseModel]) -> None:
"""
Конструктор.
:param models: Список объектов для форматирования
"""

formatted_items = []
for model in models:
formatter = self.formatters_map.get(type(model).__name__)
if formatter is not None:
formatted_items.append(formatter(model)) # type: ignore

self.formatted_items = formatted_items

def format(self) -> list[BaseCitationStyle]:
"""
Форматирование списка источников.
:return:
"""

return sorted(self.formatted_items, key=lambda item: item.formatted)
80 changes: 74 additions & 6 deletions src/formatters/styles/gost.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@

from pydantic import BaseModel

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


logger = get_logger(__name__)


Expand All @@ -27,7 +32,6 @@ def template(self) -> Template:
)

def substitute(self) -> str:

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

return self.template.substitute(
Expand Down Expand Up @@ -64,7 +68,6 @@ def template(self) -> Template:
)

def substitute(self) -> str:

logger.info('Форматирование интернет-ресурса "%s" ...', self.data.article)

return self.template.substitute(
Expand All @@ -89,7 +92,6 @@ def template(self) -> Template:
)

def substitute(self) -> str:

logger.info('Форматирование сборника статей "%s" ...', self.data.article_title)

return self.template.substitute(
Expand All @@ -103,6 +105,68 @@ def substitute(self) -> str:
)


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

data: AbstractModel

@property
def template(self) -> Template:
return Template(
"$author $abstract_title: автореф. дис. ... $author_status $science_field наук: $specialty_code. $city, "
"$year. $pages с."
)

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

return self.template.substitute(
author=self.data.author,
abstract_title=self.data.abstract_title,
author_status=self.data.author_status,
science_field=self.data.science_field,
specialty_code=self.data.specialty_code,
city=self.data.city,
year=self.data.year,
pages=self.data.pages,
)


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

data: RegulationModel

@property
def template(self) -> Template:
return Template(
'$source "$regulation_title" от $acceptance_date № $regulation_id // $publishing_source. '
"$publishing_year г. № $publishing_source_id. Ст. $publishing_article_id с изм. и допол. в ред. от "
"$modification_date"
)

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

return self.template.substitute(
regulation_title=self.data.regulation_title,
source=self.data.source,
publishing_source=self.data.publishing_source,
regulation_id=self.data.regulation_id,
acceptance_date=self.data.acceptance_date,
publishing_year=self.data.publishing_year,
publishing_source_id=self.data.publishing_source_id,
publishing_article_id=self.data.publishing_article_id,
modification_date=self.data.modification_date,
)


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

def __init__(self, models: list[BaseModel]) -> None:
Expand All @@ -123,7 +189,9 @@ def __init__(self, models: list[BaseModel]) -> None:

formatted_items = []
for model in models:
formatted_items.append(self.formatters_map.get(type(model).__name__)(model)) # type: ignore
formatter = self.formatters_map.get(type(model).__name__)
if formatter is not None:
formatted_items.append(formatter(model)) # type: ignore

self.formatted_items = formatted_items

Expand Down
21 changes: 15 additions & 6 deletions src/main.py
100644 → 100755
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 All @@ -25,6 +26,19 @@ class CitationEnum(Enum):
APA = "apa" # American Psychological Association


style_map = {
CitationEnum.APA.name: APACitationFormatter,
CitationEnum.GOST.name: GOSTCitationFormatter,
}


def format_by_style(citation: str, models: list, path_output: str) -> None:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Новые методы тоже нужно документировать :)

logger.info(style_map[citation])
formatted_models = tuple(str(item) for item in style_map[citation](models).format())
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Что, если citation не найдется в словаре style_map?

logger.info(f"Генерация выходного файла в формате ${citation}...")
Renderer(formatted_models).render(path_output)


@click.command()
@click.option(
"--citation",
Expand Down Expand Up @@ -77,12 +91,7 @@ def process_input(
)

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

logger.info("Генерация выходного файла ...")
Renderer(formatted_models).render(path_output)
format_by_style(citation, models, path_output)

logger.info("Команда успешно завершена.")

Expand Down
Loading