install-texlive 0.3.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,40 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ tags:
8
+ - '**'
9
+ pull_request:
10
+
11
+ schedule:
12
+ - cron: '0 16 * * 1' # Build every monday, 16:00
13
+
14
+ jobs:
15
+ tests:
16
+ runs-on: ubuntu-latest
17
+ strategy:
18
+ matrix:
19
+ python-version: ["3.9", "3.10", "3.11"]
20
+
21
+ steps:
22
+ - uses: actions/checkout@v3
23
+
24
+ - name: Install
25
+ run: |
26
+ python --version
27
+ pip install .
28
+
29
+ - name: Test TL2022
30
+ run: |
31
+ python -m install_texlive -c="-a" -t 2022 -p $HOME/texlive -f tex-packages.txt -v
32
+ export PATH=$HOME/texlive/2022/bin/x86_64-linux:$PATH
33
+ latexmk -lualatex -halt-on-error -interaction=nonstopmode hello.tex
34
+ latexmk -c hello.tex
35
+
36
+ - name: Test TL current
37
+ run: |
38
+ python -m install_texlive -c="-a" -p $HOME/texlive -v -f tex-packages.txt
39
+ export PATH=$HOME/texlive/2024/bin/x86_64-linux:$PATH
40
+ latexmk -lualatex -halt-on-error -interaction=nonstopmode hello.tex
@@ -0,0 +1,39 @@
1
+ name: Deploy to PyPi
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ jobs:
9
+ pypi-publish:
10
+ name: Upload to PyPI
11
+ runs-on: ubuntu-latest
12
+ environment:
13
+ name: pypi
14
+ url: https://pypi.org/p/install-texlive
15
+ permissions:
16
+ id-token: write
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ # make sure we have version info
21
+ - run: git fetch --tags
22
+
23
+ - name: Set up Python
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: "3.12"
27
+
28
+ - name: Install dependencies
29
+ run: |
30
+ python --version
31
+ pip install -U build
32
+ python -m build
33
+
34
+ - name: Publish package
35
+ uses: pypa/gh-action-pypi-publish@release/v1
36
+ with:
37
+ user: __token__
38
+ password: ${{ secrets.pypi_password }}
39
+
@@ -0,0 +1,271 @@
1
+ _version.py
2
+ # Byte-compiled / optimized / DLL files
3
+ __pycache__/
4
+ *.py[cod]
5
+ *$py.class
6
+
7
+ # C extensions
8
+ *.so
9
+
10
+ # Distribution / packaging
11
+ .Python
12
+ env/
13
+ build/
14
+ develop-eggs/
15
+ dist/
16
+ downloads/
17
+ eggs/
18
+ .eggs/
19
+ lib/
20
+ lib64/
21
+ parts/
22
+ sdist/
23
+ var/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+
28
+ # PyInstaller
29
+ # Usually these files are written by a python script from a template
30
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
31
+ *.manifest
32
+ *.spec
33
+
34
+ # Installer logs
35
+ pip-log.txt
36
+ pip-delete-this-directory.txt
37
+
38
+ # Unit test / coverage reports
39
+ htmlcov/
40
+ .tox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *,cover
47
+ .hypothesis/
48
+
49
+ # Translations
50
+ *.mo
51
+ *.pot
52
+
53
+ # Django stuff:
54
+ *.log
55
+ local_settings.py
56
+
57
+ # Flask stuff:
58
+ instance/
59
+ .webassets-cache
60
+
61
+ # Scrapy stuff:
62
+ .scrapy
63
+
64
+ # Sphinx documentation
65
+ docs/_build/
66
+
67
+ # PyBuilder
68
+ target/
69
+
70
+ # IPython Notebook
71
+ .ipynb_checkpoints
72
+
73
+ # pyenv
74
+ .python-version
75
+
76
+ # celery beat schedule file
77
+ celerybeat-schedule
78
+
79
+ # dotenv
80
+ .env
81
+
82
+ # virtualenv
83
+ venv/
84
+ ENV/
85
+
86
+ # Spyder project settings
87
+ .spyderproject
88
+
89
+ # Rope project settings
90
+ .ropeproject
91
+
92
+ ## Core latex/pdflatex auxiliary files:
93
+ *.aux
94
+ *.lof
95
+ *.log
96
+ *.lot
97
+ *.fls
98
+ *.out
99
+ *.toc
100
+ *.fmt
101
+ *.fot
102
+ *.cb
103
+ *.cb2
104
+
105
+ ## Intermediate documents:
106
+ *.dvi
107
+ *-converted-to.*
108
+ # these rules might exclude image files for figures etc.
109
+ # *.ps
110
+ # *.eps
111
+ # *.pdf
112
+
113
+ ## Bibliography auxiliary files (bibtex/biblatex/biber):
114
+ *.bbl
115
+ *.bcf
116
+ *.blg
117
+ *-blx.aux
118
+ *-blx.bib
119
+ *.brf
120
+ *.run.xml
121
+
122
+ ## Build tool auxiliary files:
123
+ *.fdb_latexmk
124
+ *.synctex
125
+ *.synctex.gz
126
+ *.synctex.gz(busy)
127
+ *.pdfsync
128
+
129
+ ## Auxiliary and intermediate files from other packages:
130
+ # algorithms
131
+ *.alg
132
+ *.loa
133
+
134
+ # achemso
135
+ acs-*.bib
136
+
137
+ # amsthm
138
+ *.thm
139
+
140
+ # beamer
141
+ *.nav
142
+ *.snm
143
+ *.vrb
144
+
145
+ # cprotect
146
+ *.cpt
147
+
148
+ # fixme
149
+ *.lox
150
+
151
+ #(r)(e)ledmac/(r)(e)ledpar
152
+ *.end
153
+ *.?end
154
+ *.[1-9]
155
+ *.[1-9][0-9]
156
+ *.[1-9][0-9][0-9]
157
+ *.[1-9]R
158
+ *.[1-9][0-9]R
159
+ *.[1-9][0-9][0-9]R
160
+ *.eledsec[1-9]
161
+ *.eledsec[1-9]R
162
+ *.eledsec[1-9][0-9]
163
+ *.eledsec[1-9][0-9]R
164
+ *.eledsec[1-9][0-9][0-9]
165
+ *.eledsec[1-9][0-9][0-9]R
166
+
167
+ # glossaries
168
+ *.acn
169
+ *.acr
170
+ *.glg
171
+ *.glo
172
+ *.gls
173
+ *.glsdefs
174
+
175
+ # gnuplottex
176
+ *-gnuplottex-*
177
+
178
+ # hyperref
179
+ *.brf
180
+
181
+ # knitr
182
+ *-concordance.tex
183
+ # TODO Comment the next line if you want to keep your tikz graphics files
184
+ *.tikz
185
+ *-tikzDictionary
186
+
187
+ # listings
188
+ *.lol
189
+
190
+ # makeidx
191
+ *.idx
192
+ *.ilg
193
+ *.ind
194
+ *.ist
195
+
196
+ # minitoc
197
+ *.maf
198
+ *.mlf
199
+ *.mlt
200
+ *.mtc
201
+ *.mtc[0-9]
202
+ *.mtc[1-9][0-9]
203
+
204
+ # minted
205
+ _minted*
206
+ *.pyg
207
+
208
+ # morewrites
209
+ *.mw
210
+
211
+ # mylatexformat
212
+ *.fmt
213
+
214
+ # nomencl
215
+ *.nlo
216
+
217
+ # sagetex
218
+ *.sagetex.sage
219
+ *.sagetex.py
220
+ *.sagetex.scmd
221
+
222
+ # sympy
223
+ *.sout
224
+ *.sympy
225
+ sympy-plots-for-*.tex/
226
+
227
+ # pdfcomment
228
+ *.upa
229
+ *.upb
230
+
231
+ # pythontex
232
+ *.pytxcode
233
+ pythontex-files-*/
234
+
235
+ # thmtools
236
+ *.loe
237
+
238
+ # TikZ & PGF
239
+ *.dpth
240
+ *.md5
241
+ *.auxlock
242
+
243
+ # todonotes
244
+ *.tdo
245
+
246
+ # xindy
247
+ *.xdy
248
+
249
+ # xypic precompiled matrices
250
+ *.xyc
251
+
252
+ # endfloat
253
+ *.ttt
254
+ *.fff
255
+
256
+ # Latexian
257
+ TSWLatexianTemp*
258
+
259
+ ## Editors:
260
+ # WinEdt
261
+ *.bak
262
+ *.sav
263
+
264
+ # Texpad
265
+ .texpadtmp
266
+
267
+ # Kile
268
+ *.backup
269
+
270
+ # KBibTeX
271
+ *~[0-9]*
@@ -0,0 +1 @@
1
+ Maximilian Linhoff <maximilian.linhoff@tu-dortmund.de> <maximilian.noethe@tu-dortmund.de>
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Maximilian Nöthe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,75 @@
1
+ Metadata-Version: 2.1
2
+ Name: install-texlive
3
+ Version: 0.3.6
4
+ Summary: Install texlive without human interaction in the process
5
+ Author-email: Maximilian Linhoff <maximilian.linhoff@tu-dortmund.de>
6
+ License: MIT License
7
+ Project-URL: repository, http://github.com/maxnoe/texlive-batch-installation
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Operating System :: POSIX :: Linux
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Topic :: Text Processing :: Markup :: LaTeX
14
+ Requires-Python: >=3.8
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: pexpect
18
+ Requires-Dist: requests
19
+
20
+ # texlive batch install [![CI](https://github.com/maxnoe/texlive-batch-installation/actions/workflows/ci.yml/badge.svg)](https://github.com/maxnoe/texlive-batch-installation/actions/workflows/ci.yml)
21
+
22
+ The TeX Live installer does not allow for interaction-less installation.
23
+
24
+ This is the reason why I created this project using pexpect to talk to the `install-tl`
25
+ script.
26
+
27
+ Usage:
28
+ ```
29
+ usage: install_texlive [-h] [-v] [-t VERSION] [--install-tl INSTALL_TL] [-k]
30
+ [-p PREFIX] [-c COLLECTIONS]
31
+ [-s {f,g,d,i,k,c,e,h,b,j,a}] [-u] [-i INSTALL]
32
+ [--source] [--docs]
33
+
34
+ optional arguments:
35
+ -h, --help show this help message and exit
36
+ -v, --verbose Create more verbose output
37
+ -t VERSION, --texlive-version VERSION
38
+ TeX Live version to install
39
+ --install-tl INSTALL_TL
40
+ Path to the install-tl script. If not given, TeX Live
41
+ will be downloaded.
42
+ -k, --keep-config If an existing installation is found, keep its config
43
+ -p PREFIX, --prefix PREFIX
44
+ Installation prefix, equivalent to setting
45
+ TEXLIVE_INSTALL_PREFIX
46
+ -c COLLECTIONS, --collections COLLECTIONS
47
+ The TeX Live package collections to install. E.g. -a
48
+ to deselect all and only install the absolute basic
49
+ TeX packages
50
+ -s {f,g,d,i,k,c,e,h,b,j,a}, --scheme {f,g,d,i,k,c,e,h,b,j,a}
51
+ The TeX Live scheme to install. Default is "full"
52
+ -u, --update Update TeX Live after installation is finished
53
+ -i INSTALL, --install INSTALL
54
+ Additional packages to install after the main
55
+ Installation has finished
56
+ --source Install the source tree
57
+ --docs Install the docs tree
58
+ ```
59
+
60
+
61
+ For a minimal installation (e.g. for CI jobs building documents), it is recommended to
62
+ only install the bare minimum selection of package collections: `-c "-a"` and then
63
+ have a file `tex-packages.txt` with the actually needed packages to compile the document:
64
+
65
+ ```
66
+ $ python -m install_texlive -p .texlive -t 2022 --collections='-a' --package-file tex-packages.txt --update
67
+ ```
68
+
69
+ To find out which package provides which style file (e.g. to find out which CTAN package provides `scrartcl.cls`), this command is helpful:
70
+
71
+ ```
72
+ $ tlmgr search --global --file '/scrartcl.cls'
73
+ koma-script:
74
+ texmf-dist/tex/latex/koma-script/scrartcl.cls
75
+ ```
@@ -0,0 +1,56 @@
1
+ # texlive batch install [![CI](https://github.com/maxnoe/texlive-batch-installation/actions/workflows/ci.yml/badge.svg)](https://github.com/maxnoe/texlive-batch-installation/actions/workflows/ci.yml)
2
+
3
+ The TeX Live installer does not allow for interaction-less installation.
4
+
5
+ This is the reason why I created this project using pexpect to talk to the `install-tl`
6
+ script.
7
+
8
+ Usage:
9
+ ```
10
+ usage: install_texlive [-h] [-v] [-t VERSION] [--install-tl INSTALL_TL] [-k]
11
+ [-p PREFIX] [-c COLLECTIONS]
12
+ [-s {f,g,d,i,k,c,e,h,b,j,a}] [-u] [-i INSTALL]
13
+ [--source] [--docs]
14
+
15
+ optional arguments:
16
+ -h, --help show this help message and exit
17
+ -v, --verbose Create more verbose output
18
+ -t VERSION, --texlive-version VERSION
19
+ TeX Live version to install
20
+ --install-tl INSTALL_TL
21
+ Path to the install-tl script. If not given, TeX Live
22
+ will be downloaded.
23
+ -k, --keep-config If an existing installation is found, keep its config
24
+ -p PREFIX, --prefix PREFIX
25
+ Installation prefix, equivalent to setting
26
+ TEXLIVE_INSTALL_PREFIX
27
+ -c COLLECTIONS, --collections COLLECTIONS
28
+ The TeX Live package collections to install. E.g. -a
29
+ to deselect all and only install the absolute basic
30
+ TeX packages
31
+ -s {f,g,d,i,k,c,e,h,b,j,a}, --scheme {f,g,d,i,k,c,e,h,b,j,a}
32
+ The TeX Live scheme to install. Default is "full"
33
+ -u, --update Update TeX Live after installation is finished
34
+ -i INSTALL, --install INSTALL
35
+ Additional packages to install after the main
36
+ Installation has finished
37
+ --source Install the source tree
38
+ --docs Install the docs tree
39
+ ```
40
+
41
+
42
+ For a minimal installation (e.g. for CI jobs building documents), it is recommended to
43
+ only install the bare minimum selection of package collections: `-c "-a"` and then
44
+ have a file `tex-packages.txt` with the actually needed packages to compile the document:
45
+
46
+ ```
47
+ $ python -m install_texlive -p .texlive -t 2022 --collections='-a' --package-file tex-packages.txt --update
48
+ ```
49
+
50
+ To find out which package provides which style file (e.g. to find out which CTAN package provides `scrartcl.cls`), this command is helpful:
51
+
52
+ ```
53
+ $ tlmgr search --global --file '/scrartcl.cls'
54
+ koma-script:
55
+ texmf-dist/tex/latex/koma-script/scrartcl.cls
56
+ ```
@@ -0,0 +1,9 @@
1
+ \documentclass{scrartcl}
2
+
3
+ \usepackage{fontspec}
4
+
5
+ \begin{document}
6
+ \section{Hello World}
7
+ Hello, World!
8
+ \end{document}
9
+
@@ -0,0 +1,107 @@
1
+ import logging
2
+ import os
3
+ import pexpect
4
+ import re
5
+ import requests
6
+ from io import BytesIO
7
+ import tarfile
8
+ from functools import lru_cache
9
+ from io import StringIO
10
+ from html.parser import HTMLParser
11
+ from ._version import __version__, __version_tuple__
12
+
13
+
14
+ __all__ = [
15
+ "__version__",
16
+ "__version_tuple__",
17
+ "command",
18
+ "download",
19
+ "get_mirror",
20
+ "get_size",
21
+ "is_current",
22
+ "URL",
23
+ "OLDURL",
24
+ ]
25
+
26
+
27
+ log = logging.getLogger(__name__)
28
+
29
+ URL = 'https://mirror.ctan.org/systems/texlive/tlnet/'
30
+ OLDURL = 'https://ftp.tu-chemnitz.de/pub/tug/historic/systems/texlive/{v}/tlnet-final/'
31
+
32
+
33
+ class GetText(HTMLParser):
34
+ """Only extract text of html page"""
35
+
36
+ def __init__(self):
37
+ super().__init__()
38
+ self._text = StringIO()
39
+
40
+ def handle_data(self, d):
41
+ self._text.write(d)
42
+
43
+ @property
44
+ def text(self):
45
+ return self._text.getvalue()
46
+
47
+
48
+ @lru_cache
49
+ def is_current(version):
50
+ r = requests.get('https://tug.org/texlive/')
51
+ r.raise_for_status()
52
+
53
+ parser = GetText()
54
+ parser.feed(r.text)
55
+
56
+ m = re.search(r'Current release: TeX Live ([0-9]{4})', parser.text)
57
+ if not m:
58
+ raise ValueError('Could not determine current TeX Live version')
59
+
60
+ current_version = int(m.groups()[0])
61
+ log.debug('Current version of TeX Live is {}'.format(current_version))
62
+ return current_version == version
63
+
64
+
65
+ def get_mirror():
66
+ """Get a CTAN mirror"""
67
+ r = requests.get(URL, allow_redirects=False)
68
+ r.raise_for_status()
69
+ return r.headers["Location"]
70
+
71
+
72
+ def download(version=None, outdir='.', url=None):
73
+ os.makedirs(outdir, exist_ok=True)
74
+
75
+ if version is None or is_current(version):
76
+ url = url or URL
77
+ url = url.rstrip("/") + '/install-tl-unx.tar.gz'
78
+ else:
79
+ url = OLDURL.format(v=version) + 'install-tl-unx.tar.gz'
80
+
81
+ log.debug('Downloading from {}'.format(url))
82
+
83
+ ret = requests.get(url)
84
+ ret.raise_for_status()
85
+
86
+ tar = tarfile.open(fileobj=BytesIO(ret.content), mode='r:gz')
87
+ tar.extractall(outdir)
88
+
89
+
90
+ def command(process, pattern, send, **kwargs):
91
+ process.expect(pattern, **kwargs)
92
+ process.sendline(send)
93
+
94
+
95
+ def get_size(process):
96
+ timeout = process.timeout
97
+ process.timeout = 1
98
+ lines = ''
99
+ try:
100
+ while True:
101
+ lines += process.readline().decode()
102
+ except pexpect.TIMEOUT:
103
+ pass
104
+
105
+ size = re.findall(r'disk space required: ([0-9]+ MB)', lines)[-1]
106
+ process.timeout = timeout
107
+ return size
@@ -0,0 +1,153 @@
1
+ import pexpect
2
+ from glob import glob
3
+ import os
4
+ import sys
5
+ import logging
6
+ import tempfile
7
+ import re
8
+ import subprocess as sp
9
+
10
+ from . import command, download, OLDURL, get_size, is_current, get_mirror
11
+ from .parser import parser
12
+
13
+
14
+ logging.basicConfig(level=logging.INFO)
15
+ log = logging.getLogger('install_texlive')
16
+
17
+ timeout = 30
18
+
19
+
20
+ def main():
21
+ args = parser.parse_args()
22
+
23
+ if args.verbose:
24
+ log.level = logging.DEBUG
25
+
26
+ if args.prefix:
27
+ args.prefix = os.path.abspath(args.prefix)
28
+ os.environ['TEXLIVE_INSTALL_PREFIX'] = args.prefix
29
+ os.makedirs(args.prefix, exist_ok=True)
30
+
31
+ os.environ["TEXLIVE_INSTALL_ENV_NOCHECK"] = "1"
32
+ log.info('Installing texlive to {}'.format(args.prefix or '/usr/local/texlive'))
33
+
34
+ if args.repository is None:
35
+ if args.version is None or is_current(args.version):
36
+ args.repository = get_mirror()
37
+ else:
38
+ args.repository = OLDURL.format(v=args.version)
39
+
40
+ if args.install_tl:
41
+ install_script = args.install_tl
42
+ cmd = install_script
43
+ else:
44
+ log.info("Using repository: %s", args.repository)
45
+ directory = os.path.join(
46
+ tempfile.gettempdir(), 'texlive-{}'.format(args.version or 'current')
47
+ )
48
+ download(version=args.version, outdir=directory, url=args.repository)
49
+ install_script = glob(os.path.join(directory, 'install-tl-*/install-tl'))[-1]
50
+ cmd = install_script + ' --repository={}'.format(args.repository)
51
+
52
+ log.info(cmd)
53
+
54
+ tl = pexpect.spawn(cmd, timeout=timeout)
55
+
56
+ try:
57
+ command(tl, 'installation.profile', 'N', timeout=5)
58
+ except pexpect.TIMEOUT:
59
+ pass
60
+
61
+ try:
62
+ command(tl, 'Import settings', 'y' if args.keep_config else 'n', timeout=5)
63
+ except pexpect.TIMEOUT:
64
+ log.info('No previous installation found')
65
+
66
+ try:
67
+ if args.scheme:
68
+ command(tl, 'Enter command:', 'S', timeout=timeout)
69
+ command(tl, 'Enter letter', args.scheme, timeout=timeout)
70
+ command(tl, 'Enter letter', 'R', timeout=timeout)
71
+
72
+ if args.collections:
73
+ command(tl, 'Enter command:', 'C', timeout=timeout)
74
+ command(tl, 'Enter letter', args.collections, timeout=timeout)
75
+ command(tl, 'Enter letter', 'R', timeout=timeout)
76
+
77
+ if not args.docs:
78
+ command(tl, 'Enter command:', 'O', timeout=timeout)
79
+ command(tl, 'Enter command:', 'D', timeout=timeout)
80
+ command(tl, 'Enter command:', 'R', timeout=timeout)
81
+
82
+ if not args.source:
83
+ command(tl, 'Enter command:', 'O', timeout=timeout)
84
+ command(tl, 'Enter command:', 'S', timeout=timeout)
85
+ command(tl, 'Enter command:', 'R', timeout=timeout)
86
+
87
+ log.info('Installation size will be {}'.format(get_size(tl)))
88
+ log.info('Starting installation')
89
+ command(tl, 'Enter command:', 'I', timeout=timeout)
90
+ except pexpect.TIMEOUT:
91
+ log.error('Something went wrong')
92
+ sys.exit(1)
93
+
94
+ lines = ''
95
+ try:
96
+ while not tl.terminated:
97
+ line = tl.readline().decode()
98
+ log.debug(line.strip())
99
+ lines += line
100
+ except pexpect.EOF:
101
+ log.error('EOF')
102
+
103
+ tl.close()
104
+ if tl.exitstatus == 0:
105
+ log.info('Installation installed succesfully')
106
+ else:
107
+ log.error('Installation did not finish succesfully')
108
+ sys.exit(tl.exitstatus)
109
+
110
+ bindir = re.findall(r'Most importantly, add\s+(.*)\s+to your PATH', lines)[0].strip()
111
+ version = re.findall(r'20[0-9][0-9]', bindir)[0]
112
+ env = os.environ
113
+ env['PATH'] = os.path.abspath(bindir) + ':' + env['PATH']
114
+
115
+ repo = args.repository
116
+ if args.version is not None and not is_current(args.version):
117
+ repo = OLDURL.format(v=version)
118
+
119
+ if repo is not None:
120
+ log.info("Setting repository to %s", repo)
121
+ sp.run(
122
+ ['tlmgr', 'option', 'repository', repo],
123
+ env=env,
124
+ check=True,
125
+ )
126
+
127
+ if args.update:
128
+ log.info('Start updating')
129
+ sp.run(
130
+ ['tlmgr', 'update', '--self', '--all', '--reinstall-forcibly-removed'],
131
+ env=env,
132
+ check=True,
133
+ )
134
+ log.info('Finished')
135
+
136
+ additional_packages = []
137
+ if args.install:
138
+ additional_packages.extend(args.install.split(','))
139
+
140
+ if args.package_file:
141
+ with open(args.package_file, 'r') as f:
142
+ additional_packages.extend(f.read().splitlines())
143
+
144
+ if additional_packages:
145
+ log.info('Start installing additional packages')
146
+ # tlmgr must always be up to date to install packages
147
+ sp.run(['tlmgr', 'update', '--self'], env=env, check=True)
148
+ sp.run(['tlmgr', 'install', *additional_packages], env=env, check=True)
149
+ log.info('Finished')
150
+
151
+
152
+ if __name__ == '__main__':
153
+ main()
@@ -0,0 +1,16 @@
1
+ # file generated by setuptools_scm
2
+ # don't change, don't track in version control
3
+ TYPE_CHECKING = False
4
+ if TYPE_CHECKING:
5
+ from typing import Tuple, Union
6
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
7
+ else:
8
+ VERSION_TUPLE = object
9
+
10
+ version: str
11
+ __version__: str
12
+ __version_tuple__: VERSION_TUPLE
13
+ version_tuple: VERSION_TUPLE
14
+
15
+ __version__ = version = '0.3.6'
16
+ __version_tuple__ = version_tuple = (0, 3, 6)
@@ -0,0 +1,73 @@
1
+ from argparse import ArgumentParser
2
+ from . import __version__
3
+
4
+ parser = ArgumentParser(prog='install_texlive')
5
+
6
+ parser.add_argument('-V', '--version', action='version', version=__version__)
7
+
8
+ parser.add_argument(
9
+ '-v', '--verbose', action='store_true', help='Create more verbose output'
10
+ )
11
+
12
+ parser.add_argument(
13
+ '-t', '--texlive-version', dest='version', type=int,
14
+ help='TeX Live version to install',
15
+ )
16
+
17
+ parser.add_argument(
18
+ '--install-tl',
19
+ help='Path to the install-tl script. If not given, TeX Live will be downloaded.',
20
+ )
21
+
22
+ parser.add_argument(
23
+ '-k', '--keep-config', action='store_true',
24
+ help='If an existing installation is found, keep its config',
25
+ )
26
+
27
+ parser.add_argument(
28
+ '-p', '--prefix',
29
+ help='Installation prefix, equivalent to setting TEXLIVE_INSTALL_PREFIX'
30
+ )
31
+
32
+ parser.add_argument(
33
+ '-c', '--collections',
34
+ help=(
35
+ 'The TeX Live package collections to install.'
36
+ ' E.g. -a to deselect all and only install the absolute basic TeX packages'
37
+ )
38
+ )
39
+
40
+ parser.add_argument(
41
+ '-s', '--scheme', choices=set('abcdefghijk'),
42
+ help='The TeX Live scheme to install. Default is "full"'
43
+ )
44
+
45
+ parser.add_argument(
46
+ '-u', '--update', action='store_true',
47
+ help='Update TeX Live after installation is finished'
48
+ )
49
+
50
+ parser.add_argument(
51
+ '-i', '--install',
52
+ help='Additional packages to install after the main Installation has finished as comma separated list'
53
+ )
54
+
55
+ parser.add_argument(
56
+ '-f', '--package-file',
57
+ help='A file with one package per line to be install after the main installation has finished'
58
+ )
59
+
60
+ parser.add_argument(
61
+ '--source', action='store_true',
62
+ help='Install the source tree',
63
+ )
64
+
65
+ parser.add_argument(
66
+ '--docs', action='store_true',
67
+ help='Install the docs tree',
68
+ )
69
+
70
+ parser.add_argument(
71
+ "-r", "--repository",
72
+ help="If given, set ctan mirror to this URL.",
73
+ )
@@ -0,0 +1,75 @@
1
+ Metadata-Version: 2.1
2
+ Name: install-texlive
3
+ Version: 0.3.6
4
+ Summary: Install texlive without human interaction in the process
5
+ Author-email: Maximilian Linhoff <maximilian.linhoff@tu-dortmund.de>
6
+ License: MIT License
7
+ Project-URL: repository, http://github.com/maxnoe/texlive-batch-installation
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Operating System :: POSIX :: Linux
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Topic :: Text Processing :: Markup :: LaTeX
14
+ Requires-Python: >=3.8
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: pexpect
18
+ Requires-Dist: requests
19
+
20
+ # texlive batch install [![CI](https://github.com/maxnoe/texlive-batch-installation/actions/workflows/ci.yml/badge.svg)](https://github.com/maxnoe/texlive-batch-installation/actions/workflows/ci.yml)
21
+
22
+ The TeX Live installer does not allow for interaction-less installation.
23
+
24
+ This is the reason why I created this project using pexpect to talk to the `install-tl`
25
+ script.
26
+
27
+ Usage:
28
+ ```
29
+ usage: install_texlive [-h] [-v] [-t VERSION] [--install-tl INSTALL_TL] [-k]
30
+ [-p PREFIX] [-c COLLECTIONS]
31
+ [-s {f,g,d,i,k,c,e,h,b,j,a}] [-u] [-i INSTALL]
32
+ [--source] [--docs]
33
+
34
+ optional arguments:
35
+ -h, --help show this help message and exit
36
+ -v, --verbose Create more verbose output
37
+ -t VERSION, --texlive-version VERSION
38
+ TeX Live version to install
39
+ --install-tl INSTALL_TL
40
+ Path to the install-tl script. If not given, TeX Live
41
+ will be downloaded.
42
+ -k, --keep-config If an existing installation is found, keep its config
43
+ -p PREFIX, --prefix PREFIX
44
+ Installation prefix, equivalent to setting
45
+ TEXLIVE_INSTALL_PREFIX
46
+ -c COLLECTIONS, --collections COLLECTIONS
47
+ The TeX Live package collections to install. E.g. -a
48
+ to deselect all and only install the absolute basic
49
+ TeX packages
50
+ -s {f,g,d,i,k,c,e,h,b,j,a}, --scheme {f,g,d,i,k,c,e,h,b,j,a}
51
+ The TeX Live scheme to install. Default is "full"
52
+ -u, --update Update TeX Live after installation is finished
53
+ -i INSTALL, --install INSTALL
54
+ Additional packages to install after the main
55
+ Installation has finished
56
+ --source Install the source tree
57
+ --docs Install the docs tree
58
+ ```
59
+
60
+
61
+ For a minimal installation (e.g. for CI jobs building documents), it is recommended to
62
+ only install the bare minimum selection of package collections: `-c "-a"` and then
63
+ have a file `tex-packages.txt` with the actually needed packages to compile the document:
64
+
65
+ ```
66
+ $ python -m install_texlive -p .texlive -t 2022 --collections='-a' --package-file tex-packages.txt --update
67
+ ```
68
+
69
+ To find out which package provides which style file (e.g. to find out which CTAN package provides `scrartcl.cls`), this command is helpful:
70
+
71
+ ```
72
+ $ tlmgr search --global --file '/scrartcl.cls'
73
+ koma-script:
74
+ texmf-dist/tex/latex/koma-script/scrartcl.cls
75
+ ```
@@ -0,0 +1,20 @@
1
+ .gitignore
2
+ .mailmap
3
+ LICENSE
4
+ README.md
5
+ hello.tex
6
+ pyproject.toml
7
+ setup.py
8
+ tex-packages.txt
9
+ .github/workflows/ci.yml
10
+ .github/workflows/pypi.yml
11
+ install_texlive/__init__.py
12
+ install_texlive/__main__.py
13
+ install_texlive/_version.py
14
+ install_texlive/parser.py
15
+ install_texlive.egg-info/PKG-INFO
16
+ install_texlive.egg-info/SOURCES.txt
17
+ install_texlive.egg-info/dependency_links.txt
18
+ install_texlive.egg-info/entry_points.txt
19
+ install_texlive.egg-info/requires.txt
20
+ install_texlive.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ install_texlive = install_texlive.__main__:main
@@ -0,0 +1,2 @@
1
+ pexpect
2
+ requests
@@ -0,0 +1 @@
1
+ install_texlive
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["setuptools>=60", "setuptools-scm>=8.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "install-texlive"
7
+ description = "Install texlive without human interaction in the process"
8
+ license = {text = "MIT License"}
9
+ authors = [
10
+ { name = "Maximilian Linhoff", email = "maximilian.linhoff@tu-dortmund.de" },
11
+ ]
12
+ requires-python = ">=3.8"
13
+ dependencies = [
14
+ "pexpect",
15
+ "requests",
16
+ ]
17
+ readme = "README.md"
18
+ dynamic = ["version"]
19
+ classifiers = [
20
+ "License :: OSI Approved :: MIT License",
21
+ "Development Status :: 5 - Production/Stable",
22
+ "Operating System :: POSIX :: Linux",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3 :: Only",
25
+ "Topic :: Text Processing :: Markup :: LaTeX",
26
+ ]
27
+
28
+ [project.urls]
29
+ repository = "http://github.com/maxnoe/texlive-batch-installation"
30
+
31
+ [project.scripts]
32
+ install_texlive = "install_texlive.__main__:main"
33
+
34
+ [tool.setuptools_scm]
35
+ version_file = "install_texlive/_version.py"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,2 @@
1
+ from setuptools import setup
2
+ setup()
@@ -0,0 +1,6 @@
1
+ luatex
2
+ latex
3
+ latex-bin
4
+ fontspec
5
+ latexmk
6
+ koma-script