Merge lp:~jml/pkgme-devportal/remove-database-code into lp:pkgme-devportal
- remove-database-code
- Merge into trunk
Proposed by
Jonathan Lange
Status: | Merged |
---|---|
Merged at revision: | 146 |
Proposed branch: | lp:~jml/pkgme-devportal/remove-database-code |
Merge into: | lp:pkgme-devportal |
Diff against target: |
376 lines (+4/-300) 6 files modified
NEWS (+3/-0) devportalbinary/aptfile.py (+0/-226) devportalbinary/database.py (+1/-7) devportalbinary/tests/test_aptfile.py (+0/-53) devportalbinary/tests/test_database.py (+0/-12) setup.py (+0/-2) |
To merge this branch: | bzr merge lp:~jml/pkgme-devportal/remove-database-code |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Westby | Approve | ||
Review via email: mp+134099@code.launchpad.net |
Commit message
Remove aptfile backend
Description of the change
Removes the apt-file backend, which we don't need any more.
To post a comment you must log in.
- 175. By Jonathan Lange
-
Merge versions.cfg change.
Revision history for this message
James Westby (james-w) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'NEWS' |
2 | --- NEWS 2012-11-13 11:25:44 +0000 |
3 | +++ NEWS 2012-11-13 14:34:20 +0000 |
4 | @@ -12,6 +12,9 @@ |
5 | maintain a database of library dependencies based on published packages |
6 | from Launchpad has been removed. (Jonathan Lange) |
7 | |
8 | + * ``aptfile`` backend has been removed. (Jonathan Lange) |
9 | + |
10 | + |
11 | 0.4.11 (2012-10-29) |
12 | =================== |
13 | |
14 | |
15 | === removed file 'devportalbinary/aptfile.py' |
16 | --- devportalbinary/aptfile.py 2012-11-13 11:25:44 +0000 |
17 | +++ devportalbinary/aptfile.py 1970-01-01 00:00:00 +0000 |
18 | @@ -1,226 +0,0 @@ |
19 | -# Copyright 2012 Canonical Ltd. This software is licensed under the |
20 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
21 | - |
22 | -# XXX: Remove this. No longer used. |
23 | - |
24 | -__all__ = [ |
25 | - 'AptFilePackageDatabase', |
26 | - ] |
27 | - |
28 | -import gzip |
29 | -import urllib |
30 | -import argparse |
31 | -import os |
32 | -import re |
33 | - |
34 | - |
35 | -def make_arg_parser(): |
36 | - p = argparse.ArgumentParser() |
37 | - p.add_argument('--cache-dir', type=str, default='cache') |
38 | - p.add_argument('output_file', type=argparse.FileType('w')) |
39 | - return p |
40 | - |
41 | - |
42 | -so_filename_re = re.compile(r'\.so(\.[0-9]+)*$') |
43 | -def export_database(db, stream): |
44 | - for library, package, arch in db.iter_database(): |
45 | - if so_filename_re.search(library): |
46 | - stream.write(','.join([package, library, package, arch])) |
47 | - stream.write('\n') |
48 | - stream.flush() |
49 | - |
50 | - |
51 | -def dump_apt_file_db(): |
52 | - parser = make_arg_parser() |
53 | - args = parser.parse_args() |
54 | - if not os.path.isdir(args.cache_dir): |
55 | - os.path.makedirs(args.cache_dir) |
56 | - db = AptFilePackageDatabase(args.cache_dir) |
57 | - export_database(db, args.output_file) |
58 | - return 0 |
59 | - |
60 | - |
61 | -def iter_contents_file(contents): |
62 | - """ Yield (full-library-path, set-of-pkgnames) from a Contents file. |
63 | - |
64 | - It expects a line starting with "FILE" that tells it when the header ends |
65 | - and the actual content starts. |
66 | - """ |
67 | - found_start_marker = False |
68 | - for line in contents: |
69 | - if not found_start_marker: |
70 | - if line.startswith("FILE"): |
71 | - found_start_marker = True |
72 | - continue |
73 | - (path, sep, pkgs) = [s.strip() for s in line.rpartition(" ")] |
74 | - # pkgs is formated a bit funny, e.g. universe/pkgname |
75 | - pkgs = set([os.path.basename(pkg) for pkg in pkgs.split(",")]) |
76 | - yield (path, pkgs) |
77 | - |
78 | - |
79 | -class AptFilePackageDatabase(object): |
80 | - """Really dumb database that just uses apt-file for local testing """ |
81 | - |
82 | - # we could also read /etc/ld.so.conf.d/*.conf but this maybe different on |
83 | - # different distroseries especially if |
84 | - # server-distroseries != target-distroseries |
85 | - # (I wish there was ldconfig --print-search-dirs) |
86 | - LD_SEARCH_PATH = [ |
87 | - # standards |
88 | - "lib", |
89 | - "usr/lib", |
90 | - "usr/local/lib", |
91 | - # old biarch |
92 | - "lib32", |
93 | - "usr/lib32", |
94 | - # new multiarch |
95 | - "lib/i686-linux-gnu", |
96 | - "lib/i386-linux-gnu", |
97 | - "lib/x86_64-linux-gnu", |
98 | - "usr/lib/i386-linux-gnu", |
99 | - "usr/lib/i686-linux-gnu", |
100 | - "usr/lib/x86_64-linux-gnu", |
101 | - # ? |
102 | - "usr/lib/x86_64-linux-gnu/fakechroot", |
103 | - "usr/lib/x86_64-linux-gnu/mesa", |
104 | - "usr/lib/x86_64-linux-gnu/mesa-egl", |
105 | - "usr/lib/i386-linux-gnu/mesa", |
106 | - ] |
107 | - |
108 | - DISTROSERIES = "oneiric" |
109 | - |
110 | - # If db_type is set to this in the config, that means use this database. |
111 | - DB_TYPE = 'aptfile' |
112 | - |
113 | - CONTENTS_FILE_URL_LOCATION = ( |
114 | - "http://archive.ubuntu.com/ubuntu/dists/%(distroseries)s/" |
115 | - "Contents-%(arch)s.gz") |
116 | - |
117 | - CONTENTS_FILE = "Contents-%(distroseries)s-%(arch)s" |
118 | - |
119 | - def __init__(self, cachedir): |
120 | - self.cachedir = os.path.expanduser(cachedir) |
121 | - self._distroseries_arch_cache = {} |
122 | - |
123 | - @classmethod |
124 | - def from_options(cls, options): |
125 | - return cls(options.database_aptfile_cachedir) |
126 | - |
127 | - def _get_lib_to_pkgs_mapping(self, distroseries, arch): |
128 | - """Returns a dict of { library-name : set([pkg1,pkg2]) |
129 | - |
130 | - This function will return a dict to lookup library-name to package |
131 | - dependencies for the given distroseries and architecture |
132 | - """ |
133 | - if not (distroseries, arch) in self._distroseries_arch_cache: |
134 | - self._distroseries_arch_cache[(distroseries, arch)] = \ |
135 | - self._get_mapping_from_contents_file(distroseries, arch) |
136 | - return self._distroseries_arch_cache[(distroseries, arch)] |
137 | - |
138 | - def _get_contents_file_cache_path(self, distroseries, arch): |
139 | - """Return the path in the cache for the given distroseries, arch """ |
140 | - return os.path.join( |
141 | - self.cachedir, self.CONTENTS_FILE % { |
142 | - 'distroseries': distroseries, 'arch': arch}) |
143 | - |
144 | - def _get_contents_file_server_url(self, distroseries, arch): |
145 | - """Return the remote server URL for the given distroseries, arch """ |
146 | - return self.CONTENTS_FILE_URL_LOCATION % { |
147 | - 'distroseries': distroseries, 'arch': arch} |
148 | - |
149 | - def _get_mapping_from_contents_file(self, distroseries, arch): |
150 | - """Return lib,pkgs mapping from contents file for distroseries, arch |
151 | - |
152 | - This expects the contents file to be in the cachedir already. |
153 | - """ |
154 | - lib_to_pkgs = {} |
155 | - path = self._get_contents_file_cache_path(distroseries, arch) |
156 | - with open(path) as f: |
157 | - for path, pkgs in self._iter_contents_file(f): |
158 | - basename = os.path.basename(path) |
159 | - if not basename in lib_to_pkgs: |
160 | - lib_to_pkgs[basename] = set() |
161 | - lib_to_pkgs[basename] |= pkgs |
162 | - return lib_to_pkgs |
163 | - |
164 | - def _download_contents_file_compressed(self, distroseries, arch): |
165 | - """Downloads the content file for distroseries, arch into target """ |
166 | - # XXX: we may eventually want to merge the Contents files from |
167 | - # the -updates repository too in addition to the main archive |
168 | - url = self._get_contents_file_server_url(distroseries, arch) |
169 | - target = self._get_contents_file_cache_path(distroseries, arch) |
170 | - compressed_target = target + os.path.splitext(url)[1] |
171 | - # download |
172 | - urllib.urlretrieve(url, compressed_target) |
173 | - return compressed_target |
174 | - |
175 | - def _iter_contents_file(self, in_file): |
176 | - for path, pkgs in iter_contents_file(in_file): |
177 | - if os.path.dirname(path) in self.LD_SEARCH_PATH: |
178 | - yield path, pkgs |
179 | - |
180 | - def _prune_contents_gz_file(self, infile, outfile): |
181 | - """Read a compressed Contents.gz and write out a pruned version. |
182 | - |
183 | - This will use iter_contents_file to go over infile and write |
184 | - the relevant lines that are in the LD_SEARCH_PATH to outfile. |
185 | - """ |
186 | - with open(outfile, "w") as outf, gzip.open(infile) as inf: |
187 | - # first write the header |
188 | - outf.write("FILE LOCATION\n") |
189 | - # then iter over all relevant lines and write them out |
190 | - for path, pkgs in self._iter_contents_file(inf): |
191 | - outf.write("%s %s\n" % (path, ",".join(pkgs))) |
192 | - |
193 | - def _download_and_prepare_contents_file_if_needed(self, distroseries, arch): |
194 | - """Ensure there is a usable Contents file in the cachedir |
195 | - |
196 | - This will download, uncompress and prune a Conents file for |
197 | - distroseries, arch so that get_dependencies works. |
198 | - """ |
199 | - # mvo: We can (and should eventually) do etag/if-modified-since |
200 | - # matching here. But its not really important as long as |
201 | - # we package for stable distroseries as the Contents file |
202 | - # will not change |
203 | - path = self._get_contents_file_cache_path(distroseries, arch) |
204 | - if not os.path.exists(path): |
205 | - compressed_contents = self._download_contents_file_compressed( |
206 | - distroseries, arch) |
207 | - # and prune from ~300mb to 1mb uncompressed as we are only |
208 | - # interested in the library path parts |
209 | - self._prune_contents_gz_file(compressed_contents, path) |
210 | - os.remove(compressed_contents) |
211 | - |
212 | - def iter_database(self, architectures=('i386', 'amd64'), |
213 | - distroseries=None): |
214 | - """Export the database. |
215 | - |
216 | - Yields (library, package, arch) tuples for everything that we can |
217 | - find. |
218 | - """ |
219 | - # XXX: Untested |
220 | - if distroseries is None: |
221 | - distroseries = self.DISTROSERIES |
222 | - for arch in architectures: |
223 | - self._download_and_prepare_contents_file_if_needed( |
224 | - distroseries, arch) |
225 | - mapping = self._get_lib_to_pkgs_mapping(distroseries, arch) |
226 | - for library in mapping: |
227 | - for package in mapping[library]: |
228 | - yield library, package, arch |
229 | - |
230 | - def get_multiple_dependencies(self, library_names, arch): |
231 | - """Get the binary packages that provide libraries. |
232 | - |
233 | - :return: (deps, missing), where ``deps`` is a dict mapping library |
234 | - names to sets of packages that provide them, and ``missing`` is a |
235 | - set of library names for which no dependencies could be found. |
236 | - """ |
237 | - self._download_and_prepare_contents_file_if_needed( |
238 | - self.DISTROSERIES, arch) |
239 | - lib_to_pkgs = self._get_lib_to_pkgs_mapping(self.DISTROSERIES, arch) |
240 | - deps = ((lib, lib_to_pkgs.get(lib)) for lib in library_names) |
241 | - return dict((lib, dep) for (lib, dep) in deps if dep) |
242 | - |
243 | - def close(self): |
244 | - pass |
245 | |
246 | === modified file 'devportalbinary/database.py' |
247 | --- devportalbinary/database.py 2012-11-13 11:28:53 +0000 |
248 | +++ devportalbinary/database.py 2012-11-13 14:34:20 +0000 |
249 | @@ -5,7 +5,6 @@ |
250 | from storm.locals import create_database, Store |
251 | from storm.uri import URI as StormURI |
252 | |
253 | -from .aptfile import AptFilePackageDatabase |
254 | from .configuration import ( |
255 | CONF_FILE_ENV_VAR, |
256 | get_config_file_path, |
257 | @@ -159,10 +158,5 @@ |
258 | |
259 | def get_dependency_database(): |
260 | """Return an object that can get dependencies.""" |
261 | - # XXX: Remove AptFilePackageDatabase from here and simplify the method. |
262 | - databases = { |
263 | - AptFilePackageDatabase.DB_TYPE: AptFilePackageDatabase.from_options, |
264 | - LibdepServiceClient.DB_TYPE: LibdepServiceClient.from_options, |
265 | - } |
266 | options = load_configuration() |
267 | - return databases[options.database_db_type](options) |
268 | + return LibdepServiceClient.from_options(options) |
269 | |
270 | === removed file 'devportalbinary/tests/test_aptfile.py' |
271 | --- devportalbinary/tests/test_aptfile.py 2012-10-26 12:21:03 +0000 |
272 | +++ devportalbinary/tests/test_aptfile.py 1970-01-01 00:00:00 +0000 |
273 | @@ -1,53 +0,0 @@ |
274 | -import gzip |
275 | -import os |
276 | - |
277 | -from mock import patch |
278 | -from fixtures import TempDir |
279 | -from testtools import TestCase |
280 | - |
281 | -from ..aptfile import AptFilePackageDatabase |
282 | - |
283 | - |
284 | -class AptFilePackageDatabaseTestCase(TestCase): |
285 | - |
286 | - # point to our local contents file version that is a tad smaller |
287 | - CONTENTS_CACHE = os.path.join( |
288 | - os.path.dirname(__file__), "data", "apt-file-backend") |
289 | - |
290 | - def setUp(self): |
291 | - super(AptFilePackageDatabaseTestCase, self).setUp() |
292 | - self.db = AptFilePackageDatabase(self.CONTENTS_CACHE) |
293 | - |
294 | - def test_read_fixture_contents_worked(self): |
295 | - """ test that our fixture Contents file works as expected """ |
296 | - # our test DB has 4 entries in the default search path |
297 | - self.assertEqual( |
298 | - len(self.db._get_lib_to_pkgs_mapping("oneiric", "i386")), 4) |
299 | - |
300 | - def test_get_dependencies(self): |
301 | - """ Test that data from the fixture dependencies file works """ |
302 | - self.assertEqual( |
303 | - self.db.get_multiple_dependencies(["libz.so.1"], 'i386'), |
304 | - ({'libz.so.1': 'zlib1g'}, set())) |
305 | - |
306 | - @patch("urllib.urlretrieve") |
307 | - def test_lazy_downloading(self, mock_urlretrieve): |
308 | - """ test that lazy downloading works """ |
309 | - def _put_fixture_contents_file_in_place(url, target): |
310 | - with gzip.open(target, "w") as f: |
311 | - f.write(""" |
312 | -Some header text that is ignored |
313 | -FILE LOCATION |
314 | -usr/lib/libfoo.so.2 pkgfoo,pkgbar |
315 | -""") |
316 | - tempdir = self.useFixture(TempDir()) |
317 | - db = AptFilePackageDatabase(tempdir.path) |
318 | - mock_urlretrieve.side_effect = _put_fixture_contents_file_in_place |
319 | - self.assertEqual( |
320 | - db.get_multiple_dependencies(["libfoo.so.2"], arch="i386"), |
321 | - ({'libfoo.so.2': set(["pkgfoo", "pkgbar"])}, set())) |
322 | - self.assertEqual(len(db._get_lib_to_pkgs_mapping("oneiric", "i386")), 1) |
323 | - |
324 | - def test_close(self): |
325 | - # Test that there is a close method we can call |
326 | - self.db.close() |
327 | |
328 | === modified file 'devportalbinary/tests/test_database.py' |
329 | --- devportalbinary/tests/test_database.py 2012-11-13 11:22:16 +0000 |
330 | +++ devportalbinary/tests/test_database.py 2012-11-13 14:34:20 +0000 |
331 | @@ -9,7 +9,6 @@ |
332 | ) |
333 | |
334 | from devportalbinary.database import ( |
335 | - AptFilePackageDatabase, |
336 | get_dependency_database, |
337 | LibdepServiceClient, |
338 | load_configuration, |
339 | @@ -78,17 +77,6 @@ |
340 | self.assertRaises(ValueError, PackageDatabase.get_db_info_from_config, |
341 | options) |
342 | |
343 | - def test_default_create_no_config(self): |
344 | - nonexistent = self.getUniqueString() |
345 | - self.useFixture(ConfigFileFixture(nonexistent)) |
346 | - self.assertIsInstance( |
347 | - get_dependency_database(), AptFilePackageDatabase) |
348 | - |
349 | - def test_default_create_empty_config(self): |
350 | - self.useFixture(ConfigSettings()) |
351 | - self.assertIsInstance( |
352 | - get_dependency_database(), AptFilePackageDatabase) |
353 | - |
354 | def test_remote_service(self): |
355 | base_url = 'http://example.com/libdep-service/' |
356 | self.use_database_config(db_type='libdep-service', base_url=base_url) |
357 | |
358 | === modified file 'setup.py' |
359 | --- setup.py 2012-11-13 09:14:39 +0000 |
360 | +++ setup.py 2012-11-13 14:34:20 +0000 |
361 | @@ -36,7 +36,6 @@ |
362 | install_requires = [ |
363 | 'bzr', |
364 | 'configglue', |
365 | - 'launchpadlib', |
366 | 'libdep-service-python>=0.0.5', |
367 | 'PIL', |
368 | 'pkgme>=0.4.1', |
369 | @@ -45,7 +44,6 @@ |
370 | ], |
371 | entry_points = { |
372 | 'console_scripts': [ |
373 | - 'dump-apt-file-db=devportalbinary.aptfile:dump_apt_file_db', |
374 | 'guess-executable=devportalbinary.binary:print_executable', |
375 | 'guess-deps=devportalbinary.binary:print_dependencies', |
376 | ], |