Coverage for tests/test_packages.py: 14%
93 statements
« prev ^ index » next coverage.py v6.4.4, created at 2022-08-27 02:19 -0700
« prev ^ index » next coverage.py v6.4.4, created at 2022-08-27 02:19 -0700
1# This file is part of utils.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# Use of this source code is governed by a 3-clause BSD-style
10# license that can be found in the LICENSE file.
11#
13import os
14import unittest
15from collections.abc import Mapping
17import lsst.utils.packages
18import lsst.utils.tests
20TESTDIR = os.path.abspath(os.path.dirname(__file__))
23class PackagesTestCase(unittest.TestCase):
24 """Tests for package version collection
26 Unfortunately, we're somewhat limited in what we can test because
27 we only get the versions of things being used at runtime, and this
28 package sits rather low in the dependency chain so there's not
29 usually a lot of other packages available when this test gets run.
30 Therefore some of the tests are only checking that things don't
31 explode, since they are incapable of testing much more than that.
32 """
34 def testPython(self):
35 """Test that we get the right version for this python package"""
36 versions = lsst.utils.packages.getPythonPackages()
37 expected = lsst.utils.version.__version__
38 self.assertEqual(versions["utils"], expected)
40 def testEnvironment(self):
41 """Test getting versions from the environment
43 Unfortunately, none of the products that need their versions divined
44 from the environment are dependencies of this package, and so all we
45 can do is test that this doesn't fall over.
46 """
47 lsst.utils.packages.getEnvironmentPackages()
49 def testConda(self):
50 """Test getting versions from conda environement
52 We do not rely on being run in a conda environment so all we can do is
53 test that this doesn't fall over.
54 """
55 lsst.utils.packages.getCondaPackages()
57 def _writeTempFile(self, packages, suffix):
58 """Write packages to a temp file using the supplied suffix and read
59 back.
60 """
61 with lsst.utils.tests.getTempFilePath(suffix) as tempName:
62 packages.write(tempName)
63 new = lsst.utils.packages.Packages.read(tempName)
64 return new
66 def testPackages(self):
67 """Test the Packages class"""
68 packages = lsst.utils.packages.Packages.fromSystem()
69 self.assertIsInstance(packages, Mapping)
71 # Check that stringification is not crashing.
72 self.assertTrue(str(packages).startswith("Packages({"))
73 self.assertTrue(repr(packages).startswith("Packages({"))
75 # Test pickling and YAML
76 new = self._writeTempFile(packages, ".pickle")
77 new_pkl = self._writeTempFile(packages, ".pkl")
78 new_yaml = self._writeTempFile(packages, ".yaml")
79 new_json = self._writeTempFile(packages, ".json")
81 self.assertIsInstance(new, lsst.utils.packages.Packages, f"Checking type ({type(new)}) from pickle")
82 self.assertIsInstance(
83 new_yaml, lsst.utils.packages.Packages, f"Checking type ({type(new_yaml)}) from YAML"
84 )
85 self.assertEqual(new, packages)
86 self.assertEqual(new_pkl, new)
87 self.assertEqual(new, new_yaml)
88 self.assertEqual(new, new_json)
90 # Dict compatibility.
91 for k, v in new.items():
92 self.assertEqual(new[k], v)
94 with self.assertRaises(ValueError):
95 self._writeTempFile(packages, ".txt")
97 with self.assertRaises(ValueError):
98 # .txt extension is not recognized
99 lsst.utils.packages.Packages.read("something.txt")
101 # 'packages' and 'new' should have identical content
102 self.assertDictEqual(packages.difference(new), {})
103 self.assertDictEqual(packages.missing(new), {})
104 self.assertDictEqual(packages.extra(new), {})
105 self.assertEqual(len(packages), len(new))
107 # Check inverted comparisons
108 self.assertDictEqual(new.difference(packages), {})
109 self.assertDictEqual(new.missing(packages), {})
110 self.assertDictEqual(new.extra(packages), {})
112 # Now load an obscure python package and the list of packages should
113 # change
114 # Shouldn't be used by anything we've previously imported
115 import smtpd # noqa: F401
117 new = lsst.utils.packages.Packages.fromSystem()
118 self.assertDictEqual(packages.difference(new), {}) # No inconsistencies
119 self.assertDictEqual(packages.extra(new), {}) # Nothing in 'packages' that's not in 'new'
120 missing = packages.missing(new)
121 self.assertGreater(len(missing), 0) # 'packages' should be missing some stuff in 'new'
122 self.assertIn("smtpd", missing)
124 # Inverted comparisons
125 self.assertDictEqual(new.difference(packages), {})
126 self.assertDictEqual(new.missing(packages), {}) # Nothing in 'new' that's not in 'packages'
127 extra = new.extra(packages)
128 self.assertGreater(len(extra), 0) # 'new' has extra stuff compared to 'packages'
129 self.assertIn("smtpd", extra)
130 self.assertIn("smtpd", new)
132 # Run with both a Packages and a dict
133 for new_pkg in (new, dict(new)):
134 packages.update(new_pkg) # Should now be identical
135 self.assertDictEqual(packages.difference(new_pkg), {})
136 self.assertDictEqual(packages.missing(new_pkg), {})
137 self.assertDictEqual(packages.extra(new_pkg), {})
138 self.assertEqual(len(packages), len(new_pkg))
140 # Loop over keys to check iterator.
141 keys = {k for k in new}
142 self.assertEqual(keys, set(dict(new).keys()))
144 # Loop over values to check that we do get them all.
145 values = {v for v in new.values()}
146 self.assertEqual(values, set(dict(new).values()))
148 # Serialize via bytes
149 for format in ("pickle", "yaml", "json"):
150 asbytes = new.toBytes(format)
151 from_bytes = lsst.utils.packages.Packages.fromBytes(asbytes, format)
152 self.assertEqual(from_bytes, new)
154 with self.assertRaises(ValueError):
155 new.toBytes("unknown_format")
157 with self.assertRaises(ValueError):
158 lsst.utils.packages.Packages.fromBytes(from_bytes, "unknown_format")
160 with self.assertRaises(TypeError):
161 some_yaml = b"list: [1, 2]"
162 lsst.utils.packages.Packages.fromBytes(some_yaml, "yaml")
164 def testBackwardsCompatibility(self):
165 """Test if we can read old data files."""
167 # Pickle contents changed when moving to dict base class.
168 packages_p = lsst.utils.packages.Packages.read(os.path.join(TESTDIR, "data", "v1.pickle"))
169 self.assertIsInstance(packages_p, lsst.utils.packages.Packages)
171 # YAML format is unchanged when moving from special class to dict
172 # but test anyway.
173 packages_y = lsst.utils.packages.Packages.read(os.path.join(TESTDIR, "data", "v1.yaml"))
175 self.assertEqual(packages_p, packages_y)
177 # Now check that we can read the version 2 files that were
178 # written with Packages inheriting from dict but still in `base`.
179 packages_p2 = lsst.utils.packages.Packages.read(os.path.join(TESTDIR, "data", "v2.pickle"))
180 packages_y2 = lsst.utils.packages.Packages.read(os.path.join(TESTDIR, "data", "v2.yaml"))
181 self.assertEqual(packages_p2, packages_y2)
182 self.assertIsInstance(packages_p2, lsst.utils.packages.Packages)
185if __name__ == "__main__": 185 ↛ 186line 185 didn't jump to line 186, because the condition on line 185 was never true
186 unittest.main()