1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Install PythonTeX
This installation script is written to work with TeX Live and MiKTeX. Note
that PythonTeX is included in TeX Live 2013 and later, and may be installed
via the package manager. Thus, this installation script is only needed with
TeX Live when you wish to install the latest version. PythonTeX is not
currently available via the MiKTeX package manager.
The script will automatically overwrite (and thus update) all previously
installed PythonTeX files in the designated installation location. When
Kpathsea is available, files may be installed in TEXMFDIST, TEXMFLOCAL,
TEXMFHOME, or a manually specified location. Otherwise, the installation
location must be specified manually. Installing in TEXMFDIST is useful
under TeX Live if you want to install PythonTeX and then update it in the
future via the package manager.
The `mktexlsr` (TeX Live) or `initexmf --update-fndb` (MiKTeX) command is
executed at the end of the script, to make the system aware of any new files.
Under TeX Live, the script attempts to create a binary wrapper (Windows) or
symlink (Linux and OS X) for launching the main PythonTeX scripts,
`pythontex*.py` and `depythontex*.py`. Under MiKTeX, it attempts to create
a batch file in `miktex/bin`.
Copyright (c) 2012-2014, Geoffrey M. Poore
All rights reserved.
Licensed under the BSD 3-Clause License:
http://www.opensource.org/licenses/BSD-3-Clause
'''
# Imports
import sys
import platform
from os import path, mkdir, makedirs
if platform.system() != 'Windows':
# Only create symlinks if not under Windows
# (os.symlink doesn't exist under Windows)
from os import symlink, chmod, unlink
from subprocess import call, check_call, check_output
from shutil import copy
import textwrap
# We need a version of input that works under both Python 2 and 3
try:
input = raw_input
except:
pass
# Print startup messages and notices
print('Preparing to install PythonTeX')
if platform.system() != 'Windows':
message = '''
You may need to run this script with elevated permissions
and/or specify the environment. For example, you may need
"sudo env PATH=$PATH". That is typically necessary when your
system includes a TeX distribution, and you have manually
installed another distribution (common with Ubuntu etc.). If
the installation path you want is not automatically detected,
it may indicate a permissions issue.
'''
print(textwrap.dedent(message))
# Attempt to detect the TeX distribution
try:
if sys.version_info.major == 2:
texout = check_output(['latex', '--version'])
else:
texout = check_output(['latex', '--version']).decode('utf-8')
except:
sys.exit('Could not retrieve latex info when running "latex --version"')
if 'TeX Live' in texout:
detected_texdist = True
texlive = True
miktex = False
elif platform.system() == 'Windows' and 'MiKTeX' in texout:
detected_texdist = True
texlive = False
miktex = True
else:
detected_texdist = False
texlive = False
miktex = False
# Make sure all necessary files are present
# The pythontex_gallery and pythontex_quickstart are optional; we
# check for them when installing doc, and install if available
needed_files = ['pythontex.py', 'pythontex2.py', 'pythontex3.py',
'pythontex_engines.py', 'pythontex_utils.py',
'depythontex.py', 'depythontex2.py', 'depythontex3.py',
'pythontex.sty', 'pythontex.ins', 'pythontex.dtx',
'pythontex.pdf', 'README',
'syncpdb.py']
missing_files = False
# Print a list of all files that are missing, and exit if any are
for eachfile in needed_files:
if not path.exists(eachfile):
print('Could not find file ' + eachfile)
missing_files = True
if missing_files:
sys.exit('Exiting due to missing files.')
# Retrieve the location of valid TeX trees
if sys.version_info[0] == 2:
try:
texmf_dist = check_output(['kpsewhich', '-var-value', 'TEXMFDIST']).rstrip('\r\n')
except:
texmf_dist = None
try:
texmf_local = check_output(['kpsewhich', '-var-value', 'TEXMFLOCAL']).rstrip('\r\n')
except:
texmf_local = None
try:
texmf_home = check_output(['kpsewhich', '-var-value', 'TEXMFHOME']).rstrip('\r\n')
except:
texmf_home = None
else:
try:
texmf_dist = check_output(['kpsewhich', '-var-value', 'TEXMFDIST']).decode('utf-8').rstrip('\r\n')
except:
texmf_dist = None
try:
texmf_local = check_output(['kpsewhich', '-var-value', 'TEXMFLOCAL']).decode('utf-8').rstrip('\r\n')
except:
texmf_local = None
try:
texmf_home = check_output(['kpsewhich', '-var-value', 'TEXMFHOME']).decode('utf-8').rstrip('\r\n')
except:
texmf_home = None
# Get installation location from user
texmf_vars = [texmf_dist, texmf_local, texmf_home]
message = '''
Choose an installation location.
TEXMFDIST is a good choice if you want to update PythonTeX
in the future using your TeX distribution's package manager
(assuming that is supported).
1. TEXMFDIST
{0}
2. TEXMFLOCAL
{1}
3. TEXMFHOME
{2}
4. Manual location
5. Exit without installing
'''.format(*[x if x else '<INVALID>' for x in texmf_vars])
if any(texmf_vars):
path_choice = ''
while (path_choice not in ('1', '2', '3', '4', '5') or
(int(path_choice) <= 3 and not texmf_vars[int(path_choice)-1])):
print(textwrap.dedent(message))
path_choice = input('Installation location (number): ')
if path_choice == '':
sys.exit()
if path_choice == '1':
texmf_path = texmf_dist
elif path_choice == '2':
texmf_path = texmf_local
elif path_choice == '3':
texmf_path = texmf_home
elif path_choice == '4':
texmf_path = input('Enter a path:\n')
if texmf_path == '':
sys.exit()
if platform.system() == 'Windows':
if 'texlive' in texmf_path.lower():
detected_texdist = True
texlive = True
miktex = False
elif 'miktex' in texmf_path.lower():
detected_texdist = True
texlive = False
miktex = True
else:
sys.exit()
else:
print('Failed to detect possible installation locations automatically.')
print('TEXMF paths could not be located with kpsewhich.')
texmf_path = input('Plese enter an installation path, or press "Enter" to exit:\n')
if texmf_path == '':
sys.exit()
# Make sure path slashes are compatible with the operating system
# Kpathsea returns forward slashes, but Windows needs back slashes
texmf_path = path.expandvars(path.expanduser(path.normcase(texmf_path)))
# Check to make sure the path is valid
# This should only be needed for manual input, but it's a good check
if not path.isdir(texmf_path):
sys.exit('Invalid installation path. Exiting.')
# Now check that all other needed paths are present
if path_choice != '2':
doc_path = path.join(texmf_path, 'doc', 'latex')
package_path = path.join(texmf_path, 'tex', 'latex')
scripts_path = path.join(texmf_path, 'scripts')
source_path = path.join(texmf_path, 'source', 'latex')
else:
doc_path = path.join(texmf_path, 'doc', 'latex', 'local')
package_path = path.join(texmf_path, 'tex', 'latex', 'local')
scripts_path = path.join(texmf_path, 'scripts', 'local')
source_path = path.join(texmf_path, 'source', 'latex', 'local')
# May need to create some local directories
make_paths = False
for eachpath in [doc_path, package_path, scripts_path, source_path]:
if not path.exists(eachpath):
if make_paths:
makedirs(eachpath)
print(' * Created ' + eachpath)
else:
choice = ''
while choice not in ('y', 'n'):
choice = input('Some directories do not exist. Create them? [y/n] ')
if choice == '':
sys.exit()
if choice == 'y':
make_paths = True
try:
makedirs(eachpath)
print(' * Created ' + eachpath)
except (OSError, IOError) as e:
if e.errno == 13:
print('\nInsufficient permission to install PythonTeX')
if platform.system() == 'Windows':
message = '''
You may need to run the installer as "administrator".
This may be done under Vista and later by right-clicking on
pythontex_install.bat, then selecting "Run as administrator".
Or you can open a command prompt as administrator
(Start, Programs, Accessories, right-click Command Prompt,
Run as administrator), change to the directory in which
pythontex_install.py is located, and run
"python pythontex_install.py".
'''
print(textwrap.dedent(message))
call(['pause'], shell=True)
else:
print('(For example, you may need "sudo", or possibly "sudo env PATH=$PATH")\n')
sys.exit(1)
else:
raise
else:
message = '''
Paths were not created. The following will be needed.
* {0}
* {1}
* {2}
* {3}
Exiting.
'''.format(doc_path, package_path, scripts_path, source_path)
print(textwrap.dedent(message))
sys.exit()
# Modify the paths by adding the pythontex directory, which will be created
doc_path = path.join(doc_path, 'pythontex')
package_path = path.join(package_path, 'pythontex')
scripts_path = path.join(scripts_path, 'pythontex')
source_path = path.join(source_path, 'pythontex')
# Install files
# Use a try/except in case elevated permissions are needed (Linux and OS X)
print('\nPythonTeX will be installed in \n ' + texmf_path)
try:
# Install docs
if not path.exists(doc_path):
mkdir(doc_path)
copy('pythontex.pdf', doc_path)
copy('README', doc_path)
for doc in ('pythontex_quickstart.tex', 'pythontex_quickstart.pdf',
'pythontex_gallery.tex', 'pythontex_gallery.pdf'):
if path.isfile(doc):
copy(doc, doc_path)
else:
doc = path.join('..', doc.rsplit('.', 1)[0], doc)
if path.isfile(doc):
copy(doc, doc_path)
# Install package
if not path.exists(package_path):
mkdir(package_path)
copy('pythontex.sty', package_path)
# Install scripts
if not path.exists(scripts_path):
mkdir(scripts_path)
copy('pythontex.py', scripts_path)
copy('depythontex.py', scripts_path)
copy('pythontex_utils.py', scripts_path)
copy('pythontex_engines.py', scripts_path)
copy('syncpdb.py', scripts_path)
for ver in [2, 3]:
copy('pythontex{0}.py'.format(ver), scripts_path)
copy('depythontex{0}.py'.format(ver), scripts_path)
# Install source
if not path.exists(source_path):
mkdir(source_path)
copy('pythontex.ins', source_path)
copy('pythontex.dtx', source_path)
except (OSError, IOError) as e:
if e.errno == 13:
print('\nInsufficient permission to install PythonTeX')
if platform.system() == 'Windows':
message = '''
You may need to run the installer as "administrator".
This may be done under Vista and later by right-clicking on
pythontex_install.bat, then selecting "Run as administrator".
Or you can open a command prompt as administrator
(Start, Programs, Accessories, right-click Command Prompt,
Run as administrator), change to the directory in which
pythontex_install.py is located, and run
"python pythontex_install.py".
'''
print(textwrap.dedent(message))
call(['pause'], shell=True)
else:
print('(For example, you may need "sudo", or possibly "sudo env PATH=$PATH")\n')
sys.exit(1)
else:
raise
# Install binary wrappers, create symlinks, or suggest the creation of
# wrappers/batch files/symlinks. This part is operating system dependent.
if platform.system() == 'Windows':
# If under Windows, we create a binary wrapper if under TeX Live
# or a batch file if under MiKTeX. Otherwise, alert the user
# regarding the need for a wrapper or batch file.
if miktex:
try:
if sys.version_info.major == 2:
bin_path = check_output(['kpsewhich', '-var-value', 'TEXMFDIST']).rstrip('\r\n')
else:
bin_path = check_output(['kpsewhich', '-var-value', 'TEXMFDIST']).decode('utf-8').rstrip('\r\n')
bin_path = path.join(bin_path, 'miktex', 'bin')
for s in ('pythontex.py', 'depythontex.py'):
batch = '@echo off\n"{0}" %*\n'.format(path.join(scripts_path, s))
f = open(path.join(bin_path, s.replace('.py', '.bat')), 'w')
f.write(batch)
f.close()
except:
message = '''
Could not create a batch file for launching pythontex.py and
depythontex.py. You will need to create a batch file manually.
Sample batch files are included with the main PythonTeX files.
The batch files should be in a location on the Windows PATH.
The bin/ directory in your TeX distribution may be a good
location.
The scripts pythontex.py and depythontex.py are located in
the following directory:
{0}
'''.format(scripts_path)
print(textwrap.dedent(message))
else:
# Assemble the binary path, assuming TeX Live
# The directory bin/ should be at the same level as texmf
bin_path = path.join(path.split(texmf_path)[0], 'bin', 'win32')
if path.exists(path.join(bin_path, 'runscript.exe')):
for f in ('pythontex.py', 'depythontex.py'):
copy(path.join(bin_path, 'runscript.exe'), path.join(bin_path, '{0}.exe'.format(f.rsplit('.')[0])))
print('\nCreated binary wrapper...')
else:
message = '''
Could not create a wrapper for launching pythontex.py and
depythontex.py; did not find runscript.exe. You will need
to create a wrapper manually, or use a batch file. Sample
batch files are included with the main PythonTeX files.
The wrapper or batch file should be in a location on the
Windows PATH. The bin/ directory in your TeX distribution
may be a good location.
The scripts pythontex.py and depythontex.py are located in
the following directory:
{0}
'''.format(scripts_path)
print(textwrap.dedent(message))
else:
# Optimistically proceed as if every system other than Windows can
# share one set of code.
root_path = path.split(texmf_path)[0]
# Create a list of all possible subdirectories of bin/ for TeX Live
# Source: http://www.tug.org/texlive/doc/texlive-en/texlive-en.html#x1-250003.2.1
texlive_platforms = ['alpha-linux', 'amd64-freebsd', 'amd64-kfreebsd',
'armel-linux', 'i386-cygwin', 'i386-freebsd',
'i386-kfreebsd', 'i386-linux', 'i386-solaris',
'mips-irix', 'mipsel-linux', 'powerpc-aix',
'powerpc-linux', 'sparc-solaris', 'universal-darwin',
'x86_64-darwin', 'x86_64-linux', 'x86_64-solaris']
symlink_created = False
# Try to create a symlink in the standard TeX Live locations
for pltfrm in texlive_platforms:
bin_path = path.join(root_path, 'bin', pltfrm)
if path.exists(bin_path):
# Unlink any old symlinks if they exist, and create new ones
# Not doing this gave permissions errors under Ubuntu
for f in ('pythontex.py', 'pythontex2.py', 'pythontex3.py',
'depythontex.py', 'depythontex2.py', 'depythontex3.py'):
link = path.join(bin_path, f)
if path.exists(link):
unlink(link)
symlink(path.join(scripts_path, f), link)
chmod(link, 0o775)
symlink_created = True
# If the standard TeX Live bin/ locations didn't work, try the typical
# location for MacPorts TeX Live. This should typically be
# /opt/local/bin, but instead of assuming that location, we just climb
# two levels up from texmf-dist and then look for a bin/ directory that
# contains a tex executable. (For MacPorts, texmf-dist should be at
# /opt/local/share/texmf-dist.)
if not symlink_created and platform.system() == 'Darwin':
bin_path = path.join(path.split(root_path)[0], 'bin')
if path.exists(bin_path):
try:
# Make sure this bin/ is the bin/ we're looking for, by
# seeing if pdftex exists
check_output([path.join(bin_path, 'pdftex'), '--version'])
# Create symlinks
for f in ('pythontex.py', 'pythontex2.py', 'pythontex3.py',
'depythontex.py', 'depythontex2.py', 'depythontex3.py'):
link = path.join(bin_path, f)
if path.exists(link):
unlink(link)
symlink(path.join(scripts_path, f), link)
chmod(link, 0o775)
symlink_created = True
except:
pass
if symlink_created:
print("\nCreated symlink in Tex's bin/ directory...")
else:
print('\nCould not automatically create a symlink to pythontex*.py and depythontex*.py.')
print('You may wish to create one manually, and make it executable via chmod.')
print('The scripts pythontex*.py and depythontex*.py are located in the following directory:')
print(' ' + scripts_path)
# Alert TeX to the existence of the package via mktexlsr
if not miktex:
try:
# Need to adjust if under Windows with a user-specified TeX Live
# installation and a default MiKTeX installation; want to call
# mktexlsr for the user-specified TeX Live installation
if platform.system() == 'Windows' and 'MiKTeX' in texout:
check_call(path.join(bin_path, 'mktexlsr'))
else:
check_call(['mktexlsr'])
print('\nRunning "mktexlsr" to make TeX aware of new files...')
except:
print('Could not run "mktexlsr".')
print('Your system may not be aware of newly installed files.')
else:
success = False
try:
check_call(['initexmf', '--admin', '--update-fndb'])
print('\nRunning "initexmf --admin --update-fndb" to make TeX aware of new files...')
check_call(['initexmf', '--update-fndb'])
print('\nRunning "initexmf --update-fndb" to make TeX aware of new files...')
success = True
except:
pass
if not success:
try:
check_call(['initexmf', '--update-fndb'])
print('\nRunning "initexmf --update-fndb" to make TeX aware of new files...')
print('Depending on your installation settings, you may also need to run')
print('"initexmf --admin --update-fndb"')
except:
print('Could not run "initexmf --update-fndb" or "initexmf --admin --update-fndb"')
print('Your system may not be aware of newly installed files.')
if platform.system() == 'Windows':
# Pause so that the user can see any errors or other messages
# input('\n[Press ENTER to exit]')
print('\n')
call(['pause'], shell=True)
|