#! /usr/bin/env python # -*- coding: utf-8 -*- import sys; assert sys.version_info < (3,), ur"Tahoe-LAFS does not run under Python 3. Please use Python 2.7.x." # Tahoe-LAFS -- secure, distributed storage grid # # Copyright © 2006-2012 The Tahoe-LAFS Software Foundation # # This file is part of Tahoe-LAFS. # # See the docs/about.rst file for licensing information. import os, subprocess, re ##### sys.path management basedir = os.path.dirname(os.path.abspath(__file__)) # 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_PY_FILENAME = 'src/allmydata/_version.py' version = read_version_py(VERSION_PY_FILENAME) 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) # 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'] setup_requires = adglobals['setup_requires'] if len(sys.argv) > 1 and sys.argv[1] == '--fakedependency': del sys.argv[1] install_requires += ["fakedependency >= 1.0.0"] from setuptools import setup from setuptools import Command from setuptools.command import install trove_classifiers=[ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Environment :: Web Environment", "License :: OSI Approved :: GNU General Public License (GPL)", "License :: DFSG approved", "License :: Other/Proprietary License", "Intended Audience :: Developers", "Intended Audience :: End Users/Desktop", "Intended Audience :: System Administrators", "Operating System :: Microsoft", "Operating System :: Microsoft :: Windows", "Operating System :: Unix", "Operating System :: POSIX :: Linux", "Operating System :: POSIX", "Operating System :: MacOS :: MacOS X", "Operating System :: OS Independent", "Natural Language :: English", "Programming Language :: C", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Topic :: Utilities", "Topic :: System :: Systems Administration", "Topic :: System :: Filesystems", "Topic :: System :: Distributed Computing", "Topic :: Software Development :: Libraries", "Topic :: System :: Archiving :: Backup", "Topic :: System :: Archiving :: Mirroring", "Topic :: System :: Archiving", ] # We no longer have any requirements specific to tests. tests_require=[] class Trial(Command): description = "run trial (use 'bin%stahoe debug trial' for the full set of trial options)" % (os.sep,) # This is just a subset of the most useful options, for compatibility. user_options = [ ("no-rterrors", None, "Don't print out tracebacks as they occur."), ("rterrors", "e", "Print out tracebacks as they occur (default, so ignored)."), ("until-failure", "u", "Repeat a test (specified by -s) until it fails."), ("reporter=", None, "The reporter to use for this test run."), ("suite=", "s", "Specify the test suite."), ("quiet", None, "Don't display version numbers and paths of Tahoe dependencies."), ("coverage", "c", "Collect branch coverage information."), ] def initialize_options(self): self.rterrors = False self.no_rterrors = False self.until_failure = False self.reporter = None self.suite = "allmydata" self.quiet = False self.coverage = False def finalize_options(self): pass def run(self): args = [sys.executable, os.path.join('bin', 'tahoe')] if self.coverage: from errno import ENOENT coverage_cmd = 'coverage' try: subprocess.call([coverage_cmd, 'help']) except OSError as e: if e.errno != ENOENT: raise coverage_cmd = 'python-coverage' try: rc = subprocess.call([coverage_cmd, 'help']) except OSError as e: if e.errno != ENOENT: raise print >>sys.stderr print >>sys.stderr, "Couldn't find the command 'coverage' nor 'python-coverage'." print >>sys.stderr, "coverage can be installed using 'pip install coverage', or on Debian-based systems, 'apt-get install python-coverage'." sys.exit(1) args += ['@' + coverage_cmd, 'run', '--branch', '--source=src/allmydata', '@tahoe'] if not self.quiet: args.append('--version-and-path') args += ['debug', 'trial'] if self.rterrors and self.no_rterrors: raise AssertionError("--rterrors and --no-rterrors conflict.") if not self.no_rterrors: args.append('--rterrors') if self.until_failure: args.append('--until-failure') if self.reporter: args.append('--reporter=' + self.reporter) if self.suite: args.append(self.suite) rc = subprocess.call(args) sys.exit(rc) GIT_VERSION_BODY = ''' # This _version.py is generated from git metadata by the tahoe setup.py. __pkgname__ = %(pkgname)r real_version = %(version)r full_version = %(full)r branch = %(branch)r verstr = %(normalized)r __version__ = verstr ''' def run_command(args, cwd=None): use_shell = sys.platform == "win32" try: p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd, shell=use_shell) except EnvironmentError as e: # if this gives a SyntaxError, note that Tahoe-LAFS requires Python 2.7+ print("Warning: unable to run %r." % (" ".join(args),)) print(e) return None stdout = p.communicate()[0].strip() if p.returncode != 0: print("Warning: %r returned error code %r." % (" ".join(args), p.returncode)) return None return stdout def versions_from_git(tag_prefix): # This runs 'git' from the directory that contains this file. That either # means someone ran a setup.py command (and this code is in # versioneer.py, thus the containing directory is the root of the source # tree), or someone ran a project-specific entry point (and this code is # in _version.py, thus the containing directory is somewhere deeper in # the source tree). This only gets called if the git-archive 'subst' # variables were *not* expanded, and _version.py hasn't already been # rewritten with a short version string, meaning we're inside a checked # out source tree. # versions_from_git (as copied from python-versioneer) returns strings # like "1.9.0-25-gb73aba9-dirty", which means we're in a tree with # uncommited changes (-dirty), the latest checkin is revision b73aba9, # the most recent tag was 1.9.0, and b73aba9 has 25 commits that weren't # in 1.9.0 . The narrow-minded NormalizedVersion parser that takes our # output (meant to enable sorting of version strings) refuses most of # that. Tahoe uses a function named suggest_normalized_version() that can # handle "1.9.0.post25", so dumb down our output to match. try: source_dir = os.path.dirname(os.path.abspath(__file__)) except NameError as e: # some py2exe/bbfreeze/non-CPython implementations don't do __file__ print("Warning: unable to find version because we could not obtain the source directory.") print(e) return {} stdout = run_command(["git", "describe", "--tags", "--dirty", "--always"], cwd=source_dir) if stdout is None: # run_command already complained. return {} if not stdout.startswith(tag_prefix): print("Warning: tag %r doesn't start with prefix %r." % (stdout, tag_prefix)) return {} version = stdout[len(tag_prefix):] pieces = version.split("-") if len(pieces) == 1: normalized_version = pieces[0] else: normalized_version = "%s.post%s" % (pieces[0], pieces[1]) stdout = run_command(["git", "rev-parse", "HEAD"], cwd=source_dir) if stdout is None: # run_command already complained. return {} full = stdout.strip() if version.endswith("-dirty"): full += "-dirty" normalized_version += ".dev0" # Thanks to Jistanidiot at . stdout = run_command(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=source_dir) branch = (stdout or "unknown").strip() return {"version": version, "normalized": normalized_version, "full": full, "branch": branch} # setup.cfg has an [aliases] section which runs "update_version" before many # commands (like "build" and "sdist") that need to know our package version # ahead of time. If you add different commands (or if we forgot some), you # may need to add it to setup.cfg and configure it to run update_version # before your command. class UpdateVersion(Command): description = "update _version.py from revision-control metadata" user_options = install.install.user_options def initialize_options(self): pass def finalize_options(self): pass def run(self): global version verstr = version if os.path.isdir(os.path.join(basedir, ".git")): verstr = self.try_from_git() if verstr: self.distribution.metadata.version = verstr else: print("""\ ******************************************************************** Warning: no version information found. This may cause tests to fail. ******************************************************************** """) def try_from_git(self): # If we change APPNAME, the release tag names should also change from then on. versions = versions_from_git(APPNAME + '-') if versions: f = open(VERSION_PY_FILENAME, "wb") f.write(GIT_VERSION_BODY % { "pkgname": self.distribution.get_name(), "version": versions["version"], "normalized": versions["normalized"], "full": versions["full"], "branch": versions["branch"], }) f.close() print("Wrote normalized version %r into '%s'" % (versions["normalized"], VERSION_PY_FILENAME)) return versions.get("normalized", None) setup_args = {} if version: setup_args["version"] = version setup(name=APPNAME, description='secure, decentralized, fault-tolerant file store', long_description=open('README.rst', 'rU').read(), author='the Tahoe-LAFS project', author_email='tahoe-dev@tahoe-lafs.org', url='https://tahoe-lafs.org/', license='GNU GPL', # see README.rst -- there is an alternative licence cmdclass={"trial": Trial, "update_version": UpdateVersion, }, package_dir = {'':'src'}, packages=['allmydata', 'allmydata.frontends', 'allmydata.immutable', 'allmydata.immutable.downloader', 'allmydata.introducer', 'allmydata.mutable', 'allmydata.scripts', 'allmydata.storage', 'allmydata.test', 'allmydata.util', 'allmydata.web', 'allmydata.windows', 'buildtest'], classifiers=trove_classifiers, test_suite="allmydata.test", install_requires=install_requires, tests_require=tests_require, package_data={"allmydata.web": ["*.xhtml", "static/*.js", "static/*.png", "static/*.css", "static/img/*.png", "static/css/*.css", ] }, setup_requires=setup_requires, entry_points = { 'console_scripts': [ 'tahoe = allmydata.scripts.runner:run' ] }, zip_safe=False, # We prefer unzipped for easier access. **setup_args )