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, shutil, stat, subprocess, sys, zipfile
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
87 from pkg_resources import require
89 # Make the dependency-version-requirement, which is used by the Makefile at
90 # build-time, also available to the app at runtime:
92 shutil.copyfile("_auto_deps.py", os.path.join("src", "allmydata", "_auto_deps.py"))
95 "Development Status :: 5 - Production/Stable",
96 "Environment :: Console",
97 "Environment :: Web Environment",
98 "License :: OSI Approved :: GNU General Public License (GPL)",
99 "License :: DFSG approved",
100 "License :: Other/Proprietary License",
101 "Intended Audience :: Developers",
102 "Intended Audience :: End Users/Desktop",
103 "Intended Audience :: System Administrators",
104 "Operating System :: Microsoft",
105 "Operating System :: Microsoft :: Windows",
106 "Operating System :: Microsoft :: Windows :: Windows NT/2000",
107 "Operating System :: Unix",
108 "Operating System :: POSIX :: Linux",
109 "Operating System :: POSIX",
110 "Operating System :: MacOS :: MacOS X",
111 "Operating System :: OS Independent",
112 "Natural Language :: English",
113 "Programming Language :: C",
114 "Programming Language :: Python",
115 "Programming Language :: Python :: 2",
116 "Programming Language :: Python :: 2.4",
117 "Programming Language :: Python :: 2.5",
118 "Topic :: Utilities",
119 "Topic :: System :: Systems Administration",
120 "Topic :: System :: Filesystems",
121 "Topic :: System :: Distributed Computing",
122 "Topic :: Software Development :: Libraries",
123 "Topic :: Communications :: Usenet News",
124 "Topic :: System :: Archiving :: Backup",
125 "Topic :: System :: Archiving :: Mirroring",
126 "Topic :: System :: Archiving",
130 VERSIONFILE = "src/allmydata/_version.py"
133 verstrline = open(VERSIONFILE, "rt").read()
134 except EnvironmentError:
135 pass # Okay, there is no version file.
137 VSRE = r"^verstr = ['\"]([^'\"]*)['\"]"
138 mo = re.search(VSRE, verstrline, re.M)
142 print "unable to find version in %s" % (VERSIONFILE,)
143 raise RuntimeError("if %s.py exists, it is required to be well-formed" % (VERSIONFILE,))
146 """Welcome to the Tahoe project, a secure, decentralized, fault-tolerant
147 filesystem. All of the source code is available under a Free Software, Open
150 This filesystem is encrypted and spread over multiple peers in such a way that
151 it remains available even when some of the peers are unavailable,
152 malfunctioning, or malicious."""
157 # Nevow requires Twisted to setup, but doesn't declare that requirement in a way that enables
158 # setuptools to satisfy that requirement before Nevow's setup.py tried to "import twisted".
159 setup_requires.extend(['Twisted >= 2.4.0', 'setuptools_trial'])
161 # darcsver is needed only if you want "./setup.py darcsver" to write a new
162 # version stamp in src/allmydata/_version.py, with a version number derived from
164 # http://pypi.python.org/pypi/darcsver
165 if 'darcsver' in sys.argv[1:]:
166 setup_requires.append('darcsver >= 1.1.5')
168 # setuptools_trial is needed only if you want "./setup.py trial" to execute the tests.
169 # http://pypi.python.org/pypi/setuptools_trial
170 if 'trial' in sys.argv[1:]:
171 setup_requires.append('setuptools_trial >= 0.2')
173 # setuptools_darcs is required to produce complete distributions (such as with
174 # "sdist" or "bdist_egg"), unless there is a PKG-INFO file present which shows
175 # that this is itself a source distribution.
176 # http://pypi.python.org/pypi/setuptools_darcs
177 if not os.path.exists('PKG-INFO'):
178 setup_requires.append('setuptools_darcs >= 1.1.0')
180 class ShowSupportLib(Command):
182 def initialize_options(self):
184 def finalize_options(self):
187 # TODO: --quiet suppresses the 'running show_supportlib' message.
188 # Find a way to do this all the time.
189 print supportlib # TODO windowsy
191 class ShowPythonPath(Command):
193 def initialize_options(self):
195 def finalize_options(self):
198 # TODO: --quiet suppresses the 'running show_supportlib' message.
199 # Find a way to do this all the time.
200 print "PYTHONPATH=%s" % os.environ["PYTHONPATH"]
202 class RunWithPythonPath(Command):
203 description = "Run a subcommand with PYTHONPATH set appropriately"
205 user_options = [ ("python", "p",
206 "Treat command string as arguments to a python executable"),
207 ("command=", "c", "Command to be run"),
208 ("directory=", "d", "Directory to run the command in"),
210 boolean_options = ["python"]
212 def initialize_options(self):
215 self.directory = None
216 def finalize_options(self):
219 # os.environ['PYTHONPATH'] is already set by add_tahoe_paths, so we
220 # just need to exec() their command. We must require the command to
221 # be safe to split on whitespace, and have --python and --directory
222 # to make it easier to achieve this.
225 command.append(sys.executable)
227 command.extend(self.command.split())
229 raise RuntimeError("The --command argument is mandatory")
231 os.chdir(self.directory)
233 print "command =", " ".join(command)
234 rc = subprocess.call(command)
237 class CheckAutoDeps(Command):
239 def initialize_options(self):
241 def finalize_options(self):
245 _auto_deps.require_auto_deps()
248 class BuildTahoe(Command):
250 def initialize_options(self):
252 def finalize_options(self):
255 # On Windows, create the 'tahoe-script.py' file based on the 'tahoe'
256 # executable script under the 'bin' directory so that the tahoe.exe
257 # will work correctly. The 'tahoe-script.py' file is exactly the same
258 # as the 'tahoe' script except that we need to update the she-bang
259 # line. The tahoe.exe will be copied from the setuptools egg's cli.exe
260 # and this will work from a zip-safe and non-zip-safe setuptools egg.
261 if sys.platform == "win32":
262 setuptools_egg = require("setuptools")[0].location
263 if os.path.isfile(setuptools_egg):
264 z = zipfile.ZipFile(setuptools_egg, 'r')
265 for filename in z.namelist():
266 if 'cli.exe' in filename:
267 cli_exe = z.read(filename)
269 cli_exe = os.path.join(setuptools_egg, 'setuptools', 'cli.exe')
270 tahoe_exe = os.path.join("bin", "tahoe.exe")
271 if os.path.isfile(setuptools_egg):
272 f = open(tahoe_exe, 'wb')
276 shutil.copy(cli_exe, tahoe_exe)
277 bin_tahoe = os.path.join("bin", "tahoe")
278 f = open(bin_tahoe, "r")
279 script_lines = f.readlines()
281 script_lines[0] = "#!%s\n" % sys.executable
282 tahoe_script = os.path.join("bin", "tahoe-script.py")
283 f = open(tahoe_script, "w")
284 for line in script_lines:
288 command = [sys.executable, "setup.py", "develop", "--prefix", "support"]
289 print "Command:", " ".join(command)
290 rc = subprocess.call(command)
292 print >>sys.stderr, "'setup.py develop' terminated by signal", -rc
295 print >>sys.stderr, "'setup.py develop' exited with rc", rc
298 class MySdist(sdist.sdist):
299 """ A hook in the sdist command so that we can determine whether this the
300 tarball should be 'SUMO' or not, i.e. whether or not to include the
301 external dependency tarballs. Note that we always include
302 misc/dependencies/* in the tarball; --sumo controls whether tahoe-deps/*
306 user_options = sdist.sdist.user_options + \
308 "create a 'sumo' sdist which includes the contents of tahoe-deps/*"),
310 boolean_options = ['sumo']
312 def initialize_options(self):
313 sdist.sdist.initialize_options(self)
316 def make_distribution(self):
317 # add our extra files to the list just before building the
318 # tarball/zipfile. We override make_distribution() instead of run()
319 # because setuptools.command.sdist.run() does not lend itself to
320 # easy/robust subclassing (the code we need to add goes right smack
321 # in the middle of a 12-line method). If this were the distutils
322 # version, we'd override get_file_list().
325 # If '--sumo' was specified, include tahoe-deps/* in the sdist.
326 # We assume that the user has fetched the tahoe-deps.tar.gz
327 # tarball and unpacked it already.
328 self.filelist.extend([os.path.join("tahoe-deps", fn)
329 for fn in os.listdir("tahoe-deps")])
330 # In addition, we want the tarball/zipfile to have -SUMO in the
331 # name, and the unpacked directory to have -SUMO too. The easiest
332 # way to do this is to patch self.distribution and override the
333 # get_fullname() method. (an alternative is to modify
334 # self.distribution.metadata.version, but that also affects the
335 # contents of PKG-INFO).
336 fullname = self.distribution.get_fullname()
338 return fullname + "-SUMO"
339 self.distribution.get_fullname = get_fullname
341 return sdist.sdist.make_distribution(self)
343 # Tahoe's dependencies are managed by the find_links= entry in setup.cfg and
344 # the _auto_deps.install_requires list, which is used in the call to setup()
345 # at the end of this file
346 from _auto_deps import install_requires
348 setup(name='allmydata-tahoe',
350 description='secure, decentralized, fault-tolerant filesystem',
351 long_description=LONG_DESCRIPTION,
352 author='the allmydata.org Tahoe project',
353 author_email='tahoe-dev@allmydata.org',
354 url='http://allmydata.org/',
356 cmdclass={"show_supportlib": ShowSupportLib,
357 "show_pythonpath": ShowPythonPath,
358 "run_with_pythonpath": RunWithPythonPath,
359 "check_auto_deps": CheckAutoDeps,
360 "build_tahoe": BuildTahoe,
363 package_dir = {'':'src'},
364 packages=find_packages("src"),
365 classifiers=trove_classifiers,
366 test_suite="allmydata.test",
367 install_requires=install_requires,
368 include_package_data=True,
369 setup_requires=setup_requires,
370 entry_points = { 'console_scripts': [ 'tahoe = allmydata.scripts.runner:run' ] },
371 zip_safe=False, # We prefer unzipped for easier access.