From caa69b007e8a187c10276a034e03fd1618a0e555 Mon Sep 17 00:00:00 2001
From: Zooko O'Whielacronx <zooko@zooko.com>
Date: Wed, 12 Dec 2007 19:37:37 -0700
Subject: [PATCH] refactor the feature of getting versions of packages, include
 the version numbers of more of the packages that we use

---
 src/allmydata/__init__.py       | 26 ++++++++++++++++++++++++++
 src/allmydata/logpublisher.py   |  8 +++-----
 src/allmydata/node.py           | 17 ++---------------
 src/allmydata/scripts/common.py |  9 ++-------
 src/allmydata/webish.py         |  5 ++---
 5 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/src/allmydata/__init__.py b/src/allmydata/__init__.py
index 349c7e2e..793827ad 100644
--- a/src/allmydata/__init__.py
+++ b/src/allmydata/__init__.py
@@ -18,3 +18,29 @@ except ImportError:
 hush_pyflakes = __version__
 del hush_pyflakes
 
+def get_package_versions():
+    import OpenSSL, allmydata, foolscap, nevow, pycryptopp, setuptools, simplejson, twisted, zfec
+    return {
+        'pyopenssl': OpenSSL.__version__,
+        'allmydata': allmydata.__version__,
+        'foolscap': foolscap.__version__,
+        'nevow': nevow.__version__,
+        'pycryptopp': pycryptopp.__version__,
+        'setuptools': setuptools.__version__,
+        'simplejson': simplejson.__version__,
+        'twisted': twisted.__version__,
+        'zfec': zfec.__version__,
+        }
+
+def get_package_versions_string():
+    versions = get_package_versions()
+    res = []
+    for p in ["allmydata", "foolscap", "pycryptopp", "zfec", "twisted", "nevow"]:
+        if versions.has_key(p):
+            res.append(str(p) + ": " + str(versions[p]))
+            del versions[p]
+        else:
+            res.append(str(p) + ": UNKNOWN")
+    for p, v in versions.iteritems():
+        res.append(str(p) + ": " + str(v))
+    return ', '.join(res)
diff --git a/src/allmydata/logpublisher.py b/src/allmydata/logpublisher.py
index 5de90641..0718dcf7 100644
--- a/src/allmydata/logpublisher.py
+++ b/src/allmydata/logpublisher.py
@@ -5,6 +5,7 @@ from twisted.application import service
 from twisted.python import log
 from foolscap import Referenceable, RemoteInterface
 from foolscap.schema import DictOf, Any
+from allmydata import get_package_versions
 
 class RILogObserver(RemoteInterface):
     def msg(logmsg=DictOf(str, Any())):
@@ -67,12 +68,9 @@ class LogPublisher(Referenceable, service.MultiService):
         #f.close()
 
     def remote_get_versions(self):
-        versions = self.parent.get_versions()
-        # our __version__ attributes are actually instances of
-        # allmydata.util.version_class.Version, so convert them into strings
-        # first.
+        # Convert all the version instances to strings.
         return dict([(k,str(v))
-                     for k,v in versions.items()])
+                     for k,v in get_package_versions().iteritems()])
 
     def remote_subscribe_to_all(self, observer):
         s = Subscription()
diff --git a/src/allmydata/node.py b/src/allmydata/node.py
index 8989eef5..4c4ad3bc 100644
--- a/src/allmydata/node.py
+++ b/src/allmydata/node.py
@@ -7,14 +7,12 @@ from twisted.python import log
 from twisted.application import service
 from twisted.internet import defer, reactor
 from foolscap import Tub, eventual
+from allmydata import get_package_versions_string
 from allmydata.util import log as tahoe_log
 from allmydata.util import iputil, observer, humanreadable
 from allmydata.util.assertutil import precondition
 from allmydata.logpublisher import LogPublisher
 
-# Just to get their versions:
-import allmydata, foolscap, pycryptopp, zfec
-
 # group 1 will be addr (dotted quad string), group 3 if any will be portnum (string)
 ADDR_RE=re.compile("^([1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*)(:([1-9][0-9]*))?$")
 
@@ -72,10 +70,7 @@ class Node(service.MultiService):
                 self.log("AuthorizedKeysManhole listening on %d" % portnum)
 
         self.setup_logging()
-        self.log("Node constructed.  tahoe version: %s, foolscap: %s,"
-                 " twisted: %s, zfec: %s"
-                 % (allmydata.__version__, foolscap.__version__,
-                    twisted.__version__, zfec.__version__,))
+        self.log("Node constructed. " + get_package_versions_string())
         iputil.increase_rlimits()
 
     def get_config(self, name, mode="r", required=False):
@@ -128,14 +123,6 @@ class Node(service.MultiService):
             self.log("Unable to write config file '%s'" % fn)
             self.log(e)
 
-    def get_versions(self):
-        return {'allmydata': allmydata.__version__,
-                'foolscap': foolscap.__version__,
-                'twisted': twisted.__version__,
-                'zfec': zfec.__version__,
-                'pycryptopp': pycryptopp.__version__,
-                }
-
     def startService(self):
         # Note: this class can be started and stopped at most once.
         self.log("Node.startService")
diff --git a/src/allmydata/scripts/common.py b/src/allmydata/scripts/common.py
index b29d2b83..dd15fda8 100644
--- a/src/allmydata/scripts/common.py
+++ b/src/allmydata/scripts/common.py
@@ -10,13 +10,8 @@ class BaseOptions:
         ]
 
     def opt_version(self):
-        from twisted import copyright
-        import allmydata, zfec, foolscap, pycryptopp
-        print "Twisted version:", copyright.version
-        print "Foolscap version:", foolscap.__version__
-        print "zfec version:", zfec.__version__
-        print "allmydata version:", allmydata.__version__
-        print "pycryptopp version:", pycryptopp.__version__
+        import allmydata
+        print allmydata.get_package_versions_string()
         sys.exit(0)
 
 
diff --git a/src/allmydata/webish.py b/src/allmydata/webish.py
index 2db720d8..88a6c266 100644
--- a/src/allmydata/webish.py
+++ b/src/allmydata/webish.py
@@ -14,6 +14,7 @@ from allmydata.interfaces import IDownloadTarget, IDirectoryNode, IFileNode, \
      IMutableFileNode
 from allmydata import upload, download
 from allmydata import provisioning
+from allmydata import get_package_versions_string
 from zope.interface import implements, Interface
 import urllib
 from formless import webform
@@ -1303,9 +1304,7 @@ class Root(rend.Page):
     child_provisioning = provisioning.ProvisioningTool()
 
     def data_version(self, ctx, data):
-        v = IClient(ctx).get_versions()
-        return "tahoe: %s, zfec: %s, foolscap: %s, twisted: %s" % \
-               (v['allmydata'], v['zfec'], v['foolscap'], v['twisted'])
+        return get_package_versions_string()
 
     def data_my_nodeid(self, ctx, data):
         return b32encode(IClient(ctx).nodeid).lower()
-- 
2.45.2