pytex/PyTeX/format/formatting_config.py

418 lines
13 KiB
Python

from typing import List, Optional, Union, Dict
from pathlib import Path
import yaml
import json
from .enums import NamingScheme
from .generic_text import GenericText
from .formatterif import Config
from .git_version_info import GitVersionInfo
from .constants import *
from .enums import TeXType, TeXFlavour
class VersionInfo:
def __init__(self):
self._repo_version: Optional[GitVersionInfo] = None
self._pytex_version: Optional[GitVersionInfo] = None
@property
def pytex_version(self) -> Optional[GitVersionInfo]:
if self._pytex_version is None:
return None
else:
return self._pytex_version
@property
def repo_version(self) -> Optional[GitVersionInfo]:
if self._repo_version is None:
return None
else:
return self._repo_version
def clean_dict(dictionary: Dict) -> Optional[Dict]:
aux = {
k: clean_dict(v) for k, v in dictionary.items() if type(v) == dict
} | {
k: v for k, v in dictionary.items() if type(v) != dict
}
aux2 = {
k: v for k, v in aux.items() if v is not None
}
return aux2 if aux2 != {} else None
def recursive_merge_dictionaries(dict1: Dict, dict2: Dict) -> Dict:
aux1 = {
k: v for k, v in dict1.items() if type(v) == dict
}
aux2 = {
k: v for k, v in dict2.items() if type(v) == dict
}
merged = {
k: recursive_merge_dictionaries(v, aux2[k]) for k, v in aux1.items() if k in aux2.keys()
}
return dict1 | dict2 | merged
class FormattingConfig(Config):
def __init__(self):
self._naming_scheme: Optional[Union[NamingScheme, str]] = None
self._license: Optional[GenericText] = None
self._description: Optional[str] = None
self._include_extra_header: Optional[bool] = None
self._include_pytex_version: Optional[bool] = None
self._include_pytex_info_text: Optional[bool] = None
self._include_repo_version: Optional[bool] = None
self._include_repo_info_text: Optional[bool] = None
self._include_time: Optional[bool] = None
self._include_license: Optional[bool] = None
self._extra_header: Optional[GenericText] = None
self._author: Optional[str] = None
self._version: Optional[str] = None
self._pytex_info_text: Optional[GenericText] = None
self._repo_info_text: Optional[GenericText] = None
self._include_drv: Optional[bool] = None
self._include_ins: Optional[bool] = None
self._docstrip_guards: Optional[List[str]] = None
self._doc_dependencies: Optional[List[str]] = None
self._tex_dependencies: Optional[List[str]] = None
self._tex_type: Optional[TeXType] = None
self._tex_flavour: Optional[TeXFlavour] = None
def set_from_json(self, content: Dict):
content = recursive_merge_dictionaries(
FormattingConfig().to_json(),
content
)
info = content[YAML_INFO]
self._author = info[YAML_AUTHOR]
self._naming_scheme = info[YAML_NAMING_SCHEME]
self._tex_flavour = info[YAML_TEX_FLAVOUR]
self._tex_type = info[YAML_TEX_TYPE]
self._description = info[YAML_DESCRIPTION]
header = content[YAML_HEADER]
extra = header[YAML_EXTRA]
self._include_extra_header = extra[YAML_INCLUDE_EXTRA_HEADER]
self._extra_header = GenericText(
extra[YAML_PATH] if extra[YAML_PATH] else extra[YAML_TEXT]
)
repo = header[YAML_REPO]
self._include_repo_info_text = repo[YAML_INCLUDE_INFO_TEXT]
self._include_repo_version = repo[YAML_INCLUDE_VERSION]
self._repo_info_text = GenericText(
repo[YAML_PATH] if repo[YAML_PATH] else repo[YAML_TEXT]
)
pytex = header[YAML_PYTEX]
self._include_pytex_info_text = pytex[YAML_INCLUDE_INFO_TEXT]
self._include_pytex_version = pytex[YAML_INCLUDE_VERSION]
self._pytex_info_text = GenericText(
pytex[YAML_PATH] if pytex[YAML_PATH] else pytex[YAML_TEXT]
)
self._include_time = header[YAML_INCLUDE_TIME]
license_ = header[YAML_LICENSE]
self._include_license = license_[YAML_INCLUDE_LICENSE]
self._license = GenericText(
license_[YAML_PATH] if license_[YAML_PATH] else license_[YAML_TEXT]
)
docstrip = content[YAML_DOCSTRIP]
self._include_drv = docstrip[YAML_INCLUDE_DRV]
self._include_ins = docstrip[YAML_INCLUDE_INS]
self._docstrip_guards = docstrip[YAML_DOCSTRIP_GUARDS]
@classmethod
def from_yaml(cls, content: Path):
with open(content, 'r') as config:
content: Dict = yaml.safe_load(config)
return cls.from_json(content)
@classmethod
def from_json(cls, content: Union[Path, Dict]):
if isinstance(content, Path):
with open(content, 'r') as config:
content: Dict = json.load(config)
config = FormattingConfig()
config.set_from_json(content)
return config
def dump_as_yaml(self, filename: Path):
with filename.open('w') as file:
simple_dict = clean_dict(self.to_json())
if simple_dict is not None:
yaml.dump(simple_dict, file)
else:
pass # TODO
def to_json(self) -> Dict:
return {
YAML_INFO: {
YAML_AUTHOR: self._author,
YAML_NAMING_SCHEME: self._naming_scheme,
YAML_TEX_FLAVOUR: self._tex_flavour,
YAML_TEX_TYPE: self._tex_type,
YAML_VERSION: self._version,
YAML_DESCRIPTION: self._description
},
YAML_HEADER: {
YAML_EXTRA: {
YAML_INCLUDE_EXTRA_HEADER: self._include_extra_header,
YAML_PATH: self._extra_header.pathname if self._extra_header else None,
YAML_TEXT: self._extra_header.real_text if self._extra_header else None
},
YAML_REPO: {
YAML_INCLUDE_INFO_TEXT: self._include_repo_info_text,
YAML_INCLUDE_VERSION: self._include_repo_version,
YAML_PATH: self._repo_info_text.pathname if self._repo_info_text else None,
YAML_TEXT: self._repo_info_text.real_text if self._repo_info_text else None
},
YAML_PYTEX: {
YAML_INCLUDE_INFO_TEXT: self._include_pytex_info_text,
YAML_INCLUDE_VERSION: self._include_pytex_version,
YAML_PATH: self._pytex_info_text.path if self._pytex_info_text else None,
YAML_TEXT: self._pytex_info_text.real_text if self._pytex_info_text else None
},
YAML_INCLUDE_TIME: self._include_time,
YAML_LICENSE: {
YAML_INCLUDE_LICENSE: self._include_license,
YAML_PATH: self._license.path if self._license else None,
YAML_TEXT: self._license.real_text if self._license else None
},
},
YAML_DOCSTRIP: {
YAML_INCLUDE_DRV: self._include_drv,
YAML_INCLUDE_INS: self._include_ins,
YAML_DOCSTRIP_GUARDS: self._docstrip_guards
},
YAML_DEPENDENCIES: {
YAML_DOC_DEPENDENCIES: self._doc_dependencies,
YAML_TEX_DEPENDENCIES: self._tex_dependencies
}
}
@property
def naming_scheme(self) -> NamingScheme:
if self._naming_scheme is None:
return NamingScheme.prepend_author
else:
return self._naming_scheme
@naming_scheme.setter
def naming_scheme(self, naming_scheme: NamingScheme):
self._naming_scheme = naming_scheme
@property
def license(self) -> GenericText:
if self._license is None:
return GenericText()
else:
return self._license
@license.setter
def license(self, license: GenericText):
self._license = license
@property
def include_extra_header(self) -> bool:
if self._include_extra_header is None:
return False
else:
return self._include_extra_header
@include_extra_header.setter
def include_extra_header(self, include: bool):
self._include_extra_header = include
@property
def include_pytex_version(self) -> bool:
if self._include_pytex_version is None:
return False
else:
return self._include_pytex_version
@include_pytex_version.setter
def include_pytex_version(self, include: bool):
self._include_pytex_version = include
@property
def include_pytex_info_text(self) -> bool:
if self._include_pytex_info_text is None:
return False
else:
return self._include_pytex_info_text
@include_pytex_info_text.setter
def include_pytex_info_text(self, include: bool):
self._include_pytex_info_text = include
@property
def include_repo_version(self) -> bool:
if self._include_repo_version is None:
return False
else:
return self._include_repo_version
@include_repo_version.setter
def include_repo_version(self, include: bool):
self._include_repo_version = include
@property
def include_repo_info_text(self) -> bool:
if self._include_repo_info_text is None:
return False
else:
return self._include_repo_info_text
@include_repo_info_text.setter
def include_repo_info_text(self, include: bool):
self._include_repo_info_text = include
@property
def extra_header(self) -> GenericText:
if self._extra_header is None:
return GenericText()
else:
return self._extra_header
@extra_header.setter
def extra_header(self, extra_header: GenericText):
self._extra_header = extra_header
@property
def author(self) -> str:
if self._author is None:
return "MISSING AUTHOR"
else:
return self._author
@author.setter
def author(self, author: str):
self._author = author
@property
def version(self) -> str:
if self._version is None:
return "0.0.0"
else:
return self._version
@version.setter
def version(self, version: str):
self._version = version
@property
def pytex_info_text(self) -> GenericText:
if self._pytex_info_text is None:
return GenericText()
else:
return self._pytex_info_text
@pytex_info_text.setter
def pytex_info_text(self, info_text: GenericText):
self._pytex_info_text = info_text
@property
def repo_info_text(self) -> GenericText:
if self._repo_info_text is None:
return GenericText()
else:
return self._repo_info_text
@repo_info_text.setter
def repo_info_text(self, info_text: GenericText):
self._repo_info_text = info_text
@property
def include_drv(self) -> bool:
if self._include_drv is None:
return False
else:
return self._include_drv
@include_drv.setter
def include_drv(self, include: bool):
self._include_drv = include
@property
def include_ins(self) -> bool:
if self._include_ins is None:
return False
else:
return self._include_ins
@include_ins.setter
def include_ins(self, include):
self._include_ins = include
@property
def docstrip_guards(self) -> List[str]:
if self._docstrip_guards is None:
return []
else:
return self._docstrip_guards
@docstrip_guards.setter
def docstrip_guards(self, guards: List[str]):
self._docstrip_guards = guards
@property
def description(self) -> str:
if self._description is None:
return ''
else:
return self._description
@description.setter
def description(self, description: str):
self._description = description
@property
def include_time(self) -> bool:
if self._include_time is None:
return False
else:
return self._include_time
@include_time.setter
def include_time(self, include: bool):
self._include_time = include
@property
def doc_dependencies(self) -> List[str]:
if self._doc_dependencies is None:
return []
else:
return self._doc_dependencies
@doc_dependencies.setter
def doc_dependencies(self, dependencies: List[str]):
self._doc_dependencies = dependencies
@property
def tex_dependencies(self) -> List[str]:
if self._tex_dependencies is None:
return []
else:
return self._tex_dependencies
@tex_dependencies.setter
def tex_dependencies(self, dependencies: List[str]):
self._tex_dependencies = dependencies
class DocFormattingConfig:
def __init__(self):
self._documents: Optional[List[str]] = None
self._dependencies: Optional[List[str]] = None