pytex/PyTeX/format/pytex_formatter.py

128 lines
4.9 KiB
Python
Raw Normal View History

2022-02-07 18:36:30 +01:00
import re
2022-02-06 15:10:28 +01:00
from pathlib import Path
2022-02-07 18:36:30 +01:00
from typing import Optional
from .constants import *
2022-02-06 15:10:28 +01:00
from .formatterif import FormatterIF
2022-02-07 18:36:30 +01:00
from .formatting_config import FormattingConfig
2022-02-06 15:10:28 +01:00
from .generic_text import GenericText
from ..logger import logger
2022-02-08 18:26:25 +01:00
from abc import ABC
2022-02-06 15:10:28 +01:00
2022-02-08 17:04:16 +01:00
class PyTeXFormatter(FormatterIF, ABC):
2022-02-06 15:10:28 +01:00
def __init__(
self,
input_file: Optional[Path] = None,
config: Optional[FormattingConfig] = None,
locate_file_config: bool = True,
allow_infile_config: bool = True
2022-02-06 15:10:28 +01:00
):
super().__init__(
input_file=input_file,
config=config
)
self._config: Optional[FormattingConfig] = self._config # for type-hinting
self._allow_infile_config = allow_infile_config
2022-02-06 15:10:28 +01:00
self._header: Optional[GenericText] = None
if locate_file_config:
file_config = self.parse_file_config()
if allow_infile_config:
infile_config = self.parse_infile_config()
self._config = \
file_config.merge_with(
infile_config,
strict=True
2022-02-08 19:01:18 +01:00
).merge_with(self.config, strict=False)
else:
2022-02-08 19:01:18 +01:00
self._config = file_config.merge_with(self.config)
else:
if allow_infile_config:
infile_config = self.parse_infile_config()
2022-02-08 19:01:18 +01:00
self._config = infile_config.merge_with(self.config)
2022-02-08 16:34:59 +01:00
def parse_file_config(self) -> FormattingConfig:
config_file = self.input_file.with_name(self.input_file.name + PYTEX_CONFIG_FILE_EXTENSION)
if config_file.exists():
try:
2022-02-08 16:34:59 +01:00
return FormattingConfig.from_yaml(config_file)
except:
raise NotImplementedError # Invalid yaml file format
else:
2022-02-08 16:34:59 +01:00
return FormattingConfig()
2022-02-08 16:34:59 +01:00
def parse_infile_config(self) -> FormattingConfig:
if self._input_file is None:
raise NotImplementedError # no file initialised yet
with open(self._input_file, "r") as file:
line = file.readline()
if re.match(self.config.escape_character + INFILE_CONFIG_BEGIN_CONFIG, line):
if not line.strip().lstrip('%').strip() == self.config.escape_character + INFILE_CONFIG_BEGIN_CONFIG:
logger.warning(
"File {file}: Start of infile config invalid."
)
config = []
while True:
line = file.readline()
if re.match(self.config.escape_character + INFILE_CONFIG_END_CONFIG, line):
if not line.strip().lstrip(
'%').strip() == self.config.escape_character + INFILE_CONFIG_END_CONFIG:
logger.warning(
"File {file}: End of infile config invalid."
)
break
if line == '':
raise NotImplementedError # No matching end block
config.append(line.lstrip('%').rstrip())
try:
2022-02-08 16:34:59 +01:00
return FormattingConfig.from_yaml('\n'.join(config))
except:
raise NotImplementedError # Invalid yaml file format
else:
2022-02-08 16:34:59 +01:00
return FormattingConfig()
2022-02-06 15:10:28 +01:00
@property
def config(self) -> FormattingConfig:
if self._config is None:
2022-02-08 19:01:18 +01:00
return FormattingConfig()
2022-02-06 15:10:28 +01:00
return self._config
2022-02-08 16:34:59 +01:00
@config.setter
def config(self, formatting_config: FormattingConfig):
self._config = formatting_config
2022-02-06 15:10:28 +01:00
@property
def header(self) -> GenericText:
if self._header is None:
if not (
self.config.include_extra_header
2022-02-08 16:34:59 +01:00
or self.config.include_time
or self.config.include_pytex_version
or self.config.include_pytex_info_text
or self.config.include_repo_version
or self.config.include_repo_info_text
2022-02-06 15:10:28 +01:00
):
self._header = GenericText([])
else:
self._header = GenericText([])
# TODO: handle license
if self.config.include_extra_header:
self._header += self.config.extra_header + ['']
if self.config.include_repo_info_text:
self._header += self.config.repo_info_text
if self.config.include_pytex_info_text:
self._header += self.config.pytex_info_text + ['']
## TODO handle rest
return self._header
2022-02-06 16:08:05 +01:00
2022-02-06 18:51:49 +01:00
def make_header(self, **kwargs) -> str:
return '\n'.join(
[
2022-02-07 18:36:30 +01:00
'%' * 80,
self.header.format(**kwargs), # TODO: add standard keywords here
'%' * 80
]
)