copy bin/tahoe from $PATH for the sake of test_runner

This is needed to allow virtualenv-based builds to exercise
test_runner.BinTahoe (and a few others), which expect to run an
executable program in "bin/tahoe". This also helps users who aren't yet
accustomed to the new virtualenv world where they can just run "tahoe"
instead of "bin/tahoe".

This changes the "setup.py make_executable" command to copy the first
"tahoe" executable found on $PATH into bin/tahoe . Previously bin/tahoe
was created by modifying the shbang line of a template stored in
bin/tahoe-script.template (which has been deleted).

It also changes setup.cfg to run "make_executable" before tests,
and *after* an install. Note that you must use "setup.py install" before
"setup.py test", since make_executable requires the installed "tahoe" on
$PATH.

In the future, we hope to get rid of bin/tahoe altogether, and have
these tests run the "tahoe" from $PATH directly.
This commit is contained in:
Brian Warner 2016-02-16 10:59:02 -08:00 committed by Daira Hopwood
parent fe360ee47b
commit 0651991474
4 changed files with 34 additions and 172 deletions

View File

@ -12,7 +12,7 @@ export PYFLAKES
# itself. It will also create it in the beginning of the 'develop' command.
TAHOE=$(PYTHON) bin/tahoe
SOURCES=src/allmydata src/buildtest static misc bin/tahoe-script.template setup.py
SOURCES=src/allmydata src/buildtest static misc setup.py
APPNAME=allmydata-tahoe
# This is necessary only if you want to automatically produce a new

View File

@ -1,130 +0,0 @@
#!/bin/false # You must specify a python interpreter.
import sys; assert sys.version_info < (3,), ur"Tahoe-LAFS does not run under Python 3. Please use a version of Python between 2.6 and 2.7.x inclusive."
import os, subprocess
where = os.path.realpath(sys.argv[0])
base = os.path.dirname(os.path.dirname(where))
if sys.platform == "win32":
perhaps_installed_tahoe = os.path.join(os.path.dirname(sys.executable), 'Scripts', 'tahoe.pyscript')
else:
perhaps_installed_tahoe = "/usr/bin/tahoe"
whoami = '''\
I am a "bin%stahoe" executable for the convenience of running Tahoe-LAFS
from its source distribution -- I work only when invoked as the "tahoe"
script that lives in the "bin" subdirectory of a Tahoe source code
distribution, and only if you have already run "python setup.py build".
''' % (os.path.sep,)
# look for Tahoe.home .
homemarker = os.path.join(base, "Tahoe.home")
if not os.path.exists(homemarker):
print(whoami)
print('''\
I just tried to run and found that I am not living in such a directory, so I
am stopping now. To run Tahoe after it has been is installed, please execute
my brother, who gets installed into the appropriate place for executables
when you run "make install" (perhaps as "%s").
''' % (perhaps_installed_tahoe,))
sys.exit(1)
# we've found our home. Put the tahoe support/lib etc. in our PYTHONPATH.
if sys.platform == "win32":
supportdir = os.path.join(base, "support", "Lib", "site-packages")
else:
supportdir = os.path.join(base, "support",
"lib",
"python%d.%d" % sys.version_info[:2],
"site-packages")
# update PYTHONPATH so that child processes (like twistd) will use this too
pp = os.environ.get("PYTHONPATH")
if pp:
pp = os.pathsep.join([supportdir] + pp.split(os.pathsep))
else:
pp = supportdir
os.environ["PYTHONPATH"] = pp
# find commandline args and the location of the tahoe executable.
if sys.platform == "win32":
import re
from ctypes import WINFUNCTYPE, POINTER, byref, c_wchar_p, c_int, windll
GetCommandLineW = WINFUNCTYPE(c_wchar_p)(("GetCommandLineW", windll.kernel32))
CommandLineToArgvW = WINFUNCTYPE(POINTER(c_wchar_p), c_wchar_p, POINTER(c_int)) \
(("CommandLineToArgvW", windll.shell32))
argc = c_int(0)
argv_unicode = CommandLineToArgvW(GetCommandLineW(), byref(argc))
# See src/allmydata/scripts/runner.py for the corresponding unmangler.
# Note that this doesn't escape \x7F. If it did, test_unicode_arguments_and_output
# in test_runner.py wouldn't work.
def mangle(s):
return str(re.sub(u'[^\\x20-\\x7F]', lambda m: u'\x7F%x;' % (ord(m.group(0)),), s))
argv = [mangle(argv_unicode[i]) for i in xrange(0, argc.value)]
# Take only the suffix with the same number of arguments as sys.argv.
# This accounts for anything that can cause initial arguments to be stripped,
# for example, the Python interpreter or any options passed to it, or runner
# scripts such as 'coverage run'. It works even if there are no such arguments,
# as in the case of a frozen executable created by bb-freeze or similar.
argv = argv[-len(sys.argv):]
# On Windows, the script is not directly executable and must be run via python.
prefix = [sys.executable]
script = os.path.join(base, "support", "Scripts", "tahoe.pyscript")
args = argv[1:]
else:
# On non-Windows, invoke the script directly, so that 'top' for example shows 'tahoe'.
prefix = []
script = os.path.join(base, "support", "bin", "tahoe")
args = sys.argv[1:]
# Support indirection via another "runner" script (e.g. coverage).
# For example: bin/tahoe @RUNNER RUNNER_ARGS @tahoe TAHOE_ARGS
if len(args) >= 1 and args[0].startswith('@'):
runner = args[0][1:]
if runner.endswith('.py') or runner.endswith('.pyscript'):
prefix = [sys.executable]
else:
prefix = []
if runner == "python":
runner = sys.executable
def _subst(a):
if a == '@tahoe': return script
return a
command = prefix + [runner] + map(_subst, args[1:])
else:
runner = script
command = prefix + [script] + args
if not os.path.exists(script):
print(whoami)
print('''\
I could not find the support script
"%s".
To run an installed version of Tahoe-LAFS, please execute the "tahoe"
script that is installed into the appropriate place for executables
when you run "python setup.py install" (perhaps as "%s").
''' % (script, perhaps_installed_tahoe))
sys.exit(1)
try:
res = subprocess.call(command, env=os.environ)
except Exception as le:
print(whoami)
print('''\
I just tried to invoke "%s"
and got an exception.
''' % (runner,))
raise
else:
sys.exit(res)

