177 lines
5.6 KiB
Python
Executable File
177 lines
5.6 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
def make_lifelib(autorun=True):
|
|
'''
|
|
This script should be run from within the Python environment in which
|
|
you would like to install or upgrade lifelib. It will do the following
|
|
in turn:
|
|
|
|
- ensure its own existence;
|
|
- invoke the pip package manager to install/upgrade python-lifelib;
|
|
- ensure the lifelib environment is correctly configured;
|
|
- perform a rudimentary sanity check;
|
|
- perform comprehensive tests.
|
|
|
|
It can be invoked as a Python script or module, or run from within an
|
|
interpreter (python, IPython, or Jupyter), or executed as a Golly script.
|
|
'''
|
|
|
|
import sys
|
|
import os
|
|
from time import sleep
|
|
|
|
print('Determining whether Golly exists...')
|
|
try:
|
|
import golly as g
|
|
def pprint(x):
|
|
print(x)
|
|
g.show(x)
|
|
g.update()
|
|
sleep(0.5)
|
|
golly_exists=True
|
|
except ImportError:
|
|
def pprint(x):
|
|
print(x)
|
|
golly_exists=False
|
|
|
|
preposition = ('within' if golly_exists else 'outside')
|
|
pprint('We are running %s Golly.' % preposition)
|
|
|
|
pprint('Determining Python executable...')
|
|
this_python = os.path.abspath(sys.executable)
|
|
|
|
pprint('Determining script location...')
|
|
try:
|
|
this_script = os.path.abspath(__file__)
|
|
if not os.path.exists(this_script):
|
|
raise NameError("Script does not exist.")
|
|
except NameError:
|
|
# We may be running from stdin or the clipboard. Ensure the script
|
|
# exists in a real location:
|
|
pprint('Writing script to file...')
|
|
this_script = 'lifelib_install.py'
|
|
|
|
try:
|
|
import inspect
|
|
source = '#!/usr/bin/python\n\n'
|
|
source += inspect.getsource(make_lifelib)
|
|
source += '# run program\nmake_lifelib(False)\n'
|
|
with open(this_script, 'w') as f:
|
|
f.write(source)
|
|
except:
|
|
try:
|
|
from urllib import urlretrieve
|
|
except ImportError:
|
|
from urllib.request import urlretrieve
|
|
pprint("Downloading installation script over HTTPS...")
|
|
script_path = 'https://gitlab.com/apgoucher/python-lifelib'
|
|
script_path += '/raw/master/install/install.py'
|
|
urlretrieve(script_path, this_script)
|
|
|
|
def install_package():
|
|
|
|
pprint("Finding pip package manager...")
|
|
|
|
try:
|
|
import pip
|
|
except ImportError:
|
|
import ensurepip
|
|
ensurepip.bootstrap()
|
|
|
|
try:
|
|
# Python 3.x:
|
|
from pip._internal import main
|
|
except ImportError:
|
|
# Python 2.x:
|
|
from pip import main
|
|
|
|
pprint("Installing/upgrading lifelib...")
|
|
rc = main(['install', '--user', '--upgrade', 'python-lifelib'])
|
|
|
|
if rc and os.environ.get('VIRTUAL_ENV', None):
|
|
pprint("Probably running in virtualenv so dropping --user...")
|
|
rc = main(['install', '--upgrade', 'python-lifelib'])
|
|
|
|
if rc:
|
|
pprint("Failed to install or upgrade lifelib.")
|
|
|
|
def post_install():
|
|
|
|
pprint("Checking lifelib is installed...")
|
|
|
|
try:
|
|
# This usually works, but not if this is the first time that
|
|
# a --user package has been installed:
|
|
import lifelib
|
|
except ImportError:
|
|
pprint("Updating sys.path...")
|
|
|
|
# Find the updated sys.path which contains the newly-minted
|
|
# python-lifelib installation:
|
|
from subprocess import check_output
|
|
sa = [this_python, '-c', 'import sys; print(sys.path)']
|
|
new_path = check_output(sa)
|
|
|
|
# Python 3 returns a 'bytes' object which is incompatible
|
|
# with the ast.literal_eval() function, so cast to str:
|
|
if not isinstance(new_path, str):
|
|
new_path = new_path.decode()
|
|
|
|
# Safely decode the returned string:
|
|
import ast
|
|
new_path = ast.literal_eval(new_path)
|
|
|
|
# In-place list concatenation:
|
|
for n in new_path:
|
|
sys.path.append(n)
|
|
|
|
# Now that sys.path has been modified, we can import lifelib:
|
|
import lifelib
|
|
|
|
pprint("Lifelib version: %s" % lifelib.__version__)
|
|
|
|
if (os.name == 'nt'):
|
|
pprint("Installing Cygwin if necessary...")
|
|
lifelib.install_cygwin()
|
|
|
|
pprint("Creating session...")
|
|
sess = lifelib.load_rules('b3s23', force_indirect=True)
|
|
lt = sess.lifetree()
|
|
lidka = lt.pattern("bo$obo$bo8$8bo$6bobo$5b2obo2$4b3o!", 'b3s23')
|
|
|
|
lp = lidka.population
|
|
l30kp = lidka[30000].population
|
|
|
|
pprint("Initial population of Lidka: %d" % lp)
|
|
pprint("Final population of Lidka: %d" % l30kp)
|
|
|
|
if (lp != 13) or (l30kp != 1623):
|
|
raise ValueError("Serious problem: populations do not match.")
|
|
|
|
pprint("Checking numpy is installed...")
|
|
import numpy as np
|
|
pprint("Numpy version: %s" % np.__version__)
|
|
|
|
pprint("Running comprehensive tests...")
|
|
lifelib.run_tests()
|
|
|
|
pprint("Everything completed successfully.")
|
|
|
|
def install_sandboxed():
|
|
|
|
from subprocess import check_call
|
|
pprint("Upgrading lifelib in separate process...")
|
|
check_call([this_python, this_script, '*'])
|
|
pprint("Lifelib upgraded; running post-install tasks...")
|
|
sleep(1.0)
|
|
post_install()
|
|
|
|
if autorun or golly_exists:
|
|
install_sandboxed()
|
|
elif (__name__ == '__main__'):
|
|
[install_sandboxed, install_package, post_install][len(sys.argv)-1]()
|
|
|
|
pass
|
|
# run program
|
|
make_lifelib(False)
|