3 # Allmydata Tahoe -- secure, distributed storage grid
5 # Copyright (C) 2008 Allmydata, Inc.
7 # This file is part of tahoe.
9 # See the docs/about.html file for licensing information.
11 import os, re, sys, stat, subprocess
13 ##### sys.path management
15 def pylibdir(prefixdir):
16 pyver = "python%d.%d" % (sys.version_info[:2])
17 if sys.platform == "win32":
18 return os.path.join(prefixdir, "Lib", "site-packages")
20 return os.path.join(prefixdir, "lib", pyver, "site-packages")
22 basedir = os.path.dirname(os.path.abspath(__file__))
23 supportlib = pylibdir(os.path.join(basedir, "support"))
25 for i in range(len(sys.argv)):
27 if arg == "build_tahoe":
29 sys.argv.extend(["develop", "--prefix=support", "--script-dir=support/bin"])
31 for i in range(len(sys.argv)):
34 if arg.startswith("--prefix="):
35 prefixdir = arg[len("--prefix="):]
37 if len(sys.argv) > i+1:
38 prefixdir = sys.argv[i+1]
41 libdir = pylibdir(prefixdir)
44 except EnvironmentError, le:
45 # Okay, maybe the dir was already there.
47 sys.path.append(libdir)
48 pp = os.environ.get('PYTHONPATH','').split(os.pathsep)
50 os.environ['PYTHONPATH'] = os.pathsep.join(pp)
52 if arg.startswith("build"):
54 bin_tahoe = os.path.join("bin", "tahoe")
55 old_mode = stat.S_IMODE(os.stat(bin_tahoe)[stat.ST_MODE])
56 new_mode = old_mode | (stat.S_IXUSR | stat.S_IRUSR |
57 stat.S_IXGRP | stat.S_IRGRP |
58 stat.S_IXOTH | stat.S_IROTH )
59 os.chmod(bin_tahoe, new_mode)
61 if arg.startswith("install") or arg.startswith("develop"):
62 if sys.platform == "linux2":
63 # workaround for tahoe #229 / setuptools #17, on debian
64 sys.argv.extend(["--site-dirs", "/var/lib/python-support/python%d.%d" % (sys.version_info[:2])])
65 elif sys.platform == "darwin":
66 # this probably only applies to leopard 10.5, possibly only 10.5.5
67 sd = "/System/Library/Frameworks/Python.framework/Versions/%d.%d/Extras/lib/python" % (sys.version_info[:2])
68 sys.argv.extend(["--site-dirs", sd])
71 from ez_setup import use_setuptools
75 # This invokes our own customized version of ez_setup.py to make sure that
76 # setuptools >= v0.6c8 (a.k.a. v0.6-final) is installed.
78 # setuptools < v0.6c8 doesn't handle eggs which get installed into the CWD
79 # as a result of being transitively depended on in a setup_requires, but
80 # then are needed for the installed code to run, i.e. in an
82 use_setuptools(download_delay=0, min_version="0.6c10dev")
84 from setuptools import find_packages, setup
85 from setuptools.command import sdist
86 from distutils.core import Command
89 pkg_resources.require('setuptools_trial')
90 from setuptools_trial.setuptools_trial import TrialTest
92 # Make the dependency-version-requirement, which is used by the Makefile at
93 # build-time, also available to the app at runtime:
95 shutil.copyfile("_auto_deps.py", os.path.join("src", "allmydata", "_auto_deps.py"))
98 "Development Status :: 5 - Production/Stable",
99 "Environment :: Console",
100 "Environment :: Web Environment",
101 "License :: OSI Approved :: GNU General Public License (GPL)",
102 "License :: DFSG approved",
103 "License :: Other/Proprietary License",
104 "Intended Audience :: Developers",
105 "Intended Audience :: End Users/Desktop",
106 "Intended Audience :: System Administrators",
107 "Operating System :: Microsoft",
108 "Operating System :: Microsoft :: Windows",
109 "Operating System :: Microsoft :: Windows :: Windows NT/2000",
110 "Operating System :: Unix",
111 "Operating System :: POSIX :: Linux",
112 "Operating System :: POSIX",
113 "Operating System :: MacOS :: MacOS X",
114 "Operating System :: OS Independent",
115 "Natural Language :: English",
116 "Programming Language :: C",
117 "Programming Language :: Python",
118 "Programming Language :: Python :: 2",
119 "Programming Language :: Python :: 2.4",
120 "Programming Language :: Python :: 2.5",
121 "Topic :: Utilities",
122 "Topic :: System :: Systems Administration",
123 "Topic :: System :: Filesystems",
124 "Topic :: System :: Distributed Computing",
125 "Topic :: Software Development :: Libraries",
126 "Topic :: Communications :: Usenet News",
127 "Topic :: System :: Archiving :: Backup",
128 "Topic :: System :: Archiving :: Mirroring",
129 "Topic :: System :: Archiving",
133 VERSIONFILE = "src/allmydata/_version.py"
136 verstrline = open(VERSIONFILE, "rt").read()
137 except EnvironmentError:
138 pass # Okay, there is no version file.
140 VSRE = r"^verstr = ['\"]([^'\"]*)['\"]"
141 mo = re.search(VSRE, verstrline, re.M)
145 print "unable to find version in %s" % (VERSIONFILE,)
146 raise RuntimeError("if %s.py exists, it is required to be well-formed" % (VERSIONFILE,))
149 """Welcome to the Tahoe project, a secure, decentralized, fault-tolerant
150 filesystem. All of the source code is available under a Free Software, Open
153 This filesystem is encrypted and spread over multiple peers in such a way that
154 it remains available even when some of the peers are unavailable,
155 malfunctioning, or malicious."""
160 # Nevow requires Twisted to setup, but doesn't declare that requirement in a way that enables
161 # setuptools to satisfy that requirement before Nevow's setup.py tried to "import twisted".
162 setup_requires.extend(['Twisted >= 2.4.0', 'setuptools_trial'])
164 # darcsver is needed only if you want "./setup.py darcsver" to write a new
165 # version stamp in src/allmydata/_version.py, with a version number derived from
167 # http://pypi.python.org/pypi/darcsver
168 if 'darcsver' in sys.argv[1:]:
169 setup_requires.append('darcsver >= 1.1.5')
171 # setuptools_trial is needed only if you want "./setup.py trial" to execute the tests.
172 # http://pypi.python.org/pypi/setuptools_trial
173 if 'trial' in sys.argv[1:]:
174 setup_requires.append('setuptools_trial >= 0.2')
176 # setuptools_darcs is required to produce complete distributions (such as with
177 # "sdist" or "bdist_egg"), unless there is a PKG-INFO file present which shows
178 # that this is itself a source distribution.
179 # http://pypi.python.org/pypi/setuptools_darcs
180 if not os.path.exists('PKG-INFO'):
181 setup_requires.append('setuptools_darcs >= 1.1.0')
183 class ShowSupportLib(Command):
185 def initialize_options(self):
187 def finalize_options(self):
190 # TODO: --quiet suppresses the 'running show_supportlib' message.
191 # Find a way to do this all the time.
192 print supportlib # TODO windowsy
194 class ShowPythonPath(Command):
196 def initialize_options(self):
198 def finalize_options(self):
201 # TODO: --quiet suppresses the 'running show_supportlib' message.
202 # Find a way to do this all the time.
203 print "PYTHONPATH=%s" % os.environ["PYTHONPATH"]
205 class RunWithPythonPath(Command):
206 description = "Run a subcommand with PYTHONPATH set appropriately"
208 user_options = [ ("python", "p",
209 "Treat command string as arguments to a python executable"),
210 ("command=", "c", "Command to be run"),
211 ("directory=", "d", "Directory to run the command in"),
213 boolean_options = ["python"]
215 def initialize_options(self):
218 self.directory = None
219 def finalize_options(self):
222 # os.environ['PYTHONPATH'] is already set by add_tahoe_paths, so we
223 # just need to exec() their command. We must require the command to
224 # be safe to split on whitespace, and have --python and --directory
225 # to make it easier to achieve this.
228 command.append(sys.executable)
230 command.extend(self.command.split())
232 raise RuntimeError("The --command argument is mandatory")
234 os.chdir(self.directory)
236 print "command =", " ".join(command)
237 rc = subprocess.call(command)
240 class CheckAutoDeps(Command):
242 def initialize_options(self):
244 def finalize_options(self):
248 _auto_deps.require_auto_deps()
251 class BuildTahoe(Command):
253 def initialize_options(self):
255 def finalize_options(self):
258 command = [sys.executable, "setup.py", "develop", "--prefix", "support"]
259 print "Command:", " ".join(command)
260 rc = subprocess.call(command)
262 print >>sys.stderr, "'setup.py develop' terminated by signal", -rc
265 print >>sys.stderr, "'setup.py develop' exited with rc", rc
268 class Trial(TrialTest):
269 # Custom sub-class of the TrialTest class from the setuptools_trial
270 # plugin so that we can ensure certain options are set by default.
273 # setup.py trial # run all tests
274 # setup.py trial -a allmydata.test.test_util # run some tests
275 # setup.py trial -a '--reporter=text allmydata.test.test_util' #other args
278 def initialize_options(self):
279 TrialTest.initialize_options(self)
281 # We want to set the reactor to 'poll', because of bug #402
282 # (twisted bug #3218).
283 if sys.platform in ("linux2", "cygwin"):
284 # poll on linux2 to avoid #402 problems with select
285 # poll on cygwin since selectreactor runs out of fds
286 self.reactor = "poll"
289 class MySdist(sdist.sdist):
290 """ A hook in the sdist command so that we can determine whether this the
291 tarball should be 'SUMO' or not, i.e. whether or not to include the
292 external dependency tarballs. Note that we always include
293 misc/dependencies/* in the tarball; --sumo controls whether tahoe-deps/*
297 user_options = sdist.sdist.user_options + \
299 "create a 'sumo' sdist which includes the contents of tahoe-deps/*"),
301 boolean_options = ['sumo']
303 def initialize_options(self):
304 sdist.sdist.initialize_options(self)
307 def make_distribution(self):
308 # add our extra files to the list just before building the
309 # tarball/zipfile. We override make_distribution() instead of run()
310 # because setuptools.command.sdist.run() does not lend itself to
311 # easy/robust subclassing (the code we need to add goes right smack
312 # in the middle of a 12-line method). If this were the distutils
313 # version, we'd override get_file_list().
316 # If '--sumo' was specified, include tahoe-deps/* in the sdist.
317 # We assume that the user has fetched the tahoe-deps.tar.gz
318 # tarball and unpacked it already.
319 self.filelist.extend([os.path.join("tahoe-deps", fn)
320 for fn in os.listdir("tahoe-deps")])
321 # In addition, we want the tarball/zipfile to have -SUMO in the
322 # name, and the unpacked directory to have -SUMO too. The easiest
323 # way to do this is to patch self.distribution and override the
324 # get_fullname() method. (an alternative is to modify
325 # self.distribution.metadata.version, but that also affects the
326 # contents of PKG-INFO).
327 fullname = self.distribution.get_fullname()
329 return fullname + "-SUMO"
330 self.distribution.get_fullname = get_fullname
332 return sdist.sdist.make_distribution(self)
334 # Tahoe's dependencies are managed by the find_links= entry in setup.cfg and
335 # the _auto_deps.install_requires list, which is used in the call to setup()
336 # at the end of this file
337 from _auto_deps import install_requires
339 setup(name='allmydata-tahoe',
341 description='secure, decentralized, fault-tolerant filesystem',
342 long_description=LONG_DESCRIPTION,
343 author='the allmydata.org Tahoe project',
344 author_email='tahoe-dev@allmydata.org',
345 url='http://allmydata.org/',
347 cmdclass={"show_supportlib": ShowSupportLib,
348 "show_pythonpath": ShowPythonPath,
349 "run_with_pythonpath": RunWithPythonPath,
350 "check_auto_deps": CheckAutoDeps,
351 "build_tahoe": BuildTahoe,
355 package_dir = {'':'src'},
356 packages=find_packages("src"),
357 classifiers=trove_classifiers,
358 test_suite="allmydata.test",
359 install_requires=install_requires,
360 include_package_data=True,
361 setup_requires=setup_requires,
362 entry_points = { 'console_scripts': [ 'tahoe = allmydata.scripts.runner:run' ] },
363 zip_safe=False, # We prefer unzipped for easier access.