View File

@ -34,8 +34,8 @@ find_links=misc/dependencies tahoe-deps ../tahoe-deps
[aliases]
build = update_version build
test = update_version build trial
test = update_version build make_executable trial
sdist = update_version sdist
install = update_version install
install = update_version install make_executable
bdist_egg = update_version bdist_egg
trial = update_version trial

View File

@ -10,7 +10,7 @@ import sys; assert sys.version_info < (3,), ur"Tahoe-LAFS does not run under Pyt
#
# See the docs/about.rst file for licensing information.
import os, stat, subprocess, re
import os, subprocess, re
##### sys.path management
@ -72,8 +72,6 @@ if len(sys.argv) > 1 and sys.argv[1] == '--fakedependency':
__requires__ = install_requires[:]
import setuptools
from setuptools import setup
from setuptools.command import sdist
from setuptools import Command
@ -189,46 +187,40 @@ class MakeExecutable(Command):
def finalize_options(self):
pass
def run(self):
bin_tahoe_template = os.path.join("bin", "tahoe-script.template")
# A bin/tahoe (or bin/tahoe-script.py) is only necessary for the
# test_runner tests which exercise CLI invocation of a brand new
# tahoe process. It is also handy for users who are accustomed to
# running bin/tahoe (and have not yet gotten used to the new
# virtualenv-based "just run tahoe" world). Eventually this will be
# removed.
# tahoe.pyscript is really only necessary for Windows, but we also
# create it on Unix for consistency.
script_names = ["tahoe.pyscript", "tahoe"]
# This must be run *after* a 'pip install' (hopefully inside a
# virtualenv), because it needs to locate the tahoe executable (named
# 'tahoe' or 'tahoe.exe' or 'tahoe-script.py' or something) on $PATH.
# Create the tahoe script file under the 'bin' directory. This
# file is exactly the same as the 'tahoe-script.template' script
# except that the shebang line is rewritten to use our sys.executable
# for the interpreter.
f = open(bin_tahoe_template, "rU")
script_lines = f.readlines()
f.close()
script_lines[0] = '#!%s\n' % (sys.executable,)
for script_name in script_names:
tahoe_script = os.path.join("bin", script_name)
try:
os.remove(tahoe_script)
except Exception:
if os.path.exists(tahoe_script):
raise
f = open(tahoe_script, "wb")
for line in script_lines:
f.write(line)
f.close()
# This is safe because we're run after 'install', which installed
# Twisted. It would not be safe to run before that. Note that this
# uses $PATHEXT for a list of executable suffixes.
from twisted.python.procutils import which
# chmod +x
unix_script = os.path.join("bin", "tahoe")
old_mode = stat.S_IMODE(os.stat(unix_script)[stat.ST_MODE])
new_mode = old_mode | (stat.S_IXUSR | stat.S_IRUSR |
stat.S_IXGRP | stat.S_IRGRP |
stat.S_IXOTH | stat.S_IROTH )
os.chmod(unix_script, new_mode)
installed_tahoes = which("tahoe")
if not installed_tahoes:
err = ("Cannot find installed 'tahoe' binary "
"('setup.py make_executable' must be run after"
" 'setup.py install')")
raise RuntimeError(err)
old_tahoe_exe = os.path.join("bin", "tahoe.exe")
try:
os.remove(old_tahoe_exe)
except Exception:
if os.path.exists(old_tahoe_exe):
raise
if not os.path.isdir("bin"):
os.mkdir("bin")
installed_tahoe = installed_tahoes[0]
bin_tahoe = os.path.join("bin", "tahoe")
with open(installed_tahoe, "rb") as inf:
with open(bin_tahoe, "wb") as outf:
outf.write(inf.read())
# copy file mode
os.chmod(bin_tahoe, os.stat(installed_tahoe).st_mode)
GIT_VERSION_BODY = '''