2007-03-29 21:01:28 +00:00
#! /usr/bin/env python
2009-09-20 18:03:43 +00:00
# -*- coding: utf-8 -*-
2006-12-05 08:29:26 +00:00
2010-05-04 09:43:40 +00:00
# Tahoe-LAFS -- secure, distributed storage grid
2008-07-14 21:53:25 +00:00
#
2010-05-04 09:43:40 +00:00
# Copyright © 2008-2010 Allmydata, Inc.
2008-07-14 21:53:25 +00:00
#
2009-08-02 02:57:10 +00:00
# This file is part of Tahoe-LAFS.
2008-07-14 21:53:25 +00:00
#
2008-01-08 18:45:00 +00:00
# See the docs/about.html file for licensing information.
2006-12-05 08:29:26 +00:00
2010-05-23 20:52:28 +00:00
import glob , os , shutil , stat , subprocess , sys , zipfile , re
2008-09-12 01:03:21 +00:00
##### sys.path management
2008-12-06 00:30:54 +00:00
def pylibdir ( prefixdir ) :
pyver = " python %d . %d " % ( sys . version_info [ : 2 ] )
if sys . platform == " win32 " :
return os . path . join ( prefixdir , " Lib " , " site-packages " )
else :
return os . path . join ( prefixdir , " lib " , pyver , " site-packages " )
2008-09-12 01:03:21 +00:00
basedir = os . path . dirname ( os . path . abspath ( __file__ ) )
2008-12-06 00:30:54 +00:00
supportlib = pylibdir ( os . path . join ( basedir , " support " ) )
2009-08-18 01:00:57 +00:00
# locate our version number
def read_version_py ( infname ) :
try :
verstrline = open ( infname , " rt " ) . read ( )
except EnvironmentError :
return None
else :
VSRE = r " ^verstr = [ ' \" ]([^ ' \" ]*)[ ' \" ] "
mo = re . search ( VSRE , verstrline , re . M )
if mo :
return mo . group ( 1 )
version = read_version_py ( " src/allmydata/_version.py " )
2010-10-29 22:28:25 +00:00
APPNAME = ' allmydata-tahoe '
APPNAMEFILE = os . path . join ( ' src ' , ' allmydata ' , ' _appname.py ' )
APPNAMEFILESTR = " __appname__ = ' %s ' " % ( APPNAME , )
try :
curappnamefilestr = open ( APPNAMEFILE , ' rU ' ) . read ( )
except EnvironmentError :
# No file, or unreadable or something, okay then let's try to write one.
open ( APPNAMEFILE , " w " ) . write ( APPNAMEFILESTR )
else :
if curappnamefilestr . strip ( ) != APPNAMEFILESTR :
print " Error -- this setup.py file is configured with the ' application name ' to be ' %s ' , but there is already a file in place in ' %s ' which contains the contents ' %s ' . If the file is wrong, please remove it and setup.py will regenerate it and write ' %s ' into it. " % ( APPNAME , APPNAMEFILE , curappnamefilestr , APPNAMEFILESTR )
sys . exit ( - 1 )
# setuptools/zetuptoolz looks in __main__.__requires__ for a list of
# requirements. When running "python setup.py test", __main__ is
# setup.py, so we put the list here so that the requirements will be
# available for tests:
# Tahoe's dependencies are managed by the find_links= entry in setup.cfg and
# the _auto_deps.install_requires list, which is used in the call to setup()
# below.
adglobals = { }
execfile ( ' src/allmydata/_auto_deps.py ' , adglobals )
install_requires = adglobals [ ' install_requires ' ]
2010-11-19 07:40:43 +00:00
__requires__ = install_requires [ : ]
if ' trial ' in sys . argv or ' test ' in sys . argv :
if version is not None :
__requires__ . append ( APPNAME + ' == ' + version )
else :
__requires__ . append ( APPNAME )
2010-10-29 22:28:25 +00:00
2010-05-23 20:52:28 +00:00
egg = os . path . realpath ( glob . glob ( ' setuptools-*.egg ' ) [ 0 ] )
sys . path . insert ( 0 , egg )
2010-09-21 07:32:58 +00:00
egg = os . path . realpath ( glob . glob ( ' darcsver-*.egg ' ) [ 0 ] )
sys . path . insert ( 0 , egg )
2010-05-23 20:52:28 +00:00
import setuptools ; setuptools . bootstrap_install_from = egg
2007-09-13 21:51:19 +00:00
2008-09-17 23:08:29 +00:00
from setuptools import find_packages , setup
2008-08-27 18:26:44 +00:00
from setuptools . command import sdist
2009-01-29 14:00:58 +00:00
from setuptools import Command
2008-12-01 18:48:04 +00:00
2007-04-27 20:47:15 +00:00
trove_classifiers = [
2008-04-14 18:08:23 +00:00
" Development Status :: 5 - Production/Stable " ,
2007-04-27 20:47:15 +00:00
" Environment :: Console " ,
" Environment :: Web Environment " ,
2008-07-14 21:53:25 +00:00
" License :: OSI Approved :: GNU General Public License (GPL) " ,
2008-01-08 18:45:00 +00:00
" License :: DFSG approved " ,
" License :: Other/Proprietary License " ,
2008-07-14 21:53:25 +00:00
" Intended Audience :: Developers " ,
2007-04-27 20:47:15 +00:00
" Intended Audience :: End Users/Desktop " ,
" Intended Audience :: System Administrators " ,
" Operating System :: Microsoft " ,
" Operating System :: Microsoft :: Windows " ,
2008-10-21 16:32:00 +00:00
" Operating System :: Microsoft :: Windows :: Windows NT/2000 " ,
2007-04-27 20:47:15 +00:00
" Operating System :: Unix " ,
" Operating System :: POSIX :: Linux " ,
" Operating System :: POSIX " ,
" Operating System :: MacOS :: MacOS X " ,
2008-07-14 21:53:25 +00:00
" Operating System :: OS Independent " ,
" Natural Language :: English " ,
" Programming Language :: C " ,
" Programming Language :: Python " ,
2008-10-21 16:32:00 +00:00
" Programming Language :: Python :: 2 " ,
" Programming Language :: Python :: 2.4 " ,
" Programming Language :: Python :: 2.5 " ,
2009-01-29 01:26:28 +00:00
" Programming Language :: Python :: 2.6 " ,
2007-04-27 20:47:15 +00:00
" Topic :: Utilities " ,
" Topic :: System :: Systems Administration " ,
" Topic :: System :: Filesystems " ,
" Topic :: System :: Distributed Computing " ,
" Topic :: Software Development :: Libraries " ,
" Topic :: Communications :: Usenet News " ,
2008-07-14 21:53:25 +00:00
" Topic :: System :: Archiving :: Backup " ,
" Topic :: System :: Archiving :: Mirroring " ,
" Topic :: System :: Archiving " ,
2007-04-27 20:47:15 +00:00
]
2006-12-14 10:25:30 +00:00
2007-05-04 03:14:07 +00:00
2008-04-09 18:30:53 +00:00
setup_requires = [ ]
2008-09-17 01:36:27 +00:00
2009-02-19 06:57:51 +00:00
# The darcsver command from the darcsver plugin is needed to initialize the
# distribution's .version attribute correctly. (It does this either by
# examining darcs history, or if that fails by reading the
2009-05-07 21:50:03 +00:00
# src/allmydata/_version.py file). darcsver will also write a new version
# stamp in src/allmydata/_version.py, with a version number derived from
2009-02-19 06:57:51 +00:00
# darcs history. Note that the setup.cfg file has an "[aliases]" section
# which enumerates commands that you might run and specifies that it will run
# darcsver before each one. If you add different commands (or if I forgot
# some that are already in use), you may need to add it to setup.cfg and
# configure it to run darcsver before your command, if you want the version
# number to be correct when that command runs.
2009-02-04 06:24:05 +00:00
# http://pypi.python.org/pypi/darcsver
2010-11-23 02:12:18 +00:00
setup_requires . append ( ' darcsver >= 1.7.1 ' )
2009-02-04 06:24:05 +00:00
2009-02-19 06:57:51 +00:00
# Nevow requires Twisted to setup, but doesn't declare that requirement in a
# way that enables setuptools to satisfy that requirement before Nevow's
# setup.py tried to "import twisted". Fortunately we require setuptools_trial
# to setup and setuptools_trial requires Twisted to install, so hopefully
# everything will work out until the Nevow issue is fixed:
# http://divmod.org/trac/ticket/2629 setuptools_trial is needed if you want
# "./setup.py trial" or "./setup.py test" to execute the tests (and in order
# to make sure Twisted is installed early enough -- see the paragraph above).
2009-01-27 05:40:46 +00:00
# http://pypi.python.org/pypi/setuptools_trial
2009-01-30 05:31:33 +00:00
setup_requires . extend ( [ ' setuptools_trial >= 0.5 ' ] )
2008-10-25 13:50:42 +00:00
2009-02-19 06:57:51 +00:00
# setuptools_darcs is required to produce complete distributions (such as
# with "sdist" or "bdist_egg") (unless there is a PKG-INFO file present which
# shows that this is itself a source distribution). For simplicity, and
# because there is some unknown error with setuptools_darcs when building and
# testing tahoe all in one python command on some platforms, we always add it
# to setup_requires. http://pypi.python.org/pypi/setuptools_darcs
2009-02-04 06:24:05 +00:00
setup_requires . append ( ' setuptools_darcs >= 1.1.0 ' )
2008-01-22 15:35:38 +00:00
2010-05-21 12:22:26 +00:00
# trialcoverage is required if you want the "trial" unit test runner to have a
# "--reporter=bwverbose-coverage" option which produces code-coverage results.
2010-05-25 00:44:44 +00:00
# The required version is 0.3.3, because that is the latest version that only
# depends on a version of pycoverage for which binary packages are available.
2010-05-21 12:22:26 +00:00
if " --reporter=bwverbose-coverage " in sys . argv :
2010-05-24 23:37:07 +00:00
setup_requires . append ( ' trialcoverage >= 0.3.3 ' )
2010-05-21 12:22:26 +00:00
2009-07-23 15:04:07 +00:00
# stdeb is required to produce Debian files with the "sdist_dsc" command.
if " sdist_dsc " in sys . argv :
setup_requires . append ( ' stdeb >= 0.3 ' )
2010-06-09 05:05:42 +00:00
tests_require = [
# Mock - Mocking and Testing Library
# http://www.voidspace.org.uk/python/mock/
" mock " ,
]
2008-09-12 01:03:21 +00:00
class ShowSupportLib ( Command ) :
user_options = [ ]
def initialize_options ( self ) :
pass
def finalize_options ( self ) :
pass
def run ( self ) :
# TODO: --quiet suppresses the 'running show_supportlib' message.
# Find a way to do this all the time.
print supportlib # TODO windowsy
class ShowPythonPath ( Command ) :
user_options = [ ]
def initialize_options ( self ) :
pass
def finalize_options ( self ) :
pass
def run ( self ) :
# TODO: --quiet suppresses the 'running show_supportlib' message.
# Find a way to do this all the time.
2009-01-15 03:37:51 +00:00
print " PYTHONPATH= %s " % os . environ . get ( " PYTHONPATH " , ' ' )
2008-09-12 01:03:21 +00:00
2008-09-12 04:44:18 +00:00
class RunWithPythonPath ( Command ) :
description = " Run a subcommand with PYTHONPATH set appropriately "
user_options = [ ( " python " , " p " ,
" Treat command string as arguments to a python executable " ) ,
( " command= " , " c " , " Command to be run " ) ,
( " directory= " , " d " , " Directory to run the command in " ) ,
]
boolean_options = [ " python " ]
def initialize_options ( self ) :
self . command = None
self . python = False
self . directory = None
def finalize_options ( self ) :
pass
def run ( self ) :
2009-01-15 03:37:51 +00:00
oldpp = os . environ . get ( " PYTHONPATH " , " " ) . split ( os . pathsep )
if oldpp == [ " " ] :
# grr silly split() behavior
oldpp = [ ]
os . environ [ ' PYTHONPATH ' ] = os . pathsep . join ( oldpp + [ supportlib , ] )
# We must require the command to be safe to split on
# whitespace, and have --python and --directory to make it
# easier to achieve this.
2008-09-12 04:44:18 +00:00
command = [ ]
if self . python :
command . append ( sys . executable )
if self . command :
command . extend ( self . command . split ( ) )
if not command :
raise RuntimeError ( " The --command argument is mandatory " )
if self . directory :
os . chdir ( self . directory )
if self . verbose :
print " command = " , " " . join ( command )
rc = subprocess . call ( command )
sys . exit ( rc )
2009-07-12 23:09:40 +00:00
class TestMacDiskImage ( Command ) :
user_options = [ ]
def initialize_options ( self ) :
pass
def finalize_options ( self ) :
pass
def run ( self ) :
import sys
2010-06-07 05:16:18 +00:00
sys . path . append ( os . path . join ( ' misc ' , ' build_helpers ' ) )
2009-07-12 23:09:40 +00:00
import test_mac_diskimage
return test_mac_diskimage . test_mac_diskimage ( ' Allmydata ' , version = self . distribution . metadata . version )
2008-09-12 03:59:04 +00:00
class CheckAutoDeps ( Command ) :
user_options = [ ]
def initialize_options ( self ) :
pass
def finalize_options ( self ) :
pass
def run ( self ) :
2010-09-06 05:57:14 +00:00
adglobals = { }
execfile ( ' src/allmydata/_auto_deps.py ' , adglobals )
adglobals [ ' require_auto_deps ' ] ( )
2008-09-12 03:59:04 +00:00
2009-01-29 01:07:16 +00:00
class MakeExecutable ( Command ) :
2008-09-12 01:03:21 +00:00
user_options = [ ]
def initialize_options ( self ) :
pass
def finalize_options ( self ) :
pass
def run ( self ) :
2009-01-29 01:07:16 +00:00
bin_tahoe_template = os . path . join ( " bin " , " tahoe-script.template " )
2010-07-25 08:32:16 +00:00
if sys . platform == ' win32 ' :
# 'tahoe' script is needed for cygwin
script_names = [ " tahoe.pyscript " , " tahoe " ]
else :
script_names = [ " tahoe " ]
# 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.
2009-01-29 01:07:16 +00:00
f = open ( bin_tahoe_template , " rU " )
script_lines = f . readlines ( )
f . close ( )
2010-07-25 08:32:16 +00:00
script_lines [ 0 ] = ' #! %s \n ' % ( sys . executable , )
for script_name in script_names :
tahoe_script = os . path . join ( " bin " , script_name )
2009-01-29 01:07:16 +00:00
try :
2010-07-25 08:32:16 +00:00
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 ( )
# chmod +x
old_mode = stat . S_IMODE ( os . stat ( tahoe_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 ( tahoe_script , new_mode )
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
2008-09-12 01:03:21 +00:00
2008-08-27 18:26:44 +00:00
class MySdist ( sdist . sdist ) :
""" A hook in the sdist command so that we can determine whether this the
tarball should be ' SUMO ' or not , i . e . whether or not to include the
2008-09-17 20:01:19 +00:00
external dependency tarballs . Note that we always include
misc / dependencies / * in the tarball ; - - sumo controls whether tahoe - deps / *
is included as well .
2008-08-27 18:26:44 +00:00
"""
user_options = sdist . sdist . user_options + \
2008-09-17 20:01:19 +00:00
[ ( ' sumo ' , ' s ' ,
" create a ' sumo ' sdist which includes the contents of tahoe-deps/* " ) ,
]
2008-08-27 18:26:44 +00:00
boolean_options = [ ' sumo ' ]
def initialize_options ( self ) :
sdist . sdist . initialize_options ( self )
2008-09-17 20:01:19 +00:00
self . sumo = False
def make_distribution ( self ) :
# add our extra files to the list just before building the
# tarball/zipfile. We override make_distribution() instead of run()
# because setuptools.command.sdist.run() does not lend itself to
# easy/robust subclassing (the code we need to add goes right smack
# in the middle of a 12-line method). If this were the distutils
# version, we'd override get_file_list().
if self . sumo :
# If '--sumo' was specified, include tahoe-deps/* in the sdist.
# We assume that the user has fetched the tahoe-deps.tar.gz
# tarball and unpacked it already.
self . filelist . extend ( [ os . path . join ( " tahoe-deps " , fn )
for fn in os . listdir ( " tahoe-deps " ) ] )
# In addition, we want the tarball/zipfile to have -SUMO in the
# name, and the unpacked directory to have -SUMO too. The easiest
# way to do this is to patch self.distribution and override the
# get_fullname() method. (an alternative is to modify
# self.distribution.metadata.version, but that also affects the
# contents of PKG-INFO).
fullname = self . distribution . get_fullname ( )
def get_fullname ( ) :
return fullname + " -SUMO "
self . distribution . get_fullname = get_fullname
return sdist . sdist . make_distribution ( self )
2008-08-27 18:26:44 +00:00
2009-08-18 01:00:57 +00:00
setup_args = { }
if version :
setup_args [ " version " ] = version
versioning: include an "appname" in the application version string in the versioning protocol, and make that appname be controlled by setup.py
It is currently hardcoded in setup.py to be 'allmydata-tahoe'. Ticket #556 is to make it configurable by a runtime command-line argument to setup.py: "--appname=foo", but I suddenly wondered if we really wanted that and at the same time realized that we don't need that for tahoe-1.3.0 release, so this patch just hardcodes it in setup.py.
setup.py inspects a file named 'src/allmydata/_appname.py' and assert that it contains the string "__appname__ = 'allmydata-tahoe'", and creates it if it isn't already present. src/allmydata/__init__.py import _appname and reads __appname__ from it. The rest of the Python code imports allmydata and inspects "allmydata.__appname__", although actually every use it uses "allmydata.__full_version__" instead, where "allmydata.__full_version__" is created in src/allmydata/__init__.py to be:
__full_version__ = __appname + '-' + str(__version__).
All the code that emits an "application version string" when describing what version of a protocol it supports (introducer server, storage server, upload helper), or when describing itself in general (introducer client), usese allmydata.__full_version__.
This fixes ticket #556 at least well enough for tahoe-1.3.0 release.
2009-02-12 00:18:16 +00:00
setup ( name = APPNAME ,
2008-01-22 17:22:51 +00:00
description = ' secure, decentralized, fault-tolerant filesystem ' ,
2010-05-04 09:43:40 +00:00
long_description = open ( ' README.txt ' , ' rU ' ) . read ( ) ,
author = ' the Tahoe-LAFS project ' ,
2010-09-30 15:37:08 +00:00
author_email = ' tahoe-dev@tahoe-lafs.org ' ,
2010-05-04 09:43:40 +00:00
url = ' http://tahoe-lafs.org/ ' ,
license = ' GNU GPL ' , # see README.txt -- there is an alternative licence
2008-09-12 01:03:21 +00:00
cmdclass = { " show_supportlib " : ShowSupportLib ,
" show_pythonpath " : ShowPythonPath ,
2008-09-12 04:44:18 +00:00
" run_with_pythonpath " : RunWithPythonPath ,
2008-09-12 03:59:04 +00:00
" check_auto_deps " : CheckAutoDeps ,
2009-07-12 23:09:40 +00:00
" test_mac_diskimage " : TestMacDiskImage ,
2009-01-29 01:07:16 +00:00
" make_executable " : MakeExecutable ,
2008-09-12 01:03:21 +00:00
" sdist " : MySdist ,
} ,
2007-11-10 01:04:19 +00:00
package_dir = { ' ' : ' src ' } ,
packages = find_packages ( " src " ) ,
2007-04-27 20:47:15 +00:00
classifiers = trove_classifiers ,
test_suite = " allmydata.test " ,
2008-09-12 01:03:21 +00:00
install_requires = install_requires ,
2010-06-09 05:05:42 +00:00
tests_require = tests_require ,
2007-11-10 01:04:19 +00:00
include_package_data = True ,
2008-01-01 06:28:31 +00:00
setup_requires = setup_requires ,
2007-10-11 10:38:24 +00:00
entry_points = { ' console_scripts ' : [ ' tahoe = allmydata.scripts.runner:run ' ] } ,
2007-09-13 22:37:55 +00:00
zip_safe = False , # We prefer unzipped for easier access.
2010-11-14 07:40:40 +00:00
versionfiles = [ ' src/allmydata/_version.py ' , ] ,
2009-08-18 01:00:57 +00:00
* * setup_args
2007-04-27 20:47:15 +00:00
)