Merge lp:~jml/pkgme-devportal/restore-download-file into lp:pkgme-devportal
- restore-download-file
- Merge into trunk
Proposed by
Jonathan Lange
Status: | Merged |
---|---|
Approved by: | Jonathan Lange |
Approved revision: | 180 |
Merged at revision: | 146 |
Proposed branch: | lp:~jml/pkgme-devportal/restore-download-file |
Merge into: | lp:pkgme-devportal |
Diff against target: |
798 lines (+15/-665) 7 files modified
NEWS (+3/-0) devportalbinary/aptfile.py (+0/-226) devportalbinary/database.py (+5/-131) devportalbinary/testing.py (+3/-139) devportalbinary/tests/test_aptfile.py (+0/-53) devportalbinary/tests/test_database.py (+2/-114) setup.py (+2/-2) |
To merge this branch: | bzr merge lp:~jml/pkgme-devportal/restore-download-file |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jonathan Lange | Approve | ||
Review via email: mp+134116@code.launchpad.net |
Commit message
Add download_file back to devportalbinary
Description of the change
download_file was being imported by pkgme-service from devportalbinary
Another branch is in progress, removing this particular dependency. In the mean
time, this branch should land, restoring the behaviour so we can bump pkgme-service
to use latest devportal without probs.
To post a comment you must log in.
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:53:23 +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:53:23 +0000 |
249 | @@ -1,134 +1,13 @@ |
250 | # Copyright 2011 Canonical Ltd. This software is licensed under the |
251 | # GNU Affero General Public License version 3 (see the file LICENSE). |
252 | |
253 | -from storm.expr import And, Column, Select, Table |
254 | -from storm.locals import create_database, Store |
255 | -from storm.uri import URI as StormURI |
256 | - |
257 | -from .aptfile import AptFilePackageDatabase |
258 | -from .configuration import ( |
259 | - CONF_FILE_ENV_VAR, |
260 | - get_config_file_path, |
261 | - load_configuration, |
262 | - ) |
263 | +from .configuration import load_configuration |
264 | +from .utils import download_file |
265 | |
266 | from libdep_service_client.client import Client |
267 | |
268 | - |
269 | -class URI(StormURI): |
270 | - """A stand-in for Storm's URI class. |
271 | - |
272 | - This class implements the same interface as `storm.uri.URI`, except |
273 | - that the constructor has a different signature. Storm's version takes |
274 | - a string and parses it, this version can be used when you already |
275 | - have a parsed version and just need to create the object. |
276 | - """ |
277 | - |
278 | - # XXX: Only used by PackageDatabase, which is flagged for deletion. |
279 | - |
280 | - def __init__(self, scheme=None, host=None, port=None, username=None, |
281 | - password=None, database=None, options=None): |
282 | - self.scheme = scheme |
283 | - self.host = host |
284 | - self.port = port |
285 | - self.username = username |
286 | - self.password = password |
287 | - self.database = database |
288 | - self.options = options |
289 | - if self.options is None: |
290 | - self.options = dict() |
291 | - |
292 | - |
293 | -class PackageDatabase(object): |
294 | - |
295 | - # XXX: No longer used within pkgme-devportal |
296 | - |
297 | - SQLITE = 'sqlite' |
298 | - POSTGRES = 'postgres' |
299 | - |
300 | - def __init__(self, store): |
301 | - self._store = store |
302 | - |
303 | - @classmethod |
304 | - def _get_storm_sqlite_connection_uri(cls, opts): |
305 | - raise ValueError( |
306 | - "SQLite is no longer supported, you must migrate to postgresql.") |
307 | - |
308 | - @classmethod |
309 | - def _get_storm_postgres_connection_uri(cls, opts): |
310 | - if not getattr(opts, 'database_db_name', None): |
311 | - raise ValueError( |
312 | - "Can't create database, no connection info available. " |
313 | - "You must specify %s. Looked in %s. " |
314 | - "Perhaps %s is set incorrectly?" % ( |
315 | - 'db_name', get_config_file_path(), CONF_FILE_ENV_VAR)) |
316 | - return URI(scheme=opts.database_db_type, |
317 | - username=opts.database_username, |
318 | - password=opts.database_password, |
319 | - host=opts.database_host, |
320 | - port=opts.database_port, |
321 | - database=opts.database_db_name) |
322 | - |
323 | - @classmethod |
324 | - def _get_storm_connection_uri(cls, opts): |
325 | - if opts.database_db_type == cls.POSTGRES: |
326 | - return cls._get_storm_postgres_connection_uri(opts) |
327 | - elif opts.database_db_type == cls.SQLITE: |
328 | - return cls._get_storm_sqlite_connection_uri(opts) |
329 | - else: |
330 | - raise AssertionError( |
331 | - "Unsupported database: %s" % opts.database_db_type) |
332 | - |
333 | - @classmethod |
334 | - def get_db_info_from_config(cls, opts): |
335 | - return cls._get_storm_connection_uri(opts) |
336 | - |
337 | - @classmethod |
338 | - def get_store_from_config(cls, opts): |
339 | - """Create a storm store based on a config file. |
340 | - |
341 | - This method will create a storm store based |
342 | - on the information in ``~/.config/pkgme-binary/conf`` |
343 | - |
344 | - :return: a tuple of (store, store_type), where store_type |
345 | - is one of cls.SQLITE or cls.POSTGRES, indicating what |
346 | - is at the other end of the store. |
347 | - """ |
348 | - connection_info = cls.get_db_info_from_config(opts) |
349 | - database = create_database(connection_info) |
350 | - return Store(database) |
351 | - |
352 | - @classmethod |
353 | - def from_options(cls, options): |
354 | - return cls(cls.get_store_from_config(options)) |
355 | - |
356 | - def _get_query(self, library_names, arch): |
357 | - return Select( |
358 | - [Column('library'), Column('dependency')], |
359 | - And(Column('architecture') == arch, |
360 | - Column('library').is_in(map(unicode, library_names))), |
361 | - Table('libdep')) |
362 | - |
363 | - def get_multiple_dependencies(self, library_names, arch): |
364 | - """Get the binary packages that provide libraries. |
365 | - |
366 | - :return: (deps, missing), where ``deps`` is a dict mapping library |
367 | - names to sets of packages that provide them, and ``missing`` is a |
368 | - set of library names for which no dependencies could be found. |
369 | - """ |
370 | - arch = unicode(arch) |
371 | - result = self._store.execute(self._get_query(library_names, arch)) |
372 | - found = {} |
373 | - for row in result: |
374 | - [lib, dependency] = row |
375 | - if lib in found: |
376 | - found[lib].add(dependency) |
377 | - else: |
378 | - found[lib] = set([dependency]) |
379 | - return found |
380 | - |
381 | - def close(self): |
382 | - self._store.close() |
383 | +# Shut up pyflakes. Imported because other things use this. |
384 | +download_file |
385 | |
386 | |
387 | class LibdepServiceClient(object): |
388 | @@ -159,10 +38,5 @@ |
389 | |
390 | def get_dependency_database(): |
391 | """Return an object that can get dependencies.""" |
392 | - # XXX: Remove AptFilePackageDatabase from here and simplify the method. |
393 | - databases = { |
394 | - AptFilePackageDatabase.DB_TYPE: AptFilePackageDatabase.from_options, |
395 | - LibdepServiceClient.DB_TYPE: LibdepServiceClient.from_options, |
396 | - } |
397 | options = load_configuration() |
398 | - return databases[options.database_db_type](options) |
399 | + return LibdepServiceClient.from_options(options) |
400 | |
401 | === modified file 'devportalbinary/testing.py' |
402 | --- devportalbinary/testing.py 2012-11-13 11:12:08 +0000 |
403 | +++ devportalbinary/testing.py 2012-11-13 14:53:23 +0000 |
404 | @@ -1,7 +1,6 @@ |
405 | # Copyright 2011-2012 Canonical Ltd. This software is licensed under the |
406 | # GNU Affero General Public License version 3 (see the file LICENSE). |
407 | |
408 | -from contextlib import closing |
409 | import json |
410 | import os |
411 | import random |
412 | @@ -21,11 +20,6 @@ |
413 | Fixture, |
414 | TempDir, |
415 | ) |
416 | -from postgresfixture import ClusterFixture |
417 | -from storm.locals import create_database, Store |
418 | -from testresources import ( |
419 | - FixtureResource as _FixtureResource, |
420 | - ) |
421 | from testtools import TestCase |
422 | from treeshape import ( |
423 | from_rough_spec, |
424 | @@ -33,11 +27,7 @@ |
425 | ) |
426 | |
427 | from devportalbinary.binary import MetadataBackend |
428 | -from devportalbinary.database import ( |
429 | - LibdepServiceClient, |
430 | - PackageDatabase, |
431 | - URI, |
432 | - ) |
433 | +from devportalbinary.database import LibdepServiceClient |
434 | |
435 | from devportalbinary.configuration import CONF_FILE_ENV_VAR |
436 | |
437 | @@ -90,133 +80,6 @@ |
438 | im.size[0], im.size[1], im.format)) |
439 | |
440 | |
441 | -def get_db_schema_file_path(name): |
442 | - return os.path.join(os.path.dirname( |
443 | - os.path.abspath(__file__)), 'db', name) |
444 | - |
445 | - |
446 | -def get_db_schema_queries(filenames): |
447 | - for filename in filenames: |
448 | - path = get_db_schema_file_path(filename) |
449 | - with open(path) as f: |
450 | - yield f.read() |
451 | - |
452 | - |
453 | -class PostgresDatabaseFixture(Fixture): |
454 | - |
455 | - def __init__(self): |
456 | - super(PostgresDatabaseFixture, self).__init__() |
457 | - self.db_name = "libdep" |
458 | - |
459 | - def drop_db(self): |
460 | - # stub suggests that dropping all tables would be quicker than |
461 | - # dropping the db when the number of tables is small. |
462 | - # select quote_ident(table_schema) || '.' || |
463 | - # quote_ident(table_name) from information_schema.tables |
464 | - # WHERE table_schema = 'public'; |
465 | - self.cluster.dropdb(self.db_name) |
466 | - |
467 | - def create_db(self): |
468 | - self.cluster.createdb(self.db_name) |
469 | - queries = [ |
470 | - 'postgres_schema.sql', |
471 | - 'patch-00001.sql', |
472 | - 'patch-00002.sql', |
473 | - ] |
474 | - for patch in get_db_schema_queries(queries): |
475 | - self._execute(patch) |
476 | - |
477 | - def _execute(self, query): |
478 | - with closing(self.cluster.connect(self.db_name)) as conn: |
479 | - cur = conn.cursor() |
480 | - cur.execute(query) |
481 | - conn.commit() |
482 | - |
483 | - def close_connection(self): |
484 | - self.conn.close() |
485 | - |
486 | - def open_connection(self): |
487 | - db = create_database(URI(scheme='postgres', |
488 | - host=self.cluster.datadir, database=self.db_name)) |
489 | - self.conn = Store(db) |
490 | - self.addCleanup(self.close_connection) |
491 | - |
492 | - def reset(self): |
493 | - self.close_connection() |
494 | - self.drop_db() |
495 | - self.create_db() |
496 | - self.open_connection() |
497 | - |
498 | - def setUp(self): |
499 | - super(PostgresDatabaseFixture, self).setUp() |
500 | - self.tempdir = self.useFixture(TempDir()) |
501 | - self.cluster = self.useFixture(ClusterFixture(self.tempdir.path)) |
502 | - self.create_db() |
503 | - self.open_connection() |
504 | - |
505 | - |
506 | -class FixtureResource(_FixtureResource): |
507 | - """The built in FixtureResource doesn't get properly dirtied.""" |
508 | - # XXX: workaround for bug 1023423 |
509 | - |
510 | - def _get_dirty(self): |
511 | - return True |
512 | - |
513 | - def _set_dirty(self, new_val): |
514 | - pass |
515 | - |
516 | - _dirty = property(_get_dirty, _set_dirty) |
517 | - |
518 | - |
519 | -class PostgresDatabaseResource(FixtureResource): |
520 | - |
521 | - def __init__(self): |
522 | - fixture = PostgresDatabaseFixture() |
523 | - super(PostgresDatabaseResource, self).__init__(fixture) |
524 | - |
525 | - def reset(self, resource, result=None): |
526 | - resource.reset() |
527 | - return resource |
528 | - |
529 | - |
530 | -postgres_db_resource = PostgresDatabaseResource() |
531 | - |
532 | - |
533 | -class DatabaseConfig(Fixture): |
534 | - |
535 | - def __init__(self, db_fixture): |
536 | - super(DatabaseConfig, self).__init__() |
537 | - self.db_fixture = db_fixture |
538 | - |
539 | - def setUp(self): |
540 | - super(DatabaseConfig, self).setUp() |
541 | - self.useFixture( |
542 | - ConfigSettings( |
543 | - ('database', {'db_type': 'postgres', |
544 | - 'host': self.db_fixture.cluster.datadir, |
545 | - 'db_name': self.db_fixture.db_name, |
546 | - }))) |
547 | - |
548 | - |
549 | -class DatabaseFixture(Fixture): |
550 | - """Create a temporary database and make it the default. |
551 | - |
552 | - Don't use this twice within a test, otherwise you'll get confused. |
553 | - """ |
554 | - |
555 | - def setUp(self): |
556 | - super(DatabaseFixture, self).setUp() |
557 | - pg_db = self.useFixture(PostgresDatabaseFixture()) |
558 | - self.useFixture(DatabaseConfig(pg_db)) |
559 | - self.db = PackageDatabase(pg_db.conn) |
560 | - self.addCleanup(self.db.close) |
561 | - |
562 | - |
563 | -def ConfigFileFixture(location): |
564 | - """Use a different configuration file.""" |
565 | - return EnvironmentVariableFixture(CONF_FILE_ENV_VAR, location) |
566 | - |
567 | - |
568 | class ConfigSettings(Fixture): |
569 | """Use a configuration file with different settings.""" |
570 | |
571 | @@ -239,7 +102,8 @@ |
572 | tempdir = self.useFixture(TempDir()) |
573 | config_file_path = os.path.join(tempdir.path, 'test.cfg') |
574 | write_config_file(config_file_path, self._settings) |
575 | - self.useFixture(ConfigFileFixture(config_file_path)) |
576 | + self.useFixture( |
577 | + EnvironmentVariableFixture(CONF_FILE_ENV_VAR, config_file_path)) |
578 | |
579 | |
580 | class LibdepFixture(Fixture): |
581 | |
582 | === removed file 'devportalbinary/tests/test_aptfile.py' |
583 | --- devportalbinary/tests/test_aptfile.py 2012-10-26 12:21:03 +0000 |
584 | +++ devportalbinary/tests/test_aptfile.py 1970-01-01 00:00:00 +0000 |
585 | @@ -1,53 +0,0 @@ |
586 | -import gzip |
587 | -import os |
588 | - |
589 | -from mock import patch |
590 | -from fixtures import TempDir |
591 | -from testtools import TestCase |
592 | - |
593 | -from ..aptfile import AptFilePackageDatabase |
594 | - |
595 | - |
596 | -class AptFilePackageDatabaseTestCase(TestCase): |
597 | - |
598 | - # point to our local contents file version that is a tad smaller |
599 | - CONTENTS_CACHE = os.path.join( |
600 | - os.path.dirname(__file__), "data", "apt-file-backend") |
601 | - |
602 | - def setUp(self): |
603 | - super(AptFilePackageDatabaseTestCase, self).setUp() |
604 | - self.db = AptFilePackageDatabase(self.CONTENTS_CACHE) |
605 | - |
606 | - def test_read_fixture_contents_worked(self): |
607 | - """ test that our fixture Contents file works as expected """ |
608 | - # our test DB has 4 entries in the default search path |
609 | - self.assertEqual( |
610 | - len(self.db._get_lib_to_pkgs_mapping("oneiric", "i386")), 4) |
611 | - |
612 | - def test_get_dependencies(self): |
613 | - """ Test that data from the fixture dependencies file works """ |
614 | - self.assertEqual( |
615 | - self.db.get_multiple_dependencies(["libz.so.1"], 'i386'), |
616 | - ({'libz.so.1': 'zlib1g'}, set())) |
617 | - |
618 | - @patch("urllib.urlretrieve") |
619 | - def test_lazy_downloading(self, mock_urlretrieve): |
620 | - """ test that lazy downloading works """ |
621 | - def _put_fixture_contents_file_in_place(url, target): |
622 | - with gzip.open(target, "w") as f: |
623 | - f.write(""" |
624 | -Some header text that is ignored |
625 | -FILE LOCATION |
626 | -usr/lib/libfoo.so.2 pkgfoo,pkgbar |
627 | -""") |
628 | - tempdir = self.useFixture(TempDir()) |
629 | - db = AptFilePackageDatabase(tempdir.path) |
630 | - mock_urlretrieve.side_effect = _put_fixture_contents_file_in_place |
631 | - self.assertEqual( |
632 | - db.get_multiple_dependencies(["libfoo.so.2"], arch="i386"), |
633 | - ({'libfoo.so.2': set(["pkgfoo", "pkgbar"])}, set())) |
634 | - self.assertEqual(len(db._get_lib_to_pkgs_mapping("oneiric", "i386")), 1) |
635 | - |
636 | - def test_close(self): |
637 | - # Test that there is a close method we can call |
638 | - self.db.close() |
639 | |
640 | === modified file 'devportalbinary/tests/test_database.py' |
641 | --- devportalbinary/tests/test_database.py 2012-11-13 11:22:16 +0000 |
642 | +++ devportalbinary/tests/test_database.py 2012-11-13 14:53:23 +0000 |
643 | @@ -1,124 +1,12 @@ |
644 | -import os |
645 | |
646 | -from fixtures import TempDir |
647 | -from testresources import ResourcedTestCase |
648 | from testtools import TestCase |
649 | -from testtools.matchers import ( |
650 | - Equals, |
651 | - Matcher, |
652 | - ) |
653 | |
654 | -from devportalbinary.database import ( |
655 | - AptFilePackageDatabase, |
656 | - get_dependency_database, |
657 | - LibdepServiceClient, |
658 | - load_configuration, |
659 | - PackageDatabase, |
660 | - ) |
661 | -from devportalbinary.testing import ( |
662 | - ConfigFileFixture, |
663 | - ConfigSettings, |
664 | - get_libdep_service_client, |
665 | - postgres_db_resource, |
666 | - ) |
667 | +from devportalbinary.database import LibdepServiceClient |
668 | +from devportalbinary.testing import get_libdep_service_client |
669 | |
670 | from libdep_service_client.client import Client |
671 | |
672 | |
673 | -class ResultsIn(Matcher): |
674 | - |
675 | - def __init__(self, db, rows): |
676 | - self._db = db |
677 | - self._rows = rows |
678 | - |
679 | - def match(self, query): |
680 | - # XXX: Abstraction violation |
681 | - results = self._db._store.execute(query) |
682 | - return Equals(self._rows).match(list(results)) |
683 | - |
684 | - |
685 | -class TestDatabase(TestCase, ResourcedTestCase): |
686 | - |
687 | - resources = [ |
688 | - ('db_fixture', postgres_db_resource), |
689 | - ] |
690 | - |
691 | - def get_package_db(self): |
692 | - db = PackageDatabase(self.db_fixture.conn) |
693 | - self.addCleanup(db.close) |
694 | - return db |
695 | - |
696 | - def test_unknown_library(self): |
697 | - db = self.get_package_db() |
698 | - deps = db.get_multiple_dependencies(['libfoo.so.0'], 'i386') |
699 | - self.assertEqual(deps, {}) |
700 | - |
701 | - def test_close(self): |
702 | - # Test that we can close the package db. |
703 | - db = PackageDatabase(self.db_fixture.conn) |
704 | - db.close() |
705 | - |
706 | - def test_close_twice(self): |
707 | - # Test that we can close the package db twice with no exception. |
708 | - db = PackageDatabase(self.db_fixture.conn) |
709 | - db.close() |
710 | - db.close() |
711 | - |
712 | - |
713 | -class TestDatabaseConfiguration(TestCase): |
714 | - |
715 | - def use_database_config(self, **db_settings): |
716 | - return self.useFixture(ConfigSettings(('database', db_settings))) |
717 | - |
718 | - def test_get_db_info_from_config_sqlite(self): |
719 | - other_tempdir = self.useFixture(TempDir()) |
720 | - expected_db_path = os.path.join(other_tempdir.path, 'db') |
721 | - self.use_database_config(db_type='sqlite', path=expected_db_path) |
722 | - options = load_configuration() |
723 | - self.assertRaises(ValueError, PackageDatabase.get_db_info_from_config, |
724 | - options) |
725 | - |
726 | - def test_default_create_no_config(self): |
727 | - nonexistent = self.getUniqueString() |
728 | - self.useFixture(ConfigFileFixture(nonexistent)) |
729 | - self.assertIsInstance( |
730 | - get_dependency_database(), AptFilePackageDatabase) |
731 | - |
732 | - def test_default_create_empty_config(self): |
733 | - self.useFixture(ConfigSettings()) |
734 | - self.assertIsInstance( |
735 | - get_dependency_database(), AptFilePackageDatabase) |
736 | - |
737 | - def test_remote_service(self): |
738 | - base_url = 'http://example.com/libdep-service/' |
739 | - self.use_database_config(db_type='libdep-service', base_url=base_url) |
740 | - db = get_dependency_database() |
741 | - self.assertIsInstance(db, LibdepServiceClient) |
742 | - self.assertEqual(base_url, db._client.base_url) |
743 | - |
744 | - def test_get_db_info_from_config_postgres(self): |
745 | - expected_username = self.getUniqueString() |
746 | - expected_password = self.getUniqueString() |
747 | - expected_host = self.getUniqueString() |
748 | - expected_port = self.getUniqueInteger() |
749 | - expected_db_name = self.getUniqueString() |
750 | - |
751 | - self.use_database_config( |
752 | - db_type='postgres', |
753 | - username=expected_username, |
754 | - password=expected_password, |
755 | - host=expected_host, |
756 | - port=expected_port, |
757 | - db_name=expected_db_name) |
758 | - options = load_configuration() |
759 | - uri = PackageDatabase.get_db_info_from_config(options) |
760 | - self.assertEqual(expected_db_name, uri.database) |
761 | - self.assertEqual(expected_port, uri.port) |
762 | - self.assertEqual(expected_host, uri.host) |
763 | - self.assertEqual(expected_password, uri.password) |
764 | - self.assertEqual(expected_username, uri.username) |
765 | - |
766 | - |
767 | class TestLibdepServiceClient(TestCase): |
768 | |
769 | TEST_DATA = [('libfoo', {'i386': {'libfoo': 'libfoo-bin'}})] |
770 | |
771 | === modified file 'setup.py' |
772 | --- setup.py 2012-11-13 09:14:39 +0000 |
773 | +++ setup.py 2012-11-13 14:53:23 +0000 |
774 | @@ -18,6 +18,8 @@ |
775 | ) |
776 | from setuptools import setup, find_packages |
777 | |
778 | +# XXX: Need to do a trawl to see if we are depending on things that we are no |
779 | +# longer using. |
780 | |
781 | __version__ = get_version('devportalbinary/__init__.py') |
782 | |
783 | @@ -36,7 +38,6 @@ |
784 | install_requires = [ |
785 | 'bzr', |
786 | 'configglue', |
787 | - 'launchpadlib', |
788 | 'libdep-service-python>=0.0.5', |
789 | 'PIL', |
790 | 'pkgme>=0.4.1', |
791 | @@ -45,7 +46,6 @@ |
792 | ], |
793 | entry_points = { |
794 | 'console_scripts': [ |
795 | - 'dump-apt-file-db=devportalbinary.aptfile:dump_apt_file_db', |
796 | 'guess-executable=devportalbinary.binary:print_executable', |
797 | 'guess-deps=devportalbinary.binary:print_dependencies', |
798 | ], |
Rubberstamp! Proposer approves of own proposal.