From 348eecd615379965c60950335492f5d3ed2a16c4 Mon Sep 17 00:00:00 2001
From: Zooko O'Whielacronx <zooko@zooko.com>
Date: Tue, 22 Jan 2008 17:24:33 -0700
Subject: [PATCH] setup: require specific versions of dependencies, both at
 run-time (if pkg_resources is available) and at build-time, and make there be
 only once place where we specify those versions Using pkg_resources.require()
 like this also apparently allows people to install multiple different
 versions of packages on their system and tahoe (if pkg_resources is available
 to it) will import the version of the package that it requires.  I haven't
 tested this feature.

---
 Makefile                  |  6 ++++--
 _auto_deps.py             | 24 ++++++++++++++++++++++++
 setup.py                  | 20 ++++++++++++--------
 src/allmydata/__init__.py | 14 ++++++--------
 4 files changed, 46 insertions(+), 18 deletions(-)
 create mode 100644 _auto_deps.py

diff --git a/Makefile b/Makefile
index 15660a78..df7ea567 100644
--- a/Makefile
+++ b/Makefile
@@ -160,9 +160,11 @@ signal-error-pyopenssl-dep:
 	@echo
 	exit 1
 
-check-all-deps: check-deps
+check-auto-deps:
 	$(PP) \
-	 $(PYTHON) -c 'import allmydata, zfec, foolscap, simplejson, nevow, pycryptopp' || $(MAKE) signal-error-deps
+	 $(PYTHON) -c 'import _auto_deps ; _auto_deps.require_auto_deps()' || $(MAKE) signal-error-deps
+
+check-all-deps: check-deps check-auto-deps
 
 check-twisted-dep:
 	$(PYTHON) -c 'import twisted, zope.interface' || $(MAKE) signal-error-twisted-dep
diff --git a/_auto_deps.py b/_auto_deps.py
new file mode 100644
index 00000000..e505abba
--- /dev/null
+++ b/_auto_deps.py
@@ -0,0 +1,24 @@
+install_requires=["zfec >= 1.3.0",
+                  "foolscap >= 0.2.3",
+                  "simplejson >= 1.7.3",
+                  "pycryptopp >= 0.2.9",
+                  "nevow >= 0.6.0",
+                  "zope.interface >= 3.1.0",
+                  ]
+
+def require_auto_deps():
+    try:
+        import pkg_resources
+    except:
+        # Then we can't assert that the versions of these packages are the right
+        # versions, but we can still try to use them anyway...
+        pass
+    else:
+        for requirement in install_requires:
+            pkg_resources.require(requirement)
+    for requirement in install_requires:
+        name, cmpop, verstr = requirement.split()
+        __import__(name)
+
+if __name__ == "__main__":
+    require_auto_deps()
diff --git a/setup.py b/setup.py
index 8ede2810..dd0f2ea0 100644
--- a/setup.py
+++ b/setup.py
@@ -23,6 +23,16 @@ else:
 
 from setuptools import Extension, find_packages, setup
 
+# Make the dependency-version-requirement, which is used by the Makefile at
+# build-time, also available to the app at runtime:
+import shutil
+try:
+    shutil.copyfile("_auto_deps.py", os.path.join("src", "allmydata", "_auto_deps.py"))
+except EnvironmentError:
+    # Nevermind then -- perhaps it is already in place and in any case we can do
+    # without it.
+    pass
+
 trove_classifiers=[
     "Development Status :: 4 - Beta", 
     "Environment :: Console",
@@ -103,13 +113,7 @@ setup_requires.append('darcsver >= 1.0.0')
 if not os.path.exists('PKG-INFO'):
     setup_requires.append('setuptools_darcs >= 1.1.0')
 
-install_requires=["zfec >= 1.3.0",
-                  "foolscap >= 0.2.3",
-                  "simplejson >= 1.7.3",
-                  "pycryptopp >= 0.2.9",
-                  "nevow >= 0.6.0",
-                  "zope.interface >= 3.1.0",
-                  ]
+import _auto_deps
 
 setup(name='allmydata-tahoe',
       version=verstr,
@@ -123,7 +127,7 @@ setup(name='allmydata-tahoe',
       packages=find_packages("src"),
       classifiers=trove_classifiers,
       test_suite="allmydata.test",
-      install_requires=install_requires,
+      install_requires=_auto_deps.install_requires,
       include_package_data=True,
       setup_requires=setup_requires,
       dependency_links=dependency_links,
diff --git a/src/allmydata/__init__.py b/src/allmydata/__init__.py
index 2d6e7340..d67ec9b0 100644
--- a/src/allmydata/__init__.py
+++ b/src/allmydata/__init__.py
@@ -20,17 +20,15 @@ hush_pyflakes = __version__
 del hush_pyflakes
 
 try:
-    import pkg_resources
+    import _auto_deps
 except ImportError:
-    # nevermind
+    # Never mind -- even if we can't use pkg_resources to check the required
+    # version numbers and to select the right one in the case that more than one
+    # version is available, we can still barrel on and if "import thingie" gives
+    # us a thingie that works, we're okay.
     pass
 else:
-    pkg_resources.require("zfec >= 1.3.0")
-    pkg_resources.require("foolscap >= 0.2.3")
-    pkg_resources.require("simplejson >= 1.7.3")
-    pkg_resources.require("pycryptopp >= 0.2.9")
-    pkg_resources.require("nevow >= 0.6.0")
-    pkg_resources.require("zope.interface >= 3.1.0")
+    _auto_deps.require_auto_deps()
 
 def get_package_versions():
     import OpenSSL, allmydata, foolscap, nevow, pycryptopp, simplejson, twisted, zfec
-- 
2.45.2