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
2009-08-18 01:00:57 +00:00
import 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 " )
2007-11-09 21:58:03 +00:00
try :
from ez_setup import use_setuptools
except ImportError :
pass
2007-09-13 01:57:10 +00:00
else :
2009-02-19 06:57:51 +00:00
# This invokes our own customized version of ez_setup.py to make sure
# that setuptools v0.6c12dev (which is our own toothpick of setuptools)
# is used to build. Note that we can use any version of setuptools >=
# 0.6c6 to *run* -- see _auto_deps.py for run-time dependencies (a.k.a.
# "install_requires") -- this is only for build-time dependencies (a.k.a.
# "setup_requires").
2009-02-05 16:29:23 +00:00
use_setuptools ( download_delay = 0 , min_version = " 0.6c12dev " )
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
2009-01-09 19:42:22 +00:00
from pkg_resources import require
2008-12-01 18:48:04 +00:00
2008-01-23 00:24:33 +00:00
# Make the dependency-version-requirement, which is used by the Makefile at
# build-time, also available to the app at runtime:
2009-02-19 06:57:51 +00:00
shutil . copyfile ( " _auto_deps.py " ,
os . path . join ( " src " , " allmydata " , " _auto_deps.py " ) )
2008-01-23 00:24:33 +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
setup_requires . append ( ' darcsver >= 1.2.0 ' )
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.
if " --reporter=bwverbose-coverage " in sys . argv :
setup_requires . append ( ' trialcoverage >= 0.3.10 ' )
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 ' )
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
sys . path . append ( ' misc ' )
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 ) :
import _auto_deps
_auto_deps . require_auto_deps ( )
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 " )
2009-02-19 06:57:51 +00:00
# Create the 'tahoe-script.py' file under the 'bin' directory. The
# 'tahoe-script.py' 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. On
# Windows, create a tahoe.exe will execute it. On non-Windows, make a
# symlink to it from 'tahoe'. The tahoe.exe will be copied from the
# setuptools egg's cli.exe and this will work from a zip-safe and
# non-zip-safe setuptools egg.
2009-01-29 01:07:16 +00:00
f = open ( bin_tahoe_template , " rU " )
script_lines = f . readlines ( )
f . close ( )
script_lines [ 0 ] = " #! %s \n " % sys . executable
tahoe_script = os . path . join ( " bin " , " tahoe-script.py " )
f = open ( tahoe_script , " w " )
for line in script_lines :
f . write ( line )
f . close ( )
2009-01-09 19:42:22 +00:00
if sys . platform == " win32 " :
setuptools_egg = require ( " setuptools " ) [ 0 ] . location
if os . path . isfile ( setuptools_egg ) :
z = zipfile . ZipFile ( setuptools_egg , ' r ' )
for filename in z . namelist ( ) :
if ' cli.exe ' in filename :
cli_exe = z . read ( filename )
else :
cli_exe = os . path . join ( setuptools_egg , ' setuptools ' , ' cli.exe ' )
tahoe_exe = os . path . join ( " bin " , " tahoe.exe " )
if os . path . isfile ( setuptools_egg ) :
f = open ( tahoe_exe , ' wb ' )
f . write ( cli_exe )
f . close ( )
else :
shutil . copy ( cli_exe , tahoe_exe )
2009-01-29 01:07:16 +00:00
else :
try :
os . remove ( os . path . join ( ' bin ' , ' tahoe ' ) )
except :
# okay, probably it was already gone
pass
os . symlink ( ' tahoe-script.py ' , os . path . join ( ' bin ' , ' tahoe ' ) )
# chmod +x bin/tahoe-script.py
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 )
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-02-19 06:57:51 +00:00
# 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.
2008-09-12 01:03:21 +00:00
from _auto_deps import install_requires
2008-01-01 06:28:31 +00:00
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
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 )
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 ' ,
2007-04-27 20:47:15 +00:00
author_email = ' tahoe-dev@allmydata.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 ,
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.
2009-08-18 01:00:57 +00:00
* * setup_args
2007-04-27 20:47:15 +00:00
)