| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 |  | 
| 2 import md5 |  | 
| 3 import os |  | 
| 4 import shutil |  | 
| 5 |  | 
| 6 from twisted.python import util |  | 
| 7 from twisted.trial.test import packages |  | 
| 8 from twisted.trial import runner, reporter, unittest |  | 
| 9 from twisted.trial.itrial import ITestCase |  | 
| 10 |  | 
| 11 from twisted.python.modules import getModule |  | 
| 12 |  | 
| 13 |  | 
| 14 |  | 
| 15 def testNames(tests): |  | 
| 16     """ |  | 
| 17     Return the id of each test within the given test suite or case. |  | 
| 18     """ |  | 
| 19     names = [] |  | 
| 20     for test in unittest._iterateTests(tests): |  | 
| 21         names.append(test.id()) |  | 
| 22     return names |  | 
| 23 |  | 
| 24 |  | 
| 25 |  | 
| 26 class FinderTest(packages.PackageTest): |  | 
| 27     def setUp(self): |  | 
| 28         packages.PackageTest.setUp(self) |  | 
| 29         self.loader = runner.TestLoader() |  | 
| 30 |  | 
| 31     def tearDown(self): |  | 
| 32         packages.PackageTest.tearDown(self) |  | 
| 33 |  | 
| 34     def test_findPackage(self): |  | 
| 35         sample1 = self.loader.findByName('twisted') |  | 
| 36         import twisted as sample2 |  | 
| 37         self.failUnlessEqual(sample1, sample2) |  | 
| 38 |  | 
| 39     def test_findModule(self): |  | 
| 40         sample1 = self.loader.findByName('twisted.trial.test.sample') |  | 
| 41         import sample as sample2 |  | 
| 42         self.failUnlessEqual(sample1, sample2) |  | 
| 43 |  | 
| 44     def test_findFile(self): |  | 
| 45         path = util.sibpath(__file__, 'sample.py') |  | 
| 46         sample1 = self.loader.findByName(path) |  | 
| 47         import sample as sample2 |  | 
| 48         self.failUnlessEqual(sample1, sample2) |  | 
| 49 |  | 
| 50     def test_findObject(self): |  | 
| 51         sample1 = self.loader.findByName('twisted.trial.test.sample.FooTest') |  | 
| 52         import sample |  | 
| 53         self.failUnlessEqual(sample.FooTest, sample1) |  | 
| 54 |  | 
| 55     def test_findNonModule(self): |  | 
| 56         self.failUnlessRaises(AttributeError, |  | 
| 57                               self.loader.findByName, |  | 
| 58                               'twisted.trial.test.nonexistent') |  | 
| 59 |  | 
| 60     def test_findNonPackage(self): |  | 
| 61         self.failUnlessRaises(ValueError, |  | 
| 62                               self.loader.findByName, |  | 
| 63                               'nonextant') |  | 
| 64 |  | 
| 65     def test_findNonFile(self): |  | 
| 66         path = util.sibpath(__file__, 'nonexistent.py') |  | 
| 67         self.failUnlessRaises(ValueError, self.loader.findByName, path) |  | 
| 68 |  | 
| 69 |  | 
| 70 |  | 
| 71 class FileTest(packages.SysPathManglingTest): |  | 
| 72     def test_notFile(self): |  | 
| 73         self.failUnlessRaises(ValueError, |  | 
| 74                               runner.filenameToModule, 'doesntexist') |  | 
| 75 |  | 
| 76     def test_moduleInPath(self): |  | 
| 77         sample1 = runner.filenameToModule(util.sibpath(__file__, 'sample.py')) |  | 
| 78         import sample as sample2 |  | 
| 79         self.failUnlessEqual(sample2, sample1) |  | 
| 80 |  | 
| 81     def test_moduleNotInPath(self): |  | 
| 82         self.mangleSysPath(self.oldPath) |  | 
| 83         sample1 = runner.filenameToModule(os.path.join(self.parent, |  | 
| 84                                                        'goodpackage', |  | 
| 85                                                        'test_sample.py')) |  | 
| 86         self.mangleSysPath(self.newPath) |  | 
| 87         from goodpackage import test_sample as sample2 |  | 
| 88         self.failUnlessEqual(os.path.splitext(sample2.__file__)[0], |  | 
| 89                              os.path.splitext(sample1.__file__)[0]) |  | 
| 90 |  | 
| 91     def test_packageInPath(self): |  | 
| 92         package1 = runner.filenameToModule(os.path.join(self.parent, |  | 
| 93                                                         'goodpackage')) |  | 
| 94         import goodpackage |  | 
| 95         self.failUnlessEqual(goodpackage, package1) |  | 
| 96 |  | 
| 97     def test_packageNotInPath(self): |  | 
| 98         self.mangleSysPath(self.oldPath) |  | 
| 99         package1 = runner.filenameToModule(os.path.join(self.parent, |  | 
| 100                                                         'goodpackage')) |  | 
| 101         self.mangleSysPath(self.newPath) |  | 
| 102         import goodpackage |  | 
| 103         self.failUnlessEqual(os.path.splitext(goodpackage.__file__)[0], |  | 
| 104                              os.path.splitext(package1.__file__)[0]) |  | 
| 105 |  | 
| 106     def test_directoryNotPackage(self): |  | 
| 107         self.failUnlessRaises(ValueError, runner.filenameToModule, |  | 
| 108                               util.sibpath(__file__, 'directory')) |  | 
| 109 |  | 
| 110     def test_filenameNotPython(self): |  | 
| 111         self.failUnlessRaises(ValueError, runner.filenameToModule, |  | 
| 112                               util.sibpath(__file__, 'notpython.py')) |  | 
| 113 |  | 
| 114     def test_filenameMatchesPackage(self): |  | 
| 115         filename = os.path.join(self.parent, 'goodpackage.py') |  | 
| 116         fd = open(filename, 'w') |  | 
| 117         fd.write(packages.testModule) |  | 
| 118         fd.close() |  | 
| 119         try: |  | 
| 120             module = runner.filenameToModule(filename) |  | 
| 121             self.failUnlessEqual(filename, module.__file__) |  | 
| 122         finally: |  | 
| 123             os.remove(filename) |  | 
| 124 |  | 
| 125     def test_directory(self): |  | 
| 126         """ |  | 
| 127         Test loader against a filesystem directory. It should handle |  | 
| 128         'path' and 'path/' the same way. |  | 
| 129         """ |  | 
| 130         path  = util.sibpath(__file__, 'goodDirectory') |  | 
| 131         os.mkdir(path) |  | 
| 132         f = file(os.path.join(path, '__init__.py'), "w") |  | 
| 133         f.close() |  | 
| 134         try: |  | 
| 135             module = runner.filenameToModule(path) |  | 
| 136             self.assert_(module.__name__.endswith('goodDirectory')) |  | 
| 137             module = runner.filenameToModule(path + os.path.sep) |  | 
| 138             self.assert_(module.__name__.endswith('goodDirectory')) |  | 
| 139         finally: |  | 
| 140             shutil.rmtree(path) |  | 
| 141 |  | 
| 142 |  | 
| 143 |  | 
| 144 class LoaderTest(packages.SysPathManglingTest): |  | 
| 145 |  | 
| 146     def setUp(self): |  | 
| 147         self.loader = runner.TestLoader() |  | 
| 148         packages.SysPathManglingTest.setUp(self) |  | 
| 149 |  | 
| 150     def test_sortCases(self): |  | 
| 151         import sample |  | 
| 152         suite = self.loader.loadClass(sample.AlphabetTest) |  | 
| 153         self.failUnlessEqual(['test_a', 'test_b', 'test_c'], |  | 
| 154                              [test._testMethodName for test in suite._tests]) |  | 
| 155         newOrder = ['test_b', 'test_c', 'test_a'] |  | 
| 156         sortDict = dict(zip(newOrder, range(3))) |  | 
| 157         self.loader.sorter = lambda x : sortDict.get(x.shortDescription(), -1) |  | 
| 158         suite = self.loader.loadClass(sample.AlphabetTest) |  | 
| 159         self.failUnlessEqual(newOrder, |  | 
| 160                              [test._testMethodName for test in suite._tests]) |  | 
| 161 |  | 
| 162     def test_loadMethod(self): |  | 
| 163         import sample |  | 
| 164         suite = self.loader.loadMethod(sample.FooTest.test_foo) |  | 
| 165         self.failUnlessEqual(1, suite.countTestCases()) |  | 
| 166         self.failUnlessEqual('test_foo', suite._testMethodName) |  | 
| 167 |  | 
| 168     def test_loadFailingMethod(self): |  | 
| 169         # test added for issue1353 |  | 
| 170         import erroneous |  | 
| 171         suite = self.loader.loadMethod(erroneous.TestRegularFail.test_fail) |  | 
| 172         result = reporter.TestResult() |  | 
| 173         suite.run(result) |  | 
| 174         self.failUnlessEqual(result.testsRun, 1) |  | 
| 175         self.failUnlessEqual(len(result.failures), 1) |  | 
| 176 |  | 
| 177     def test_loadNonMethod(self): |  | 
| 178         import sample |  | 
| 179         self.failUnlessRaises(TypeError, self.loader.loadMethod, sample) |  | 
| 180         self.failUnlessRaises(TypeError, |  | 
| 181                               self.loader.loadMethod, sample.FooTest) |  | 
| 182         self.failUnlessRaises(TypeError, self.loader.loadMethod, "string") |  | 
| 183         self.failUnlessRaises(TypeError, |  | 
| 184                               self.loader.loadMethod, ('foo', 'bar')) |  | 
| 185 |  | 
| 186     def test_loadClass(self): |  | 
| 187         import sample |  | 
| 188         suite = self.loader.loadClass(sample.FooTest) |  | 
| 189         self.failUnlessEqual(2, suite.countTestCases()) |  | 
| 190         self.failUnlessEqual(['test_bar', 'test_foo'], |  | 
| 191                              [test._testMethodName for test in suite._tests]) |  | 
| 192 |  | 
| 193 |  | 
| 194     def test_loadNonClass(self): |  | 
| 195         import sample |  | 
| 196         self.failUnlessRaises(TypeError, self.loader.loadClass, sample) |  | 
| 197         self.failUnlessRaises(TypeError, |  | 
| 198                               self.loader.loadClass, sample.FooTest.test_foo) |  | 
| 199         self.failUnlessRaises(TypeError, self.loader.loadClass, "string") |  | 
| 200         self.failUnlessRaises(TypeError, |  | 
| 201                               self.loader.loadClass, ('foo', 'bar')) |  | 
| 202 |  | 
| 203     def test_loadNonTestCase(self): |  | 
| 204         import sample |  | 
| 205         self.failUnlessRaises(ValueError, self.loader.loadClass, |  | 
| 206                               sample.NotATest) |  | 
| 207 |  | 
| 208     def test_loadModule(self): |  | 
| 209         import sample |  | 
| 210         suite = self.loader.loadModule(sample) |  | 
| 211         self.failUnlessEqual(7, suite.countTestCases()) |  | 
| 212 |  | 
| 213     def test_loadNonModule(self): |  | 
| 214         import sample |  | 
| 215         self.failUnlessRaises(TypeError, |  | 
| 216                               self.loader.loadModule, sample.FooTest) |  | 
| 217         self.failUnlessRaises(TypeError, |  | 
| 218                               self.loader.loadModule, sample.FooTest.test_foo) |  | 
| 219         self.failUnlessRaises(TypeError, self.loader.loadModule, "string") |  | 
| 220         self.failUnlessRaises(TypeError, |  | 
| 221                               self.loader.loadModule, ('foo', 'bar')) |  | 
| 222 |  | 
| 223     def test_loadPackage(self): |  | 
| 224         import goodpackage |  | 
| 225         suite = self.loader.loadPackage(goodpackage) |  | 
| 226         self.failUnlessEqual(7, suite.countTestCases()) |  | 
| 227 |  | 
| 228     def test_loadNonPackage(self): |  | 
| 229         import sample |  | 
| 230         self.failUnlessRaises(TypeError, |  | 
| 231                               self.loader.loadPackage, sample.FooTest) |  | 
| 232         self.failUnlessRaises(TypeError, |  | 
| 233                               self.loader.loadPackage, sample.FooTest.test_foo) |  | 
| 234         self.failUnlessRaises(TypeError, self.loader.loadPackage, "string") |  | 
| 235         self.failUnlessRaises(TypeError, |  | 
| 236                               self.loader.loadPackage, ('foo', 'bar')) |  | 
| 237 |  | 
| 238     def test_loadModuleAsPackage(self): |  | 
| 239         import sample |  | 
| 240         ## XXX -- should this instead raise a ValueError? -- jml |  | 
| 241         self.failUnlessRaises(TypeError, self.loader.loadPackage, sample) |  | 
| 242 |  | 
| 243     def test_loadPackageRecursive(self): |  | 
| 244         import goodpackage |  | 
| 245         suite = self.loader.loadPackage(goodpackage, recurse=True) |  | 
| 246         self.failUnlessEqual(14, suite.countTestCases()) |  | 
| 247 |  | 
| 248     def test_loadAnythingOnModule(self): |  | 
| 249         import sample |  | 
| 250         suite = self.loader.loadAnything(sample) |  | 
| 251         self.failUnlessEqual(sample.__name__, |  | 
| 252                              suite._tests[0]._tests[0].__class__.__module__) |  | 
| 253 |  | 
| 254     def test_loadAnythingOnClass(self): |  | 
| 255         import sample |  | 
| 256         suite = self.loader.loadAnything(sample.FooTest) |  | 
| 257         self.failUnlessEqual(2, suite.countTestCases()) |  | 
| 258 |  | 
| 259     def test_loadAnythingOnMethod(self): |  | 
| 260         import sample |  | 
| 261         suite = self.loader.loadAnything(sample.FooTest.test_foo) |  | 
| 262         self.failUnlessEqual(1, suite.countTestCases()) |  | 
| 263 |  | 
| 264     def test_loadAnythingOnPackage(self): |  | 
| 265         import goodpackage |  | 
| 266         suite = self.loader.loadAnything(goodpackage) |  | 
| 267         self.failUnless(isinstance(suite, self.loader.suiteFactory)) |  | 
| 268         self.failUnlessEqual(7, suite.countTestCases()) |  | 
| 269 |  | 
| 270     def test_loadAnythingOnPackageRecursive(self): |  | 
| 271         import goodpackage |  | 
| 272         suite = self.loader.loadAnything(goodpackage, recurse=True) |  | 
| 273         self.failUnless(isinstance(suite, self.loader.suiteFactory)) |  | 
| 274         self.failUnlessEqual(14, suite.countTestCases()) |  | 
| 275 |  | 
| 276     def test_loadAnythingOnString(self): |  | 
| 277         # the important thing about this test is not the string-iness |  | 
| 278         # but the non-handledness. |  | 
| 279         self.failUnlessRaises(TypeError, |  | 
| 280                               self.loader.loadAnything, "goodpackage") |  | 
| 281 |  | 
| 282     def test_importErrors(self): |  | 
| 283         import package |  | 
| 284         suite = self.loader.loadPackage(package, recurse=True) |  | 
| 285         result = reporter.Reporter() |  | 
| 286         suite.run(result) |  | 
| 287         self.failUnlessEqual(False, result.wasSuccessful()) |  | 
| 288         self.failUnlessEqual(2, len(result.errors)) |  | 
| 289         errors = [test.id() for test, error in result.errors] |  | 
| 290         errors.sort() |  | 
| 291         self.failUnlessEqual(errors, ['package.test_bad_module', |  | 
| 292                                       'package.test_import_module']) |  | 
| 293 |  | 
| 294 |  | 
| 295     def test_loadModuleWith_test_suite(self): |  | 
| 296         """ |  | 
| 297         Check that C{test_suite} is used when present and other L{TestCase}s are |  | 
| 298         not included. |  | 
| 299         """ |  | 
| 300         from twisted.trial.test import mockcustomsuite |  | 
| 301         suite = self.loader.loadModule(mockcustomsuite) |  | 
| 302         self.failUnlessEqual(0, suite.countTestCases()) |  | 
| 303         self.failUnlessEqual("MyCustomSuite", getattr(suite, 'name', None)) |  | 
| 304 |  | 
| 305 |  | 
| 306     def test_loadModuleWith_testSuite(self): |  | 
| 307         """ |  | 
| 308         Check that C{testSuite} is used when present and other L{TestCase}s are |  | 
| 309         not included. |  | 
| 310         """ |  | 
| 311         from twisted.trial.test import mockcustomsuite2 |  | 
| 312         suite = self.loader.loadModule(mockcustomsuite2) |  | 
| 313         self.assertEqual(0, suite.countTestCases()) |  | 
| 314         self.assertEqual("MyCustomSuite", getattr(suite, 'name', None)) |  | 
| 315 |  | 
| 316 |  | 
| 317     def test_loadModuleWithBothCustom(self): |  | 
| 318         """ |  | 
| 319         Check that if C{testSuite} and C{test_suite} are both present in a |  | 
| 320         module then C{testSuite} gets priority. |  | 
| 321         """ |  | 
| 322         from twisted.trial.test import mockcustomsuite3 |  | 
| 323         suite = self.loader.loadModule(mockcustomsuite3) |  | 
| 324         self.assertEqual('testSuite', getattr(suite, 'name', None)) |  | 
| 325 |  | 
| 326 |  | 
| 327     def test_customLoadRaisesAttributeError(self): |  | 
| 328         """ |  | 
| 329         Make sure that any C{AttributeError}s raised by C{testSuite} are not |  | 
| 330         swallowed by L{TestLoader}. |  | 
| 331         """ |  | 
| 332         def testSuite(): |  | 
| 333             raise AttributeError('should be reraised') |  | 
| 334         from twisted.trial.test import mockcustomsuite2 |  | 
| 335         mockcustomsuite2.testSuite, original = (testSuite, |  | 
| 336                                                 mockcustomsuite2.testSuite) |  | 
| 337         try: |  | 
| 338             self.assertRaises(AttributeError, self.loader.loadModule, |  | 
| 339                               mockcustomsuite2) |  | 
| 340         finally: |  | 
| 341             mockcustomsuite2.testSuite = original |  | 
| 342 |  | 
| 343 |  | 
| 344     # XXX - duplicated and modified from test_script |  | 
| 345     def assertSuitesEqual(self, test1, test2): |  | 
| 346         loader = runner.TestLoader() |  | 
| 347         names1 = testNames(test1) |  | 
| 348         names2 = testNames(test2) |  | 
| 349         names1.sort() |  | 
| 350         names2.sort() |  | 
| 351         self.assertEqual(names1, names2) |  | 
| 352 |  | 
| 353     def test_loadByNamesDuplicate(self): |  | 
| 354         """ |  | 
| 355         Check that loadByNames ignores duplicate names |  | 
| 356         """ |  | 
| 357         module = 'twisted.trial.test.test_test_visitor' |  | 
| 358         suite1 = self.loader.loadByNames([module, module], True) |  | 
| 359         suite2 = self.loader.loadByName(module, True) |  | 
| 360         self.assertSuitesEqual(suite1, suite2) |  | 
| 361 |  | 
| 362     def test_loadDifferentNames(self): |  | 
| 363         """ |  | 
| 364         Check that loadByNames loads all the names that it is given |  | 
| 365         """ |  | 
| 366         modules = ['goodpackage', 'package.test_module'] |  | 
| 367         suite1 = self.loader.loadByNames(modules) |  | 
| 368         suite2 = runner.TestSuite(map(self.loader.loadByName, modules)) |  | 
| 369         self.assertSuitesEqual(suite1, suite2) |  | 
| 370 |  | 
| 371 |  | 
| 372 |  | 
| 373 class ZipLoadingTest(LoaderTest): |  | 
| 374     def setUp(self): |  | 
| 375         from twisted.test.test_paths import zipit |  | 
| 376         LoaderTest.setUp(self) |  | 
| 377         zipit(self.parent, self.parent+'.zip') |  | 
| 378         self.parent += '.zip' |  | 
| 379         self.mangleSysPath(self.oldPath+[self.parent]) |  | 
| 380 |  | 
| 381 |  | 
| 382 |  | 
| 383 class PackageOrderingTest(packages.SysPathManglingTest): |  | 
| 384     def setUp(self): |  | 
| 385         self.resultingTests = [] |  | 
| 386         self.loader = runner.TestLoader() |  | 
| 387         self.topDir = self.mktemp() |  | 
| 388         parent = os.path.join(self.topDir, "uberpackage") |  | 
| 389         os.makedirs(parent) |  | 
| 390         file(os.path.join(parent, "__init__.py"), "wb").close() |  | 
| 391         packages.SysPathManglingTest.setUp(self, parent) |  | 
| 392         self.mangleSysPath(self.oldPath + [self.topDir]) |  | 
| 393 |  | 
| 394     def _trialSortAlgorithm(self, sorter): |  | 
| 395         """ |  | 
| 396         Right now, halfway by accident, trial sorts like this: |  | 
| 397 |  | 
| 398             1. all modules are grouped together in one list and sorted. |  | 
| 399 |  | 
| 400             2. within each module, the classes are grouped together in one list |  | 
| 401                and sorted. |  | 
| 402 |  | 
| 403             3. finally within each class, each test method is grouped together |  | 
| 404                in a list and sorted. |  | 
| 405 |  | 
| 406         This attempts to return a sorted list of testable thingies following |  | 
| 407         those rules, so that we can compare the behavior of loadPackage. |  | 
| 408 |  | 
| 409         The things that show as 'cases' are errors from modules which failed to |  | 
| 410         import, and test methods.  Let's gather all those together. |  | 
| 411         """ |  | 
| 412         pkg = getModule('uberpackage') |  | 
| 413         testModules = [] |  | 
| 414         for testModule in pkg.walkModules(): |  | 
| 415             if testModule.name.split(".")[-1].startswith("test_"): |  | 
| 416                 testModules.append(testModule) |  | 
| 417         sortedModules = util.dsu(testModules, sorter) # ONE |  | 
| 418         for modinfo in sortedModules: |  | 
| 419             # Now let's find all the classes. |  | 
| 420             module = modinfo.load(None) |  | 
| 421             if module is None: |  | 
| 422                 yield modinfo |  | 
| 423             else: |  | 
| 424                 testClasses = [] |  | 
| 425                 for attrib in modinfo.iterAttributes(): |  | 
| 426                     if runner.isTestCase(attrib.load()): |  | 
| 427                         testClasses.append(attrib) |  | 
| 428                 sortedClasses = util.dsu(testClasses, sorter) # TWO |  | 
| 429                 for clsinfo in sortedClasses: |  | 
| 430                     testMethods = [] |  | 
| 431                     for attr in clsinfo.iterAttributes(): |  | 
| 432                         if attr.name.split(".")[-1].startswith('test'): |  | 
| 433                             testMethods.append(attr) |  | 
| 434                     sortedMethods = util.dsu(testMethods, sorter) # THREE |  | 
| 435                     for methinfo in sortedMethods: |  | 
| 436                         yield methinfo |  | 
| 437 |  | 
| 438 |  | 
| 439     def loadSortedPackages(self, sorter=runner.name): |  | 
| 440         """ |  | 
| 441         Verify that packages are loaded in the correct order. |  | 
| 442         """ |  | 
| 443         import uberpackage |  | 
| 444         self.loader.sorter = sorter |  | 
| 445         suite = self.loader.loadPackage(uberpackage, recurse=True) |  | 
| 446         # XXX: Work around strange, unexplained Zope crap. |  | 
| 447         # jml, 2007-11-15. |  | 
| 448         suite = unittest.decorate(suite, ITestCase) |  | 
| 449         self.resultingTests = list(unittest._iterateTests(suite)) |  | 
| 450         manifest = list(self._trialSortAlgorithm(sorter)) |  | 
| 451         for number, (manifestTest, actualTest) in enumerate( |  | 
| 452             zip(manifest, self.resultingTests)): |  | 
| 453             self.assertEqual( |  | 
| 454                  manifestTest.name, actualTest.id(), |  | 
| 455                  "#%d: %s != %s" % |  | 
| 456                  (number, manifestTest.name, actualTest.id())) |  | 
| 457         self.assertEqual(len(manifest), len(self.resultingTests)) |  | 
| 458 |  | 
| 459 |  | 
| 460     def test_sortPackagesDefaultOrder(self): |  | 
| 461         self.loadSortedPackages() |  | 
| 462 |  | 
| 463 |  | 
| 464     def test_sortPackagesSillyOrder(self): |  | 
| 465         def sillySorter(s): |  | 
| 466             # This has to work on fully-qualified class names and class |  | 
| 467             # objects, which is silly, but it's the "spec", such as it is. |  | 
| 468 #             if isinstance(s, type) or isinstance(s, types.ClassType): |  | 
| 469 #                 return s.__module__+'.'+s.__name__ |  | 
| 470             n = runner.name(s) |  | 
| 471             d = md5.new(n).hexdigest() |  | 
| 472             return d |  | 
| 473         self.loadSortedPackages(sillySorter) |  | 
| 474 |  | 
| 475 |  | 
| OLD | NEW | 
|---|