| 1 | 1 patch for repository http://tahoe-lafs.org/source/tahoe-lafs/trunk: |
|---|
| 2 | |
|---|
| 3 | Mon Feb 21 01:58:17 GMT Standard Time 2011 david-sarah@jacaranda.org |
|---|
| 4 | * Add unit tests for cross_check_pkg_resources_versus_import, and a regression test for ref #1355. This requires a little refactoring to make it testable. |
|---|
| 5 | |
|---|
| 6 | New patches: |
|---|
| 7 | |
|---|
| 8 | [Add unit tests for cross_check_pkg_resources_versus_import, and a regression test for ref #1355. This requires a little refactoring to make it testable. |
|---|
| 9 | david-sarah@jacaranda.org**20110221015817 |
|---|
| 10 | Ignore-this: 51d181698f8c20d3aca58b057e9c475a |
|---|
| 11 | ] { |
|---|
| 12 | hunk ./src/allmydata/__init__.py 254 |
|---|
| 13 | import pkg_resources |
|---|
| 14 | from _auto_deps import install_requires |
|---|
| 15 | |
|---|
| 16 | + pkg_resources_vers_and_locs = dict([(p.project_name.lower(), (str(p.version), p.location)) |
|---|
| 17 | + for p in pkg_resources.require(install_requires)]) |
|---|
| 18 | + |
|---|
| 19 | + return cross_check(pkg_resources_vers_and_locs, _vers_and_locs_list) |
|---|
| 20 | + |
|---|
| 21 | + |
|---|
| 22 | +def cross_check(pkg_resources_vers_and_locs, imported_vers_and_locs_list): |
|---|
| 23 | + """This function returns a list of errors due to any failed cross-checks.""" |
|---|
| 24 | + |
|---|
| 25 | errors = [] |
|---|
| 26 | not_pkg_resourceable = set(['sqlite3', 'python', 'platform', __appname__.lower()]) |
|---|
| 27 | not_import_versionable = set(['zope.interface', 'mock', 'pyasn1']) |
|---|
| 28 | hunk ./src/allmydata/__init__.py 268 |
|---|
| 29 | ignorable = set(['argparse', 'pyutil', 'zbase32', 'distribute']) |
|---|
| 30 | |
|---|
| 31 | - pkg_resources_vers_and_locs = dict([(p.project_name.lower(), (str(p.version), p.location)) |
|---|
| 32 | - for p in pkg_resources.require(install_requires)]) |
|---|
| 33 | - |
|---|
| 34 | - for name, (imp_ver, imp_loc, imp_comment) in _vers_and_locs_list: |
|---|
| 35 | + for name, (imp_ver, imp_loc, imp_comment) in imported_vers_and_locs_list: |
|---|
| 36 | name = name.lower() |
|---|
| 37 | if name not in not_pkg_resourceable: |
|---|
| 38 | if name not in pkg_resources_vers_and_locs: |
|---|
| 39 | hunk ./src/allmydata/__init__.py 315 |
|---|
| 40 | "by pkg_resources, but version %s (normalized to %s, from %r) by import." |
|---|
| 41 | % (name, pr_ver, str(pr_normver), pr_loc, imp_ver, str(imp_normver), imp_loc)) |
|---|
| 42 | |
|---|
| 43 | - imported_packages = set([p.lower() for (p, _) in _vers_and_locs_list]) |
|---|
| 44 | + imported_packages = set([p.lower() for (p, _) in imported_vers_and_locs_list]) |
|---|
| 45 | for pr_name, (pr_ver, pr_loc) in pkg_resources_vers_and_locs.iteritems(): |
|---|
| 46 | if pr_name not in imported_packages and pr_name not in ignorable: |
|---|
| 47 | errors.append("Warning: dependency %s (version %s) found by pkg_resources not found by import." |
|---|
| 48 | hunk ./src/allmydata/test/test_version.py 4 |
|---|
| 49 | |
|---|
| 50 | from twisted.trial import unittest |
|---|
| 51 | |
|---|
| 52 | -from allmydata import check_requirement, PackagingError |
|---|
| 53 | +from allmydata import check_requirement, cross_check, PackagingError |
|---|
| 54 | from allmydata.util.verlib import NormalizedVersion as V, \ |
|---|
| 55 | IrrationalVersionError, \ |
|---|
| 56 | suggest_normalized_version as suggest |
|---|
| 57 | hunk ./src/allmydata/test/test_version.py 33 |
|---|
| 58 | self.failUnlessRaises(ImportError, check_requirement, |
|---|
| 59 | "foo >= 1.0", {"foo": (None, None, "foomodule")}) |
|---|
| 60 | |
|---|
| 61 | + def test_cross_check_ticket_1355(self): |
|---|
| 62 | + # The bug in #1355 is triggered when a version string from either pkg_resources or import |
|---|
| 63 | + # is not parseable at all by normalized_version. |
|---|
| 64 | + |
|---|
| 65 | + res = cross_check({"foo": ("unparseable", "")}, [("foo", ("1.0", "", None))]) |
|---|
| 66 | + self.failUnlessEqual(len(res), 1) |
|---|
| 67 | + self.failUnlessIn("by pkg_resources could not be parsed", res[0]) |
|---|
| 68 | + |
|---|
| 69 | + res = cross_check({"foo": ("1.0", "")}, [("foo", ("unparseable", "", None))]) |
|---|
| 70 | + self.failUnlessEqual(len(res), 1) |
|---|
| 71 | + self.failUnlessIn(") could not be parsed", res[0]) |
|---|
| 72 | + |
|---|
| 73 | + def test_cross_check(self): |
|---|
| 74 | + res = cross_check({}, []) |
|---|
| 75 | + self.failUnlessEqual(res, []) |
|---|
| 76 | + |
|---|
| 77 | + res = cross_check({}, [("sqlite3", ("1.0", "", "blah"))]) |
|---|
| 78 | + self.failUnlessEqual(res, []) |
|---|
| 79 | + |
|---|
| 80 | + res = cross_check({"foo": ("unparseable", "")}, []) |
|---|
| 81 | + self.failUnlessEqual(len(res), 1) |
|---|
| 82 | + self.failUnlessIn("not found by import", res[0]) |
|---|
| 83 | + |
|---|
| 84 | + res = cross_check({"argparse": ("unparseable", "")}, []) |
|---|
| 85 | + self.failUnlessEqual(len(res), 0) |
|---|
| 86 | + |
|---|
| 87 | + res = cross_check({}, [("foo", ("unparseable", "", None))]) |
|---|
| 88 | + self.failUnlessEqual(len(res), 1) |
|---|
| 89 | + self.failUnlessIn("not found by pkg_resources", res[0]) |
|---|
| 90 | + |
|---|
| 91 | + res = cross_check({"distribute": ("1.0", "/somewhere")}, [("setuptools", ("2.0", "/somewhere", "distribute"))]) |
|---|
| 92 | + self.failUnlessEqual(len(res), 0) |
|---|
| 93 | + |
|---|
| 94 | + res = cross_check({"distribute": ("1.0", "/somewhere")}, [("setuptools", ("2.0", "/somewhere", None))]) |
|---|
| 95 | + self.failUnlessEqual(len(res), 1) |
|---|
| 96 | + self.failUnlessIn("location mismatch", res[0]) |
|---|
| 97 | + |
|---|
| 98 | + res = cross_check({"distribute": ("1.0", "/somewhere")}, [("setuptools", ("2.0", "/somewhere_different", None))]) |
|---|
| 99 | + self.failUnlessEqual(len(res), 1) |
|---|
| 100 | + self.failUnlessIn("location mismatch", res[0]) |
|---|
| 101 | + |
|---|
| 102 | + res = cross_check({"zope.interface": ("1.0", "")}, [("zope.interface", ("unknown", "", None))]) |
|---|
| 103 | + self.failUnlessEqual(len(res), 0) |
|---|
| 104 | + |
|---|
| 105 | + res = cross_check({"foo": ("1.0", "")}, [("foo", ("unknown", "", None))]) |
|---|
| 106 | + self.failUnlessEqual(len(res), 1) |
|---|
| 107 | + self.failUnlessIn("could not find a version number", res[0]) |
|---|
| 108 | + |
|---|
| 109 | + # When pkg_resources and import both find a package, there is only a warning if both |
|---|
| 110 | + # the version and the path fail to match. |
|---|
| 111 | + |
|---|
| 112 | + res = cross_check({"foo": ("1.0", "/somewhere")}, [("foo", ("2.0", "/somewhere", None))]) |
|---|
| 113 | + self.failUnlessEqual(len(res), 0) |
|---|
| 114 | + |
|---|
| 115 | + res = cross_check({"foo": ("1.0", "/somewhere")}, [("foo", ("1.0", "/somewhere_different", None))]) |
|---|
| 116 | + self.failUnlessEqual(len(res), 0) |
|---|
| 117 | + |
|---|
| 118 | + res = cross_check({"foo": ("1.0-r123", "/somewhere")}, [("foo", ("1.0.post123", "/somewhere_different", None))]) |
|---|
| 119 | + self.failUnlessEqual(len(res), 0) |
|---|
| 120 | + |
|---|
| 121 | + res = cross_check({"foo": ("1.0", "/somewhere")}, [("foo", ("2.0", "/somewhere_different", None))]) |
|---|
| 122 | + self.failUnlessEqual(len(res), 1) |
|---|
| 123 | + self.failUnlessIn("but version '2.0'", res[0]) |
|---|
| 124 | + |
|---|
| 125 | |
|---|
| 126 | # based on https://bitbucket.org/tarek/distutilsversion/src/17df9a7d96ef/test_verlib.py |
|---|
| 127 | |
|---|
| 128 | } |
|---|
| 129 | |
|---|
| 130 | Context: |
|---|
| 131 | |
|---|
| 132 | [TAG allmydata-tahoe-1.8.2 |
|---|
| 133 | warner@lothar.com**20110131020101] |
|---|
| 134 | Patch bundle hash: |
|---|
| 135 | 63b353632f4e14321b0f14ce2568c156072624d9 |
|---|