Compare commits
5 commits
master
...
latex-pack
Author | SHA1 | Date | |
---|---|---|---|
c9bb0e87c9 | |||
75428387f6 | |||
ed6494826f | |||
e661ceee64 | |||
6277050e22 |
9 changed files with 116 additions and 39 deletions
|
@ -1,7 +1,8 @@
|
||||||
from PyTeX.default_formatters import ClassFormatter, PackageFormatter, DictionaryFormatter
|
from PyTeX.default_formatters import ClassFormatter, PackageFormatter, DictionaryFormatter, DocstripFormatter
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"ClassFormatter",
|
"ClassFormatter",
|
||||||
"PackageFormatter",
|
"PackageFormatter",
|
||||||
"DictionaryFormatter"
|
"DictionaryFormatter",
|
||||||
|
'DocstripFormatter'
|
||||||
]
|
]
|
||||||
|
|
|
@ -15,20 +15,20 @@ def build(
|
||||||
build_dir: Optional[Path] = None,
|
build_dir: Optional[Path] = None,
|
||||||
input_file: Optional[Path] = None,
|
input_file: Optional[Path] = None,
|
||||||
author: Optional[str] = None,
|
author: Optional[str] = None,
|
||||||
latex_name: str = 'prepend-author', # name handling
|
latex_name: str = 'prepend-author', # name handling
|
||||||
recursive: bool = False, # input control
|
recursive: bool = False, # input control
|
||||||
include_timestamp: bool = False, # header
|
include_timestamp: bool = False, # header
|
||||||
include_pytex_version: bool = False, # header
|
include_pytex_version: bool = False, # header
|
||||||
include_license: bool = False, # header
|
include_license: bool = False, # header
|
||||||
include_git_version: bool = False, # header
|
include_git_version: bool = False, # header
|
||||||
include_pytex_info_text: bool = False, # header
|
include_pytex_info_text: bool = False, # header
|
||||||
extra_header: Optional[Path] = None,
|
extra_header: Optional[Path] = None,
|
||||||
allow_dirty: bool = False, # versioning
|
allow_dirty: bool = False, # versioning
|
||||||
overwrite_existing_files: bool = False, # output control
|
overwrite_existing_files: bool = False, # output control
|
||||||
build_all: bool = False, # output control / versioning
|
build_all: bool = False, # output control / versioning
|
||||||
write_build_information: bool = True, # meta
|
write_build_information: bool = True, # meta
|
||||||
clean_old_files: bool = False
|
clean_old_files: bool = False
|
||||||
):
|
):
|
||||||
pytex_msg('Getting git repository information...')
|
pytex_msg('Getting git repository information...')
|
||||||
if extra_header:
|
if extra_header:
|
||||||
if extra_header.exists():
|
if extra_header.exists():
|
||||||
|
@ -76,6 +76,8 @@ def build(
|
||||||
files.append(file)
|
files.append(file)
|
||||||
for file in src_dir.rglob('*.pycls3'):
|
for file in src_dir.rglob('*.pycls3'):
|
||||||
files.append(file)
|
files.append(file)
|
||||||
|
for file in src_dir.rglob('*.dtx'):
|
||||||
|
files.append(file)
|
||||||
else:
|
else:
|
||||||
for file in src_dir.glob('*.pysty'):
|
for file in src_dir.glob('*.pysty'):
|
||||||
files.append(file)
|
files.append(file)
|
||||||
|
@ -87,12 +89,15 @@ def build(
|
||||||
files.append(file)
|
files.append(file)
|
||||||
for file in src_dir.glob('*.pycls3'):
|
for file in src_dir.glob('*.pycls3'):
|
||||||
files.append(file)
|
files.append(file)
|
||||||
|
for file in src_dir.glob('*.dtx'):
|
||||||
|
files.append(file)
|
||||||
|
|
||||||
sources_to_build = []
|
sources_to_build = []
|
||||||
for file in files:
|
for file in files:
|
||||||
if last_build_info:
|
if last_build_info:
|
||||||
last_build_info_for_this_file =\
|
last_build_info_for_this_file = \
|
||||||
list(filter(lambda i: i['source file'] == str(file.relative_to(src_dir)), last_build_info['tex_sources']))
|
list(filter(lambda i: i['source file'] == str(file.relative_to(src_dir)),
|
||||||
|
last_build_info['tex_sources']))
|
||||||
else:
|
else:
|
||||||
last_build_info_for_this_file = []
|
last_build_info_for_this_file = []
|
||||||
sources_to_build.append(
|
sources_to_build.append(
|
||||||
|
@ -143,8 +148,9 @@ def build(
|
||||||
file.unlink()
|
file.unlink()
|
||||||
elif not str(file.relative_to(output_dir)) in built_files:
|
elif not str(file.relative_to(output_dir)) in built_files:
|
||||||
if not file.is_dir() and not str(file.relative_to(output_dir)) == 'build_info.json':
|
if not file.is_dir() and not str(file.relative_to(output_dir)) == 'build_info.json':
|
||||||
# PyTeX does not at all know something about this file
|
if '.git' not in str(file) and 'documentation/' not in str(file):
|
||||||
raise UnknownFileInBuildDirectory(file.relative_to(output_dir))
|
# PyTeX does not at all know something about this file
|
||||||
|
raise UnknownFileInBuildDirectoryError(file.relative_to(output_dir))
|
||||||
|
|
||||||
if write_build_information:
|
if write_build_information:
|
||||||
with open(output_dir / 'build_info.json', 'w') as f:
|
with open(output_dir / 'build_info.json', 'w') as f:
|
||||||
|
|
|
@ -77,7 +77,7 @@ def parse_and_build(arglist: [str]):
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-l', '--license',
|
'-l', '--license',
|
||||||
help='Insert MIT license into package header',
|
help='Insert LPPL and GPLv3 license into package header',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
dest='include_license'
|
dest='include_license'
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,7 +2,7 @@ from pathlib import Path
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
|
|
||||||
from PyTeX.build.git_hook import is_recent, get_latest_commit
|
from PyTeX.build.git_hook import is_recent, get_latest_commit
|
||||||
from PyTeX import PackageFormatter, ClassFormatter, DictionaryFormatter
|
from PyTeX import PackageFormatter, ClassFormatter, DictionaryFormatter, DocstripFormatter
|
||||||
from PyTeX.errors import *
|
from PyTeX.errors import *
|
||||||
from .pytex_msg import pytex_msg
|
from .pytex_msg import pytex_msg
|
||||||
from PyTeX.utils import md5
|
from PyTeX.utils import md5
|
||||||
|
@ -79,6 +79,8 @@ class TexFileToFormat:
|
||||||
latex_file_type = 'class'
|
latex_file_type = 'class'
|
||||||
elif '.pydict' in self.src_path.name:
|
elif '.pydict' in self.src_path.name:
|
||||||
latex_file_type = 'dictionary'
|
latex_file_type = 'dictionary'
|
||||||
|
elif '.dtx' in self.src_path.name:
|
||||||
|
latex_file_type = 'ERROR'
|
||||||
else:
|
else:
|
||||||
raise ProgrammingError
|
raise ProgrammingError
|
||||||
new_header.append(line.format(
|
new_header.append(line.format(
|
||||||
|
@ -126,6 +128,8 @@ class TexFileToFormat:
|
||||||
author=self.current_build_info.author,
|
author=self.current_build_info.author,
|
||||||
header=self._header
|
header=self._header
|
||||||
)
|
)
|
||||||
|
elif self.src_path.name.endswith('.dtx'):
|
||||||
|
formatter = DocstripFormatter(name=self.src_path.with_suffix('').name)
|
||||||
else:
|
else:
|
||||||
raise ProgrammingError
|
raise ProgrammingError
|
||||||
formatter.make_default_macros()
|
formatter.make_default_macros()
|
||||||
|
|
|
@ -1,22 +1,27 @@
|
||||||
LICENSE = [
|
LICENSE = [
|
||||||
'Copyright © {year} {copyright_holders}',
|
'Copyright © {year} {copyright_holders}',
|
||||||
'',
|
'',
|
||||||
'Permission is hereby granted, free of charge, to any person obtaining a copy',
|
'This work may be distributed and/or modified',
|
||||||
'of this software and associated documentation files (the “Software”), to deal',
|
|
||||||
'in the Software without restriction, including without limitation the rights',
|
|
||||||
'to use, copy, modify, merge, publish, distribute, sublicense, and/or sell',
|
|
||||||
'copies of the Software, and to permit persons to whom the Software is',
|
|
||||||
'furnished to do so, subject to the following conditions:',
|
|
||||||
'The above copyright notice and this permission notice shall be included in all',
|
|
||||||
'copies or substantial portions of the Software.',
|
|
||||||
'',
|
'',
|
||||||
'THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR',
|
'1. under the LaTeX Project Public License and/or',
|
||||||
'IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,',
|
'2. under the GNU General Public License'
|
||||||
'FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE',
|
'',
|
||||||
'AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER',
|
'',
|
||||||
'LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,',
|
'Distribution under conditions of the LaTeX Project Public License,',
|
||||||
'OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE',
|
'requires either version 1.3 of this license or (at your option)',
|
||||||
'SOFTWARE.'
|
'any later version.',
|
||||||
|
'The latest version of this license is in',
|
||||||
|
' http://www.latex-project.org/lppl.txt',
|
||||||
|
'and version 1.3 or later is part of all distributions of LaTeX',
|
||||||
|
'version 2005/12/01 or later.',
|
||||||
|
'',
|
||||||
|
'This work has the LPPL maintenance status \`maintained\'.',
|
||||||
|
'',
|
||||||
|
'The Current Maintainer of this work is {copyright_holders}.',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'Distribution under the GNU General Public License requires either',
|
||||||
|
'version 3 or (at your opinion) any later version.'
|
||||||
]
|
]
|
||||||
|
|
||||||
PYTEX_INFO_TEXT = [
|
PYTEX_INFO_TEXT = [
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
from .class_formatter import ClassFormatter
|
from .class_formatter import ClassFormatter
|
||||||
from .package_formatter import PackageFormatter
|
from .package_formatter import PackageFormatter
|
||||||
from .dictionary_formatter import DictionaryFormatter
|
from .dictionary_formatter import DictionaryFormatter
|
||||||
|
from .docstrip_formatter import DocstripFormatter
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'PackageFormatter',
|
'PackageFormatter',
|
||||||
'ClassFormatter',
|
'ClassFormatter',
|
||||||
'DictionaryFormatter'
|
'DictionaryFormatter',
|
||||||
|
'DocstripFormatter'
|
||||||
]
|
]
|
||||||
|
|
39
default_formatters/docstrip_formatter.py
Normal file
39
default_formatters/docstrip_formatter.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, Optional, List
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from PyTeX.formatter import Formatter
|
||||||
|
from PyTeX.utils import ensure_file_integrity
|
||||||
|
from PyTeX.errors import FileNotGeneratedFromDTXFileError, LatexMKError
|
||||||
|
|
||||||
|
|
||||||
|
class DocstripFormatter(Formatter):
|
||||||
|
def __init__(self, name: str):
|
||||||
|
self.name = name
|
||||||
|
self.filename = self.name + '.sty'
|
||||||
|
Formatter.__init__(self)
|
||||||
|
|
||||||
|
def expected_file_name(self) -> str:
|
||||||
|
return self.filename
|
||||||
|
|
||||||
|
def format_file(self, input_path: Path, output_dir: Path,
|
||||||
|
relative_name: Optional[str] = None,
|
||||||
|
last_build_info: Optional[List[Dict]] = None) -> List[str]:
|
||||||
|
ensure_file_integrity(output_dir / self.filename, str(Path(relative_name).parent / self.filename), last_build_info)
|
||||||
|
try:
|
||||||
|
result = subprocess.run(['latexmk', '-gg', '-output-directory=/tmp'], cwd=str(input_path.parent),
|
||||||
|
stdout=subprocess.DEVNULL,
|
||||||
|
stderr=subprocess.DEVNULL
|
||||||
|
)
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
raise LatexMKError(self.filename)
|
||||||
|
if not result:
|
||||||
|
pass
|
||||||
|
sty_file = (Path('/tmp') / input_path.with_suffix('.sty').name)
|
||||||
|
if sty_file.exists():
|
||||||
|
sty = sty_file.read_text()
|
||||||
|
else:
|
||||||
|
raise FileNotGeneratedFromDTXFileError(self.filename, 'style')
|
||||||
|
output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
(output_dir / self.filename).write_text(sty)
|
||||||
|
return [self.filename]
|
|
@ -1,6 +1,6 @@
|
||||||
from .errors import PyTexError, SubmoduleDirtyForbiddenError, ProgrammingError, ExtraHeaderFileNotFoundError, \
|
from .errors import PyTexError, SubmoduleDirtyForbiddenError, ProgrammingError, ExtraHeaderFileNotFoundError, \
|
||||||
UnknownTexVersionError, ModifiedFileInBuildDirectoryError, UnknownFileInBuildDirectoryNoOverwriteError, \
|
UnknownTexVersionError, ModifiedFileInBuildDirectoryError, UnknownFileInBuildDirectoryNoOverwriteError, \
|
||||||
UnknownFileInBuildDirectory
|
UnknownFileInBuildDirectoryError, LatexMKError, FileNotGeneratedFromDTXFileError
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'PyTexError',
|
'PyTexError',
|
||||||
|
@ -10,5 +10,7 @@ __all__ = [
|
||||||
'UnknownTexVersionError',
|
'UnknownTexVersionError',
|
||||||
'ModifiedFileInBuildDirectoryError',
|
'ModifiedFileInBuildDirectoryError',
|
||||||
'UnknownFileInBuildDirectoryNoOverwriteError',
|
'UnknownFileInBuildDirectoryNoOverwriteError',
|
||||||
'UnknownFileInBuildDirectory'
|
'UnknownFileInBuildDirectoryError',
|
||||||
|
'LatexMKError',
|
||||||
|
'FileNotGeneratedFromDTXFileError'
|
||||||
]
|
]
|
||||||
|
|
|
@ -56,10 +56,28 @@ class UnknownFileInBuildDirectoryNoOverwriteError(PyTexError):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class UnknownFileInBuildDirectory(PyTexError):
|
class UnknownFileInBuildDirectoryError(PyTexError):
|
||||||
def __init__(self, filename):
|
def __init__(self, filename):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
f"Detected unknown file {filename} in build directory."
|
f"Detected unknown file {filename} in build directory."
|
||||||
f"PyTeX has no knowledge about this, you should probably"
|
f"PyTeX has no knowledge about this, you should probably"
|
||||||
f"remove it."
|
f"remove it."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class LatexMKError(PyTexError):
|
||||||
|
def __init__(self, filename):
|
||||||
|
super().__init__(
|
||||||
|
f"Running latexmk on file {filename} resulted in an error. "
|
||||||
|
f"Make sure this file is well-formed and an appropriate "
|
||||||
|
f"'.latexmkrc' is present in its directory."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class FileNotGeneratedFromDTXFileError(PyTexError):
|
||||||
|
def __init__(self, filename, type):
|
||||||
|
super().__init__(
|
||||||
|
f"Running latexmk on {filename} did not produce a LaTeX "
|
||||||
|
f"{type} file as needed. I do not know how to build "
|
||||||
|
f"a {type} from this '.dtx' file."
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in a new issue