From 7eb260a9cf6010a74ce8a0f11a19b98d9a95cbb0 Mon Sep 17 00:00:00 2001 From: Zooko O'Whielacronx Date: Wed, 11 Feb 2009 17:18:16 -0700 Subject: [PATCH] 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. --- setup.py | 15 ++++++++++++++- src/allmydata/__init__.py | 12 ++++++++++++ src/allmydata/client.py | 2 +- src/allmydata/immutable/offloaded.py | 6 +++--- src/allmydata/introducer/server.py | 2 +- src/allmydata/scripts/common_http.py | 4 ++-- src/allmydata/storage.py | 4 ++-- src/allmydata/test/test_client.py | 6 +++--- src/allmydata/test/test_upload.py | 6 +++--- 9 files changed, 41 insertions(+), 16 deletions(-) diff --git a/setup.py b/setup.py index 7183b684..acfd1046 100644 --- a/setup.py +++ b/setup.py @@ -302,7 +302,20 @@ class MySdist(sdist.sdist): # _auto_deps.install_requires list, which is used in the call to setup() below. from _auto_deps import install_requires -setup(name='allmydata-tahoe', +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) + +setup(name=APPNAME, description='secure, decentralized, fault-tolerant filesystem', long_description=LONG_DESCRIPTION, author='the allmydata.org Tahoe project', diff --git a/src/allmydata/__init__.py b/src/allmydata/__init__.py index a442d842..dacb8c6a 100644 --- a/src/allmydata/__init__.py +++ b/src/allmydata/__init__.py @@ -15,6 +15,18 @@ except ImportError: # not happen very often. pass +__appname__ = "unknown" +try: + from _appname import __appname__ +except ImportError: + # We're running in a tree that hasn't run "./setup.py". This shouldn't happen. + pass + +# __full_version__ is the one that you ought to use when identifying yourself in the +# "application" part of the Tahoe versioning scheme: +# http://allmydata.org/trac/tahoe/wiki/Versioning +__full_version__ = __appname__ + '-' + str(__version__) + hush_pyflakes = __version__ del hush_pyflakes diff --git a/src/allmydata/client.py b/src/allmydata/client.py index 10369bdf..73849c98 100644 --- a/src/allmydata/client.py +++ b/src/allmydata/client.py @@ -115,7 +115,7 @@ class Client(node.Node, pollmixin.PollMixin): self.introducer_furl = self.get_config("client", "introducer.furl") ic = IntroducerClient(self.tub, self.introducer_furl, self.nickname, - str(allmydata.__version__), + str(allmydata.__full_version__), str(self.OLDEST_SUPPORTED_VERSION)) self.introducer_client = ic # hold off on starting the IntroducerClient until our tub has been diff --git a/src/allmydata/immutable/offloaded.py b/src/allmydata/immutable/offloaded.py index 775b71e6..60a40624 100644 --- a/src/allmydata/immutable/offloaded.py +++ b/src/allmydata/immutable/offloaded.py @@ -5,7 +5,7 @@ from twisted.application import service from twisted.internet import defer from foolscap import Referenceable, DeadReferenceError from foolscap.eventual import eventually -import allmydata +import allmydata # for __full_version__ from allmydata import interfaces, storage, uri from allmydata.immutable import upload from allmydata.immutable.layout import ReadBucketProxy @@ -132,7 +132,7 @@ class CHKUploadHelper(Referenceable, upload.CHKUploader): implements(interfaces.RICHKUploadHelper) VERSION = { "http://allmydata.org/tahoe/protocols/helper/chk-upload/v1" : { }, - "application-version": str(allmydata.__version__), + "application-version": str(allmydata.__full_version__), } def __init__(self, storage_index, helper, @@ -492,7 +492,7 @@ class Helper(Referenceable, service.MultiService): name = "helper" VERSION = { "http://allmydata.org/tahoe/protocols/helper/v1" : { }, - "application-version": str(allmydata.__version__), + "application-version": str(allmydata.__full_version__), } chk_upload_helper_class = CHKUploadHelper MAX_UPLOAD_STATUSES = 10 diff --git a/src/allmydata/introducer/server.py b/src/allmydata/introducer/server.py index 3005b54d..5e519533 100644 --- a/src/allmydata/introducer/server.py +++ b/src/allmydata/introducer/server.py @@ -49,7 +49,7 @@ class IntroducerService(service.MultiService, Referenceable): name = "introducer" VERSION = { "http://allmydata.org/tahoe/protocols/introducer/v1": { }, - "application-version": str(allmydata.__version__), + "application-version": str(allmydata.__full_version__), } def __init__(self, basedir="."): diff --git a/src/allmydata/scripts/common_http.py b/src/allmydata/scripts/common_http.py index c654927b..0c7680e2 100644 --- a/src/allmydata/scripts/common_http.py +++ b/src/allmydata/scripts/common_http.py @@ -1,7 +1,7 @@ from cStringIO import StringIO import urlparse, httplib -import allmydata # for __version__ +import allmydata # for __full_version__ # copied from twisted/web/client.py def parse_url(url, defaultPort=None): @@ -44,7 +44,7 @@ def do_http(method, url, body=""): raise ValueError("unknown scheme '%s', need http or https" % scheme) c.putrequest(method, path) c.putheader("Hostname", host) - c.putheader("User-Agent", "tahoe_cli/%s" % allmydata.__version__) + c.putheader("User-Agent", "tahoe_cli/%s" % allmydata.__full_version__) c.putheader("Connection", "close") old = body.tell() diff --git a/src/allmydata/storage.py b/src/allmydata/storage.py index e2fbb4f8..ac6de53c 100644 --- a/src/allmydata/storage.py +++ b/src/allmydata/storage.py @@ -8,7 +8,7 @@ from allmydata.interfaces import RIStorageServer, RIBucketWriter, \ RIBucketReader, BadWriteEnablerError, IStatsProducer from allmydata.util import base32, fileutil, idlib, log, time_format from allmydata.util.assertutil import precondition -import allmydata # for __version__ +import allmydata # for __full_version__ class DataTooLargeError(Exception): pass @@ -968,7 +968,7 @@ class StorageServer(service.MultiService, Referenceable): "tolerates-immutable-read-overrun": True, "delete-mutable-shares-with-zero-length-writev": True, }, - "application-version": str(allmydata.__version__), + "application-version": str(allmydata.__full_version__), } return version diff --git a/src/allmydata/test/test_client.py b/src/allmydata/test/test_client.py index 099c40a7..f878101a 100644 --- a/src/allmydata/test/test_client.py +++ b/src/allmydata/test/test_client.py @@ -174,12 +174,12 @@ class Basic(unittest.TestCase): ss = c.getServiceNamed("storage") verdict = ss.remote_get_version() self.failUnlessEqual(verdict["application-version"], - str(allmydata.__version__)) + str(allmydata.__full_version__)) self.failIfEqual(str(allmydata.__version__), "unknown") - self.failUnless("." in str(allmydata.__version__), + self.failUnless("." in str(allmydata.__full_version__), "non-numeric version in '%s'" % allmydata.__version__) all_versions = allmydata.get_package_versions_string() - self.failUnless("allmydata" in all_versions) + self.failUnless("allmydata-tahoe" in all_versions) log.msg("tahoe versions: %s" % all_versions) # also test stats stats = c.get_stats() diff --git a/src/allmydata/test/test_upload.py b/src/allmydata/test/test_upload.py index 42c56101..8ed01e2c 100644 --- a/src/allmydata/test/test_upload.py +++ b/src/allmydata/test/test_upload.py @@ -7,7 +7,7 @@ from twisted.python import log from twisted.internet import defer from foolscap import eventual -import allmydata +import allmydata # for __full_version__ from allmydata import uri, monitor from allmydata.immutable import upload from allmydata.interfaces import IFileURI, FileTooLargeError, NotEnoughSharesError @@ -84,12 +84,12 @@ class FakeStorageServer: self.queries = 0 self.version = { "http://allmydata.org/tahoe/protocols/storage/v1" : { "maximum-immutable-share-size": 2**32 }, - "application-version": str(allmydata.__version__), + "application-version": str(allmydata.__full_version__), } if mode == "small": self.version = { "http://allmydata.org/tahoe/protocols/storage/v1" : { "maximum-immutable-share-size": 10 }, - "application-version": str(allmydata.__version__), + "application-version": str(allmydata.__full_version__), } -- 2.37.2