Merge lp:~jml/pkgme-devportal/reuse-backend into lp:pkgme-devportal
- reuse-backend
- Merge into trunk
| Status: | Merged |
|---|---|
| Approved by: | James Westby on 2012-01-10 |
| Approved revision: | 47 |
| Merged at revision: | 30 |
| Proposed branch: | lp:~jml/pkgme-devportal/reuse-backend |
| Merge into: | lp:pkgme-devportal |
| Diff against target: |
1657 lines (+630/-618) 24 files modified
devportalbinary/backends/binary/all_info (+13/-0) devportalbinary/backends/binary/build_depends (+0/-16) devportalbinary/backends/binary/depends (+0/-13) devportalbinary/backends/binary/description (+0/-19) devportalbinary/backends/binary/extra_files (+0/-37) devportalbinary/backends/binary/package_name (+0/-17) devportalbinary/backends/binary/want (+2/-5) devportalbinary/backends/pdf/all_info (+14/-0) devportalbinary/backends/pdf/architecture (+0/-5) devportalbinary/backends/pdf/build_depends (+0/-11) devportalbinary/backends/pdf/depends (+0/-11) devportalbinary/backends/pdf/description (+0/-26) devportalbinary/backends/pdf/extra_files (+0/-37) devportalbinary/backends/pdf/package_name (+0/-17) devportalbinary/backends/pdf/want (+2/-12) devportalbinary/binary.py (+37/-111) devportalbinary/metadata.py (+204/-0) devportalbinary/pdf.py (+47/-0) devportalbinary/testing.py (+2/-2) devportalbinary/tests/test_binary.py (+9/-170) devportalbinary/tests/test_binary_backend.py (+62/-69) devportalbinary/tests/test_metadata.py (+178/-0) devportalbinary/tests/test_pdf.py (+21/-0) devportalbinary/tests/test_pdf_backend.py (+39/-40) |
| To merge this branch: | bzr merge lp:~jml/pkgme-devportal/reuse-backend |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| James Westby | 2012-01-10 | Approve on 2012-01-10 | |
|
Review via email:
|
|||
Commit Message
Factor out common code from the PDF & binary backends.
Description of the Change
This is a big branch, but I think it's worth it.
* Take the PDF & binary backends and turn them into all_info backends, rather than per-file backends
* Create classes, BinaryBackend and PdfBackend that do all of the work
* Create a MetadataBackend class that both of those inherit from which handles all of the common work
* Move a bunch of constants into MetadataBackend
* Move all of the stuff that isn't specifically about binary backend out of the binary.py module and into either metadata.py or pdf.py backends
* Do the analogous thing for test_binary → test_metadata, test_pdf
I think that after this branch lands it would be a good idea to go over the test_binary_backend and test_pdf_backend test modules and make them exercise the BinaryBackend and PdfBackend classes directly, as well as extracting tests out of them and into test_metadata. Probably doing that would also reveal some common test fixtures that would help us reduce boiler plate.
| James Westby (james-w) wrote : | # |
| James Westby (james-w) wrote : | # |
Overall this looks great though, and much cleaner, so thanks for doing it.
I'm not approving yet as the XXX I highlighted seems to undo the work of
my last branch, so I'd like to understand why so we can fix that.
Thanks,
James
- 46. By Jonathan Lange on 2012-01-10
-
Fix tests to always have enough info for backend to work properly.
- 47. By Jonathan Lange on 2012-01-10
-
Make all of the binary backend tests directly exercise the BinaryBackend class.
| Jonathan Lange (jml) wrote : | # |
I've fixed the XXX by making sure that a proper executable is set up for all of the tests in test_binary_backend and then removing the try/except.
While there, I retargeted the tests to exercise BinaryBackend directly rather than by invoking pkgme machinery. We still would need a test cleanup branch to provide a swag of direct tests for MetadataBackend, to fix up the pdf tests and probably to change the binary tests to call the specific get methods rather than get_info() all the time.
Regarding dump_json not being to spec, I don't think it's relevant here. all_info doesn't get arguments, so it has no way of knowing what fields to generate values for. Thus SingleExternalH
| James Westby (james-w) wrote : | # |
On Tue, 10 Jan 2012 15:31:30 -0000, Jonathan Lange <email address hidden> wrote:
> I've fixed the XXX by making sure that a proper executable is set up
> for all of the tests in test_binary_backend and then removing the
> try/except.
Great, thanks.
> While there, I retargeted the tests to exercise BinaryBackend directly
> rather than by invoking pkgme machinery. We still would need a test
> cleanup branch to provide a swag of direct tests for MetadataBackend,
> to fix up the pdf tests and probably to change the binary tests to
> call the specific get methods rather than get_info() all the time.
Sounds good. Is there a card for this already?
> Regarding dump_json not being to spec, I don't think it's relevant
> here. all_info doesn't get arguments, so it has no way of knowing what
> fields to generate values for. Thus SingleExternalH
> always returns a dict with all of the information in it.
It's fugly, but...
http://
Thanks,
James
| Jonathan Lange (jml) wrote : | # |
By bad, all_info has the JSON dict written to it on stdin, but we don't acknowledge it. As you say, I think it's OK to leave as is.
Preview Diff
| 1 | === added file 'devportalbinary/backends/binary/all_info' |
| 2 | --- devportalbinary/backends/binary/all_info 1970-01-01 00:00:00 +0000 |
| 3 | +++ devportalbinary/backends/binary/all_info 2012-01-10 15:29:28 +0000 |
| 4 | @@ -0,0 +1,13 @@ |
| 5 | +#!/usr/bin/env python |
| 6 | +# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 7 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
| 8 | + |
| 9 | +from devportalbinary.binary import BinaryBackend |
| 10 | + |
| 11 | + |
| 12 | +def main(): |
| 13 | + BinaryBackend().dump_json() |
| 14 | + |
| 15 | + |
| 16 | +if __name__ == '__main__': |
| 17 | + main() |
| 18 | |
| 19 | === removed file 'devportalbinary/backends/binary/build_depends' |
| 20 | --- devportalbinary/backends/binary/build_depends 2011-11-21 16:16:36 +0000 |
| 21 | +++ devportalbinary/backends/binary/build_depends 1970-01-01 00:00:00 +0000 |
| 22 | @@ -1,16 +0,0 @@ |
| 23 | -#!/usr/bin/env python |
| 24 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 25 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
| 26 | - |
| 27 | -import os |
| 28 | - |
| 29 | -from devportalbinary.binary import guess_dependencies |
| 30 | - |
| 31 | - |
| 32 | -def main(): |
| 33 | - path = os.getcwd() |
| 34 | - print ', '.join(guess_dependencies(path)) |
| 35 | - |
| 36 | - |
| 37 | -if __name__ == '__main__': |
| 38 | - main() |
| 39 | |
| 40 | === removed file 'devportalbinary/backends/binary/depends' |
| 41 | --- devportalbinary/backends/binary/depends 2011-11-21 16:16:36 +0000 |
| 42 | +++ devportalbinary/backends/binary/depends 1970-01-01 00:00:00 +0000 |
| 43 | @@ -1,13 +0,0 @@ |
| 44 | -#!/usr/bin/env python |
| 45 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 46 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
| 47 | - |
| 48 | -from devportalbinary.binary import DEPENDS |
| 49 | - |
| 50 | - |
| 51 | -def main(): |
| 52 | - print DEPENDS |
| 53 | - |
| 54 | - |
| 55 | -if __name__ == '__main__': |
| 56 | - main() |
| 57 | |
| 58 | === removed file 'devportalbinary/backends/binary/description' |
| 59 | --- devportalbinary/backends/binary/description 2011-12-20 18:00:57 +0000 |
| 60 | +++ devportalbinary/backends/binary/description 1970-01-01 00:00:00 +0000 |
| 61 | @@ -1,19 +0,0 @@ |
| 62 | -#!/usr/bin/env python |
| 63 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 64 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
| 65 | - |
| 66 | -import json |
| 67 | -from devportalbinary.binary import ( |
| 68 | - DESCRIPTION, |
| 69 | - get_metadata, |
| 70 | - ) |
| 71 | - |
| 72 | - |
| 73 | -def main(): |
| 74 | - description = get_metadata(DESCRIPTION, None) |
| 75 | - if description: |
| 76 | - print description |
| 77 | - |
| 78 | - |
| 79 | -if __name__ == '__main__': |
| 80 | - main() |
| 81 | |
| 82 | === removed file 'devportalbinary/backends/binary/extra_files' |
| 83 | --- devportalbinary/backends/binary/extra_files 2011-12-20 13:51:05 +0000 |
| 84 | +++ devportalbinary/backends/binary/extra_files 1970-01-01 00:00:00 +0000 |
| 85 | @@ -1,37 +0,0 @@ |
| 86 | -#!/usr/bin/env python |
| 87 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 88 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
| 89 | - |
| 90 | -import json |
| 91 | -import os |
| 92 | -import sys |
| 93 | - |
| 94 | -from devportalbinary.binary import ( |
| 95 | - CATEGORIES, |
| 96 | - get_binary_desktop_file, |
| 97 | - get_install_file, |
| 98 | - get_metadata, |
| 99 | - PACKAGE_NAME, |
| 100 | - TAGLINE, |
| 101 | - ) |
| 102 | - |
| 103 | - |
| 104 | -def main(): |
| 105 | - metadata = get_metadata() |
| 106 | - package_name = metadata[PACKAGE_NAME] |
| 107 | - path = os.getcwd() |
| 108 | - install_file = get_install_file(package_name, path, True) |
| 109 | - desktop_file = get_binary_desktop_file( |
| 110 | - package_name, path, |
| 111 | - tagline=metadata.get(TAGLINE, ''), |
| 112 | - categories=metadata.get(CATEGORIES, '')) |
| 113 | - json.dump( |
| 114 | - { |
| 115 | - # XXX: Hardcoded literal attack! |
| 116 | - 'debian/install': install_file, |
| 117 | - 'debian/%s.desktop' % (package_name,): desktop_file.get_contents(), |
| 118 | - }, sys.stdout) |
| 119 | - |
| 120 | - |
| 121 | -if __name__ == '__main__': |
| 122 | - main() |
| 123 | |
| 124 | === removed file 'devportalbinary/backends/binary/package_name' |
| 125 | --- devportalbinary/backends/binary/package_name 2011-12-20 13:31:47 +0000 |
| 126 | +++ devportalbinary/backends/binary/package_name 1970-01-01 00:00:00 +0000 |
| 127 | @@ -1,17 +0,0 @@ |
| 128 | -#!/usr/bin/env python |
| 129 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 130 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
| 131 | - |
| 132 | -import json |
| 133 | -from devportalbinary.binary import ( |
| 134 | - get_metadata, |
| 135 | - PACKAGE_NAME, |
| 136 | - ) |
| 137 | - |
| 138 | - |
| 139 | -def main(): |
| 140 | - print get_metadata(PACKAGE_NAME) |
| 141 | - |
| 142 | - |
| 143 | -if __name__ == '__main__': |
| 144 | - main() |
| 145 | |
| 146 | === modified file 'devportalbinary/backends/binary/want' |
| 147 | --- devportalbinary/backends/binary/want 2011-11-21 16:16:36 +0000 |
| 148 | +++ devportalbinary/backends/binary/want 2012-01-10 15:29:28 +0000 |
| 149 | @@ -4,13 +4,10 @@ |
| 150 | |
| 151 | import os |
| 152 | |
| 153 | -from devportalbinary.binary import METADATA_FILE |
| 154 | +from devportalbinary.binary import BinaryBackend |
| 155 | |
| 156 | def main(): |
| 157 | - if os.path.exists(METADATA_FILE): |
| 158 | - print 10 |
| 159 | - else: |
| 160 | - print 0 |
| 161 | + print BinaryBackend().want() |
| 162 | |
| 163 | |
| 164 | if __name__ == '__main__': |
| 165 | |
| 166 | === added file 'devportalbinary/backends/pdf/all_info' |
| 167 | --- devportalbinary/backends/pdf/all_info 1970-01-01 00:00:00 +0000 |
| 168 | +++ devportalbinary/backends/pdf/all_info 2012-01-10 15:29:28 +0000 |
| 169 | @@ -0,0 +1,14 @@ |
| 170 | +#!/usr/bin/env python |
| 171 | +# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 172 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
| 173 | + |
| 174 | + |
| 175 | +from devportalbinary.pdf import PdfBackend |
| 176 | + |
| 177 | + |
| 178 | +def main(): |
| 179 | + PdfBackend().dump_json() |
| 180 | + |
| 181 | + |
| 182 | +if __name__ == '__main__': |
| 183 | + main() |
| 184 | |
| 185 | === removed file 'devportalbinary/backends/pdf/architecture' |
| 186 | --- devportalbinary/backends/pdf/architecture 2011-12-13 04:23:22 +0000 |
| 187 | +++ devportalbinary/backends/pdf/architecture 1970-01-01 00:00:00 +0000 |
| 188 | @@ -1,5 +0,0 @@ |
| 189 | -#!/bin/sh |
| 190 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 191 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
| 192 | - |
| 193 | -echo "all" |
| 194 | |
| 195 | === removed file 'devportalbinary/backends/pdf/build_depends' |
| 196 | --- devportalbinary/backends/pdf/build_depends 2011-12-05 22:20:24 +0000 |
| 197 | +++ devportalbinary/backends/pdf/build_depends 1970-01-01 00:00:00 +0000 |
| 198 | @@ -1,11 +0,0 @@ |
| 199 | -#!/usr/bin/env python |
| 200 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 201 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
| 202 | - |
| 203 | - |
| 204 | -def main(): |
| 205 | - print 'debhelper (>=7)' |
| 206 | - |
| 207 | - |
| 208 | -if __name__ == '__main__': |
| 209 | - main() |
| 210 | |
| 211 | === removed file 'devportalbinary/backends/pdf/depends' |
| 212 | --- devportalbinary/backends/pdf/depends 2011-12-20 13:31:47 +0000 |
| 213 | +++ devportalbinary/backends/pdf/depends 1970-01-01 00:00:00 +0000 |
| 214 | @@ -1,11 +0,0 @@ |
| 215 | -#!/usr/bin/env python |
| 216 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 217 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
| 218 | - |
| 219 | - |
| 220 | -def main(): |
| 221 | - print 'xdg-utils, ${misc:Depends}' |
| 222 | - |
| 223 | - |
| 224 | -if __name__ == '__main__': |
| 225 | - main() |
| 226 | |
| 227 | === removed file 'devportalbinary/backends/pdf/description' |
| 228 | --- devportalbinary/backends/pdf/description 2011-12-20 13:51:05 +0000 |
| 229 | +++ devportalbinary/backends/pdf/description 1970-01-01 00:00:00 +0000 |
| 230 | @@ -1,26 +0,0 @@ |
| 231 | -#!/usr/bin/env python |
| 232 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 233 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
| 234 | - |
| 235 | -import json |
| 236 | -from devportalbinary.binary import ( |
| 237 | - get_metadata, |
| 238 | - TAGLINE |
| 239 | - ) |
| 240 | - |
| 241 | - |
| 242 | -def main(): |
| 243 | - print get_metadata(TAGLINE) |
| 244 | - # Not included in metadata yet. |
| 245 | - #long_description = metadata["description"] |
| 246 | - #lines = long_description.split("\n") |
| 247 | - #new_lines = [] |
| 248 | - #for line in lines: |
| 249 | - # if not line.strip(): |
| 250 | - # line = "." |
| 251 | - # new_lines.append(" " + line) |
| 252 | - #print "\n".join([description] + new_lines) |
| 253 | - |
| 254 | - |
| 255 | -if __name__ == '__main__': |
| 256 | - main() |
| 257 | |
| 258 | === removed file 'devportalbinary/backends/pdf/extra_files' |
| 259 | --- devportalbinary/backends/pdf/extra_files 2011-12-20 13:51:05 +0000 |
| 260 | +++ devportalbinary/backends/pdf/extra_files 1970-01-01 00:00:00 +0000 |
| 261 | @@ -1,37 +0,0 @@ |
| 262 | -#!/usr/bin/env python |
| 263 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 264 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
| 265 | - |
| 266 | -import json |
| 267 | -import os |
| 268 | -import sys |
| 269 | - |
| 270 | -from devportalbinary.binary import ( |
| 271 | - CATEGORIES, |
| 272 | - get_pdf_desktop_file, |
| 273 | - get_install_file, |
| 274 | - get_metadata, |
| 275 | - PACKAGE_NAME, |
| 276 | - TAGLINE, |
| 277 | - ) |
| 278 | - |
| 279 | - |
| 280 | -def main(): |
| 281 | - metadata = get_metadata() |
| 282 | - package_name = metadata[PACKAGE_NAME] |
| 283 | - path = os.getcwd() |
| 284 | - install_file = get_install_file(package_name, path, True) |
| 285 | - desktop_file = get_pdf_desktop_file( |
| 286 | - package_name, path, |
| 287 | - tagline=metadata.get(TAGLINE, ''), |
| 288 | - categories=metadata.get(CATEGORIES, '')) |
| 289 | - extra_files = { |
| 290 | - # XXX: Hardcoded literal attack! |
| 291 | - 'debian/install': install_file, |
| 292 | - 'debian/%s.desktop' % (package_name,): desktop_file.get_contents(), |
| 293 | - } |
| 294 | - json.dump(extra_files, sys.stdout) |
| 295 | - |
| 296 | - |
| 297 | -if __name__ == '__main__': |
| 298 | - main() |
| 299 | |
| 300 | === removed file 'devportalbinary/backends/pdf/package_name' |
| 301 | --- devportalbinary/backends/pdf/package_name 2011-12-20 13:31:47 +0000 |
| 302 | +++ devportalbinary/backends/pdf/package_name 1970-01-01 00:00:00 +0000 |
| 303 | @@ -1,17 +0,0 @@ |
| 304 | -#!/usr/bin/env python |
| 305 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 306 | -# GNU Affero General Public License version 3 (see the file LICENSE). |
| 307 | - |
| 308 | -import json |
| 309 | -from devportalbinary.binary import ( |
| 310 | - get_metadata, |
| 311 | - PACKAGE_NAME, |
| 312 | - ) |
| 313 | - |
| 314 | - |
| 315 | -def main(): |
| 316 | - print get_metadata(PACKAGE_NAME) |
| 317 | - |
| 318 | - |
| 319 | -if __name__ == '__main__': |
| 320 | - main() |
| 321 | |
| 322 | === modified file 'devportalbinary/backends/pdf/want' |
| 323 | --- devportalbinary/backends/pdf/want 2011-12-13 01:52:36 +0000 |
| 324 | +++ devportalbinary/backends/pdf/want 2012-01-10 15:29:28 +0000 |
| 325 | @@ -4,20 +4,10 @@ |
| 326 | |
| 327 | import os |
| 328 | |
| 329 | -from devportalbinary.binary import METADATA_FILE |
| 330 | +from devportalbinary.pdf import PdfBackend |
| 331 | |
| 332 | def main(): |
| 333 | - want = False |
| 334 | - if os.path.exists(METADATA_FILE): |
| 335 | - files = os.listdir('.') |
| 336 | - files = [f for f in files if f not in (METADATA_FILE, 'debian')] |
| 337 | - if len(files) == 1: |
| 338 | - if files[0].endswith(".pdf"): |
| 339 | - want = True |
| 340 | - if want: |
| 341 | - print 20 |
| 342 | - else: |
| 343 | - print 0 |
| 344 | + print PdfBackend().want() |
| 345 | |
| 346 | |
| 347 | if __name__ == '__main__': |
| 348 | |
| 349 | === modified file 'devportalbinary/binary.py' |
| 350 | --- devportalbinary/binary.py 2011-12-22 22:41:37 +0000 |
| 351 | +++ devportalbinary/binary.py 2012-01-10 15:29:28 +0000 |
| 352 | @@ -20,62 +20,30 @@ |
| 353 | * That the entire contents of the tarball can be copied into |
| 354 | /opt/<package-name> and run from there |
| 355 | |
| 356 | -* That we have a metadata file, called 'devportal-metadata.json', in JSON, |
| 357 | - that specifies: |
| 358 | - * package_name |
| 359 | +* That we have a metadata file, called 'devportal-metadata.json', in JSON. |
| 360 | + See ``MetadataBackend``. |
| 361 | |
| 362 | The expectation is that this metadata file is generated from the developer |
| 363 | portal. |
| 364 | """ |
| 365 | |
| 366 | -# XXX: No idea about architecture |
| 367 | - |
| 368 | __all__ = [ |
| 369 | - 'get_install_file', |
| 370 | + 'BinaryBackend', |
| 371 | 'guess_executable', |
| 372 | 'iter_executables', |
| 373 | - 'METADATA_FILE', |
| 374 | ] |
| 375 | |
| 376 | |
| 377 | -import json |
| 378 | import os |
| 379 | import subprocess |
| 380 | |
| 381 | from pkgme.errors import PkgmeError |
| 382 | -from pkgme.info_elements import ( |
| 383 | - ApplicationName, |
| 384 | - Categories, |
| 385 | - Executable, |
| 386 | - PackageName, |
| 387 | - TagLine, |
| 388 | - ) |
| 389 | -from pkgme.package_files import ( |
| 390 | - DEBIAN_DIR, |
| 391 | - Desktop, |
| 392 | - ) |
| 393 | -from pkgme.project_info import DictInfo |
| 394 | from pkgme.run_script import run_subprocess |
| 395 | |
| 396 | from devportalbinary.database import PackageDatabase |
| 397 | - |
| 398 | - |
| 399 | -METADATA_FILE = 'devportal-metadata.json' |
| 400 | - |
| 401 | -# XXX: These duplicate the schema found in pkgme-service. |
| 402 | -# Keys found in the metadata file. |
| 403 | -CATEGORIES = 'categories' |
| 404 | -DESCRIPTION = 'description' |
| 405 | -# It's called package_name in the database, so this probably makes sense. |
| 406 | -PACKAGE_NAME = 'package_name' |
| 407 | -TAGLINE = 'tagline' |
| 408 | - |
| 409 | - |
| 410 | -# Always depend on these. |
| 411 | -# |
| 412 | -# XXX: jml just doing this because iamfuzz does. Need to either experiment or |
| 413 | -# consult expert. |
| 414 | -DEPENDS = '${shlibs:Depends}, ${misc:Depends}' |
| 415 | +from devportalbinary.metadata import MetadataBackend |
| 416 | + |
| 417 | + |
| 418 | |
| 419 | # XXX: No idea about how icons will be there. Ignoring for now. |
| 420 | |
| 421 | @@ -129,79 +97,6 @@ |
| 422 | yield os.path.relpath(file_path, path) |
| 423 | |
| 424 | |
| 425 | -_no_field = object() |
| 426 | -def get_metadata(field_name=None, default=_no_field, path=METADATA_FILE): |
| 427 | - """Return the value of ``field_name`` in metadata. |
| 428 | - |
| 429 | - :param field_name: The field to look up. If None, then return all the |
| 430 | - metadata as a dict. |
| 431 | - :param default: If provided, then this value will be returned if |
| 432 | - 'field_name' is not present in the metadata. |
| 433 | - :param path: The path to the metadata file, if unspecified, look for |
| 434 | - METADATA_FILE in the current working directory. |
| 435 | - :return: The value of the field. |
| 436 | - """ |
| 437 | - with open(path) as f: |
| 438 | - metadata = json.load(f) |
| 439 | - if field_name is None: |
| 440 | - return metadata |
| 441 | - value = metadata.get(field_name, default) |
| 442 | - if value is _no_field: |
| 443 | - raise KeyError(field_name) |
| 444 | - return value |
| 445 | - |
| 446 | - |
| 447 | -def get_install_file(package_name, path, include_desktop=False): |
| 448 | - """Generate the install file for 'package_name'.""" |
| 449 | - lines = [] |
| 450 | - # Sorting not actually needed for functionality, but makes the tests more |
| 451 | - # reliable. |
| 452 | - for filename in sorted(os.listdir(path)): |
| 453 | - if filename in (DEBIAN_DIR, METADATA_FILE): |
| 454 | - # We don't want to install the 'debian/' directory or the metadata |
| 455 | - # file. |
| 456 | - continue |
| 457 | - lines.append('%s opt/%s' % (filename, package_name)) |
| 458 | - if include_desktop: |
| 459 | - lines.append( |
| 460 | - 'debian/%s.desktop usr/share/applications' % (package_name,)) |
| 461 | - # Ending the file with a newline is basic good manners. |
| 462 | - lines.append('') |
| 463 | - return '\n'.join(lines) |
| 464 | - |
| 465 | - |
| 466 | -def get_desktop_file(package_name, executable, tagline=None, categories=None): |
| 467 | - info = { |
| 468 | - PackageName.name: package_name, |
| 469 | - ApplicationName.name: package_name.capitalize(), |
| 470 | - Executable.name: executable, |
| 471 | - TagLine.name: tagline, |
| 472 | - Categories.name: categories, |
| 473 | - } |
| 474 | - return Desktop.from_info(DictInfo(info)) |
| 475 | - |
| 476 | - |
| 477 | -def get_binary_desktop_file(package_name, path, tagline=None, |
| 478 | - categories=None): |
| 479 | - executable = guess_executable(package_name, iter_executables(path)) |
| 480 | - return get_desktop_file(package_name, |
| 481 | - '/opt/%s/%s' % (package_name, executable), tagline=tagline, |
| 482 | - categories=categories) |
| 483 | - |
| 484 | - |
| 485 | -def get_pdf_desktop_file(package_name, path, tagline=None, categories=None): |
| 486 | - pdf_filename = None |
| 487 | - for filename in os.listdir(path): |
| 488 | - if filename.endswith('.pdf'): |
| 489 | - pdf_filename = filename |
| 490 | - break |
| 491 | - if pdf_filename is None: |
| 492 | - raise AssertionError("Couldn't find pdf file") |
| 493 | - executable = '/usr/bin/xdg-open /opt/%s/%s' % (package_name, pdf_filename) |
| 494 | - return get_desktop_file(package_name, executable, tagline=tagline, |
| 495 | - categories=categories) |
| 496 | - |
| 497 | - |
| 498 | def get_file_type(path): |
| 499 | return get_file_types([path])[0] |
| 500 | |
| 501 | @@ -296,3 +191,34 @@ |
| 502 | cwd = os.getcwd() |
| 503 | print guess_executable(os.path.dirname(cwd), iter_executables(cwd)) |
| 504 | return 0 |
| 505 | + |
| 506 | + |
| 507 | +class BinaryBackend(MetadataBackend): |
| 508 | + """A backend that uses MyApps metadata to build a package for a binary.""" |
| 509 | + |
| 510 | + # XXX: jml just doing this because iamfuzz does. Need to either experiment |
| 511 | + # or consult expert. |
| 512 | + DEPENDS = '${shlibs:Depends}, ${misc:Depends}' |
| 513 | + |
| 514 | + def get_architecture(self): |
| 515 | + # XXX: No idea about architecture |
| 516 | + return None |
| 517 | + |
| 518 | + def get_build_depends(self, metadata): |
| 519 | + return ', '.join(guess_dependencies(self.path)) |
| 520 | + |
| 521 | + def get_depends(self, metadata): |
| 522 | + return self.DEPENDS |
| 523 | + |
| 524 | + def get_description(self, metadata): |
| 525 | + return metadata.get(self.DESCRIPTION, '') |
| 526 | + |
| 527 | + def get_executable(self, package_name): |
| 528 | + executable = guess_executable(package_name, iter_executables(self.path)) |
| 529 | + return '/opt/%s/%s' % (package_name, executable) |
| 530 | + |
| 531 | + def want(self): |
| 532 | + if os.path.exists(self.metadata_path): |
| 533 | + return 10 |
| 534 | + else: |
| 535 | + return 0 |
| 536 | |
| 537 | === added file 'devportalbinary/metadata.py' |
| 538 | --- devportalbinary/metadata.py 1970-01-01 00:00:00 +0000 |
| 539 | +++ devportalbinary/metadata.py 2012-01-10 15:29:28 +0000 |
| 540 | @@ -0,0 +1,204 @@ |
| 541 | +# Copyright 2011-2012 Canonical Ltd. This software is licensed under the |
| 542 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
| 543 | + |
| 544 | +"""A pkgme backend that gets much of its data from MyApps. |
| 545 | + |
| 546 | +The main idea behind this backend is that it looks for a file, |
| 547 | +'devportal-metadata.json', created with data provided by users of MyApps. It |
| 548 | +then uses this data, along with inferences from submitted files to create a |
| 549 | +Debian package. |
| 550 | +""" |
| 551 | + |
| 552 | +__all__ = [ |
| 553 | + 'MetadataBackend', |
| 554 | + ] |
| 555 | + |
| 556 | +import json |
| 557 | +import os |
| 558 | +import sys |
| 559 | + |
| 560 | +from pkgme.info_elements import ( |
| 561 | + ApplicationName, |
| 562 | + Architecture, |
| 563 | + BuildDepends, |
| 564 | + Categories, |
| 565 | + Depends, |
| 566 | + Description, |
| 567 | + Executable, |
| 568 | + ExtraFiles, |
| 569 | + PackageName, |
| 570 | + TagLine, |
| 571 | + ) |
| 572 | +from pkgme.package_files import ( |
| 573 | + DEBIAN_DIR, |
| 574 | + Desktop, |
| 575 | + ) |
| 576 | +from pkgme.project_info import DictInfo |
| 577 | + |
| 578 | + |
| 579 | +_no_field = object() |
| 580 | +def get_metadata(field_name=None, default=_no_field, path=None): |
| 581 | + """Return the value of ``field_name`` in metadata. |
| 582 | + |
| 583 | + :param field_name: The field to look up. If None, then return all the |
| 584 | + metadata as a dict. |
| 585 | + :param default: If provided, then this value will be returned if |
| 586 | + 'field_name' is not present in the metadata. |
| 587 | + :param path: The path to the metadata file, if unspecified, look for |
| 588 | + ``MetadataBackend.METADATA_FILE`` in the current working directory. |
| 589 | + :return: The value of the field. |
| 590 | + """ |
| 591 | + if path is None: |
| 592 | + path = MetadataBackend.METADATA_FILE |
| 593 | + with open(path) as f: |
| 594 | + metadata = json.load(f) |
| 595 | + if field_name is None: |
| 596 | + return metadata |
| 597 | + value = metadata.get(field_name, default) |
| 598 | + if value is _no_field: |
| 599 | + raise KeyError(field_name) |
| 600 | + return value |
| 601 | + |
| 602 | + |
| 603 | +def get_install_file(package_name, path, include_desktop=False): |
| 604 | + """Generate the install file for 'package_name'.""" |
| 605 | + lines = [] |
| 606 | + # Sorting not actually needed for functionality, but makes the tests more |
| 607 | + # reliable. |
| 608 | + for filename in sorted(os.listdir(path)): |
| 609 | + if filename in (DEBIAN_DIR, MetadataBackend.METADATA_FILE): |
| 610 | + # We don't want to install the 'debian/' directory or the metadata |
| 611 | + # file. |
| 612 | + continue |
| 613 | + lines.append('%s opt/%s' % (filename, package_name)) |
| 614 | + if include_desktop: |
| 615 | + lines.append( |
| 616 | + 'debian/%s.desktop usr/share/applications' % (package_name,)) |
| 617 | + # Ending the file with a newline is basic good manners. |
| 618 | + lines.append('') |
| 619 | + return '\n'.join(lines) |
| 620 | + |
| 621 | + |
| 622 | +class MetadataBackend(object): |
| 623 | + """A backend that is mostly powered by metadata from MyApps.""" |
| 624 | + |
| 625 | + # Where the metadata file lives. |
| 626 | + METADATA_FILE = 'devportal-metadata.json' |
| 627 | + |
| 628 | + # Keys found in the metadata file. |
| 629 | + # XXX: These duplicate the schema found in pkgme-service. |
| 630 | + CATEGORIES = 'categories' |
| 631 | + DESCRIPTION = 'description' |
| 632 | + PACKAGE_NAME = 'package_name' |
| 633 | + TAGLINE = 'tagline' |
| 634 | + |
| 635 | + def __init__(self, path=None): |
| 636 | + """Construct a ``MetadataBackend``.""" |
| 637 | + if path is None: |
| 638 | + path = os.getcwd() |
| 639 | + self.path = path |
| 640 | + self.metadata_path = os.path.join(path, self.METADATA_FILE) |
| 641 | + |
| 642 | + def get_architecture(self): |
| 643 | + """Get the architecture for the package. |
| 644 | + |
| 645 | + :return: The architecture tag, or None if no architecture is |
| 646 | + specified. |
| 647 | + """ |
| 648 | + raise NotImplementedError(self.get_architecture) |
| 649 | + |
| 650 | + def get_build_depends(self, metadata): |
| 651 | + """Get the build dependencies of the package.""" |
| 652 | + raise NotImplementedError(self.get_build_depends) |
| 653 | + |
| 654 | + def get_desktop_file(self, package_name, tagline=None, categories=None): |
| 655 | + """Get the desktop file for the package. |
| 656 | + |
| 657 | + :return: A ``Desktop``. |
| 658 | + """ |
| 659 | + executable = self.get_executable(package_name) |
| 660 | + info = { |
| 661 | + PackageName.name: package_name, |
| 662 | + ApplicationName.name: package_name.capitalize(), |
| 663 | + Executable.name: executable, |
| 664 | + TagLine.name: tagline, |
| 665 | + Categories.name: categories, |
| 666 | + } |
| 667 | + return Desktop.from_info(DictInfo(info)) |
| 668 | + |
| 669 | + def get_depends(self, metadata): |
| 670 | + """Get the dependencies for the package.""" |
| 671 | + raise NotImplementedError(self.depends) |
| 672 | + |
| 673 | + def get_description(self, metadata): |
| 674 | + """Get the package description.""" |
| 675 | + raise NotImplementedError(self.get_description) |
| 676 | + |
| 677 | + def get_executable(self, package_name): |
| 678 | + """Return the path to the executable.""" |
| 679 | + raise NotImplementedError(self.get_executable) |
| 680 | + |
| 681 | + def get_extra_files(self, package_name, metadata): |
| 682 | + """Get the extra files for the package. |
| 683 | + |
| 684 | + Assumes that the only extra files are a desktop file and an install |
| 685 | + file. Delegates to ``MetadataBackend.get_desktop_file`` for the |
| 686 | + desktop file. |
| 687 | + """ |
| 688 | + install_file = get_install_file(package_name, self.path, True) |
| 689 | + desktop_file = self.get_desktop_file( |
| 690 | + package_name, |
| 691 | + tagline=metadata.get(self.TAGLINE, ''), |
| 692 | + categories=metadata.get(self.CATEGORIES, '')) |
| 693 | + return { |
| 694 | + # XXX: Hardcoded literal attack! |
| 695 | + 'debian/install': install_file, |
| 696 | + 'debian/%s.desktop' % (package_name,): desktop_file.get_contents(), |
| 697 | + } |
| 698 | + |
| 699 | + def get_metadata(self): |
| 700 | + """Get the metadata for this backend. |
| 701 | + |
| 702 | + Looks for the metadata in a file called ``METADATA_FILE`` in the |
| 703 | + directory given to the constructor. |
| 704 | + |
| 705 | + :return: A dict of metadata. |
| 706 | + """ |
| 707 | + return get_metadata(path=self.metadata_path) |
| 708 | + |
| 709 | + def get_info(self, metadata): |
| 710 | + """Return a dict of InfoElements given 'metadata'. |
| 711 | + |
| 712 | + This is the work-horse method of the backend. It takes a dict of |
| 713 | + metadata, as extracted from a devportal-metadata.json file, and |
| 714 | + converts it into a dictionary mapping InfoElements to their actual |
| 715 | + values. |
| 716 | + |
| 717 | + This dictionary will then be dumped as the JSON output of 'all_info', |
| 718 | + substituting the InfoElements for their names. |
| 719 | + """ |
| 720 | + package_name = metadata[self.PACKAGE_NAME] |
| 721 | + info = { |
| 722 | + BuildDepends: self.get_build_depends(metadata), |
| 723 | + Depends: self.get_depends(metadata), |
| 724 | + Description: self.get_description(metadata), |
| 725 | + ExtraFiles: self.get_extra_files(package_name, metadata), |
| 726 | + PackageName: package_name, |
| 727 | + } |
| 728 | + architecture = self.get_architecture() |
| 729 | + if architecture: |
| 730 | + info[Architecture] = architecture |
| 731 | + return info |
| 732 | + |
| 733 | + def dump_json(self, stream=sys.stdout): |
| 734 | + """Dump the information from this backend as JSON.""" |
| 735 | + info = self.get_info(self.get_metadata()) |
| 736 | + info_for_json = dict( |
| 737 | + (element.name, data) for element, data in info.items()) |
| 738 | + json.dump(info_for_json, stream) |
| 739 | + |
| 740 | + def want(self): |
| 741 | + """How relevant this backend is.""" |
| 742 | + raise NotImplementedError(self.want) |
| 743 | + |
| 744 | + |
| 745 | |
| 746 | === added file 'devportalbinary/pdf.py' |
| 747 | --- devportalbinary/pdf.py 1970-01-01 00:00:00 +0000 |
| 748 | +++ devportalbinary/pdf.py 2012-01-10 15:29:28 +0000 |
| 749 | @@ -0,0 +1,47 @@ |
| 750 | +# Copyright 2011-2012 Canonical Ltd. This software is licensed under the |
| 751 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
| 752 | + |
| 753 | +import os |
| 754 | + |
| 755 | +from devportalbinary.metadata import MetadataBackend |
| 756 | + |
| 757 | + |
| 758 | +class PdfBackend(MetadataBackend): |
| 759 | + """A backend that uses MyApps metadata to build a package for a PDF.""" |
| 760 | + |
| 761 | + def get_architecture(self): |
| 762 | + return 'all' |
| 763 | + |
| 764 | + def get_build_depends(self, metadata): |
| 765 | + return 'debhelper (>=7)' |
| 766 | + |
| 767 | + def get_depends(self, metadata): |
| 768 | + return 'xdg-utils, ${misc:Depends}' |
| 769 | + |
| 770 | + def get_description(self, metadata): |
| 771 | + return metadata[self.TAGLINE] |
| 772 | + |
| 773 | + def get_executable(self, package_name): |
| 774 | + pdf_filename = None |
| 775 | + for filename in os.listdir(self.path): |
| 776 | + if filename.endswith('.pdf'): |
| 777 | + pdf_filename = filename |
| 778 | + break |
| 779 | + if pdf_filename is None: |
| 780 | + return None |
| 781 | + return '/usr/bin/xdg-open /opt/%s/%s' % (package_name, pdf_filename) |
| 782 | + |
| 783 | + def want(self): |
| 784 | + want = False |
| 785 | + if os.path.exists(self.metadata_path): |
| 786 | + files = os.listdir(self.path) |
| 787 | + files = [ |
| 788 | + f for f in files |
| 789 | + if f not in (self.METADATA_FILE, 'debian')] |
| 790 | + if len(files) == 1: |
| 791 | + if files[0].endswith(".pdf"): |
| 792 | + want = True |
| 793 | + if want: |
| 794 | + return 20 |
| 795 | + else: |
| 796 | + return 0 |
| 797 | |
| 798 | === modified file 'devportalbinary/testing.py' |
| 799 | --- devportalbinary/testing.py 2011-12-22 22:41:37 +0000 |
| 800 | +++ devportalbinary/testing.py 2012-01-10 15:29:28 +0000 |
| 801 | @@ -9,7 +9,7 @@ |
| 802 | |
| 803 | from pkgme.testing import TempdirFixture |
| 804 | |
| 805 | -from devportalbinary.binary import METADATA_FILE |
| 806 | +from devportalbinary.binary import MetadataBackend |
| 807 | from devportalbinary.database import PackageDatabase |
| 808 | |
| 809 | |
| 810 | @@ -67,7 +67,7 @@ |
| 811 | super(MetadataFixture, self).setUp() |
| 812 | self.tempdir = self.useFixture(TempdirFixture()) |
| 813 | self.path = self.tempdir.path |
| 814 | - self.metadata_path = os.path.join(self.path, METADATA_FILE) |
| 815 | + self.metadata_path = os.path.join(self.path, MetadataBackend.METADATA_FILE) |
| 816 | with open(self.metadata_path, 'w') as fp: |
| 817 | json.dump(self._metadata, fp) |
| 818 | |
| 819 | |
| 820 | === modified file 'devportalbinary/tests/test_binary.py' |
| 821 | --- devportalbinary/tests/test_binary.py 2011-12-22 22:41:37 +0000 |
| 822 | +++ devportalbinary/tests/test_binary.py 2012-01-10 15:29:28 +0000 |
| 823 | @@ -1,4 +1,4 @@ |
| 824 | -# Copyright 2011 Canonical Ltd. This software is licensed under the |
| 825 | +# Copyright 2011-2012 Canonical Ltd. This software is licensed under the |
| 826 | # GNU Affero General Public License version 3 (see the file LICENSE). |
| 827 | |
| 828 | import os |
| 829 | @@ -6,25 +6,17 @@ |
| 830 | from testtools import TestCase |
| 831 | from testtools.matchers import StartsWith |
| 832 | |
| 833 | -from pkgme.package_files import DEBIAN_DIR |
| 834 | -from pkgme.testing import ( |
| 835 | - AreDesktopValuesFor, |
| 836 | - TempdirFixture, |
| 837 | - ) |
| 838 | +from pkgme.testing import TempdirFixture |
| 839 | |
| 840 | from devportalbinary.binary import ( |
| 841 | - get_binary_desktop_file, |
| 842 | + BinaryBackend, |
| 843 | get_file_type, |
| 844 | get_file_types, |
| 845 | - get_install_file, |
| 846 | - get_metadata, |
| 847 | - get_pdf_desktop_file, |
| 848 | get_shared_library_dependencies, |
| 849 | guess_dependencies, |
| 850 | guess_executable, |
| 851 | iter_binaries, |
| 852 | iter_executables, |
| 853 | - METADATA_FILE, |
| 854 | needed_libraries_from_objdump, |
| 855 | NoBinariesFound, |
| 856 | UnknownDependency, |
| 857 | @@ -33,134 +25,16 @@ |
| 858 | DatabaseFixture, |
| 859 | get_test_data_dir_path, |
| 860 | get_test_data_file_path, |
| 861 | - MetadataFixture, |
| 862 | ) |
| 863 | |
| 864 | |
| 865 | -class MetadataTests(TestCase): |
| 866 | - |
| 867 | - def test_metadata_file(self): |
| 868 | - self.assertEqual('devportal-metadata.json', METADATA_FILE) |
| 869 | - |
| 870 | - def test_get_metadata_field_present(self): |
| 871 | - # get_metadata returns the metadata value of the requested field. |
| 872 | - metadata = { |
| 873 | - 'foo': self.getUniqueString(), |
| 874 | - 'bar': self.getUniqueInteger(), |
| 875 | - } |
| 876 | - path = self.useFixture(MetadataFixture(metadata)).metadata_path |
| 877 | - foo = get_metadata('foo', path=path) |
| 878 | - self.assertEqual(metadata['foo'], foo) |
| 879 | - |
| 880 | - def test_get_metadata_default_file(self): |
| 881 | - # By default, get_metadata looks for the METADATA_FILE in the current |
| 882 | - # working directory. |
| 883 | - metadata = { |
| 884 | - 'foo': self.getUniqueString(), |
| 885 | - 'bar': self.getUniqueInteger(), |
| 886 | - } |
| 887 | - path = self.useFixture(MetadataFixture(metadata)).path |
| 888 | - self.addCleanup(os.chdir, os.getcwd()) |
| 889 | - os.chdir(path) |
| 890 | - foo = get_metadata('foo') |
| 891 | - self.assertEqual(metadata['foo'], foo) |
| 892 | - |
| 893 | - def test_get_metadata_field_not_present_default_provided(self): |
| 894 | - # get_metadata returns the provided default value if the field is not |
| 895 | - # present in the metadata. |
| 896 | - metadata = {} |
| 897 | - path = self.useFixture(MetadataFixture(metadata)).metadata_path |
| 898 | - default = object() |
| 899 | - foo = get_metadata('foo', default, path=path) |
| 900 | - self.assertIs(default, foo) |
| 901 | - |
| 902 | - def test_get_metadata_field_not_present_no_default(self): |
| 903 | - # get_metadata raises an exception if the field isn't there and no |
| 904 | - # default was provided. |
| 905 | - metadata = {} |
| 906 | - field = self.getUniqueString() |
| 907 | - path = self.useFixture(MetadataFixture(metadata)).metadata_path |
| 908 | - e = self.assertRaises(KeyError, get_metadata, field, path=path) |
| 909 | - self.assertEqual(repr(field), str(e)) |
| 910 | - |
| 911 | - def test_get_metadata_all_fields(self): |
| 912 | - # get_metadata returns the metadata value of the requested field. |
| 913 | - metadata = { |
| 914 | - 'foo': self.getUniqueString(), |
| 915 | - 'bar': self.getUniqueInteger(), |
| 916 | - } |
| 917 | - path = self.useFixture(MetadataFixture(metadata)).metadata_path |
| 918 | - found_metadata = get_metadata(path=path) |
| 919 | - self.assertEqual(metadata, found_metadata) |
| 920 | - |
| 921 | - |
| 922 | class TestObjDump(TestCase): |
| 923 | |
| 924 | def test_no_binaries(self): |
| 925 | self.assertRaises(NoBinariesFound, needed_libraries_from_objdump, []) |
| 926 | |
| 927 | |
| 928 | -class InstallFileTests(TestCase): |
| 929 | - |
| 930 | - def test_install_file(self): |
| 931 | - # The install file instructs debhelper to copy everything in the |
| 932 | - # top-level to /opt/<package-name>. |
| 933 | - tempdir = self.useFixture(TempdirFixture()) |
| 934 | - tempdir.touch('some-file') |
| 935 | - install_file = get_install_file('package-name', tempdir.path) |
| 936 | - self.assertEqual("some-file opt/package-name\n", install_file) |
| 937 | - |
| 938 | - def test_install_file_many_files_and_directories(self): |
| 939 | - # The install file instructs debhelper to copy everything in the |
| 940 | - # top-level to /opt/<package-name>. |
| 941 | - tempdir = self.useFixture(TempdirFixture()) |
| 942 | - tempdir.touch('some-file') |
| 943 | - tempdir.mkdir('directory') |
| 944 | - install_file = get_install_file('package-name', tempdir.path) |
| 945 | - self.assertEqual( |
| 946 | - "directory opt/package-name\n" |
| 947 | - "some-file opt/package-name\n", |
| 948 | - install_file) |
| 949 | - |
| 950 | - def test_skip_debian(self): |
| 951 | - # The install file instructs debhelper to copy everything in the |
| 952 | - # top-level to /opt/<package-name>, except for the 'debian' directory. |
| 953 | - tempdir = self.useFixture(TempdirFixture()) |
| 954 | - tempdir.touch('some-file') |
| 955 | - tempdir.mkdir('directory') |
| 956 | - tempdir.mkdir(DEBIAN_DIR) |
| 957 | - install_file = get_install_file('package-name', tempdir.path) |
| 958 | - self.assertEqual( |
| 959 | - "directory opt/package-name\n" |
| 960 | - "some-file opt/package-name\n", |
| 961 | - install_file) |
| 962 | - |
| 963 | - def test_skip_metadata(self): |
| 964 | - # The install file instructs debhelper to copy everything in the |
| 965 | - # top-level to /opt/<package-name>, except for the 'debian' directory |
| 966 | - # and the metadata file. |
| 967 | - tempdir = self.useFixture(TempdirFixture()) |
| 968 | - tempdir.touch('some-file') |
| 969 | - tempdir.mkdir('directory') |
| 970 | - tempdir.touch(METADATA_FILE) |
| 971 | - install_file = get_install_file('package-name', tempdir.path) |
| 972 | - self.assertEqual( |
| 973 | - "directory opt/package-name\n" |
| 974 | - "some-file opt/package-name\n", |
| 975 | - install_file) |
| 976 | - |
| 977 | - def test_include_desktop_file(self): |
| 978 | - tempdir = self.useFixture(TempdirFixture()) |
| 979 | - tempdir.touch('some-file') |
| 980 | - install_file = get_install_file( |
| 981 | - 'package-name', tempdir.path, include_desktop=True) |
| 982 | - self.assertEqual( |
| 983 | - "some-file opt/package-name\n" |
| 984 | - "debian/package-name.desktop usr/share/applications\n", |
| 985 | - install_file) |
| 986 | - |
| 987 | - |
| 988 | -class DesktopFileTests(TestCase): |
| 989 | +class BackendTests(TestCase): |
| 990 | |
| 991 | def test_executable_is_best_guess(self): |
| 992 | package_name = self.getUniqueString() |
| 993 | @@ -168,45 +42,10 @@ |
| 994 | tempdir.mkdir('whatever') |
| 995 | tempdir.touch('whatever/not-the-best', 0755) |
| 996 | tempdir.touch('the-best', 0755) |
| 997 | - desktop_file = get_binary_desktop_file(package_name, tempdir.path) |
| 998 | - self.assertThat( |
| 999 | - {'Exec': '/opt/%s/the-best' % (package_name,)}, |
| 1000 | - AreDesktopValuesFor(desktop_file)) |
| 1001 | - |
| 1002 | - def test_app_name_is_capitalized_package_name(self): |
| 1003 | - # We don't have any information on the package name, so try to guess |
| 1004 | - # the application name. |
| 1005 | - tempdir = self.useFixture(TempdirFixture()) |
| 1006 | - package_name = self.getUniqueString() |
| 1007 | - desktop_file = get_binary_desktop_file(package_name, tempdir.path) |
| 1008 | - self.assertThat( |
| 1009 | - {'Name': package_name.capitalize()}, |
| 1010 | - AreDesktopValuesFor(desktop_file)) |
| 1011 | - |
| 1012 | - def test_category_and_tagline_are_specified(self): |
| 1013 | - # We just pass the category and comment through. |
| 1014 | - tempdir = self.useFixture(TempdirFixture()) |
| 1015 | - package_name = self.getUniqueString() |
| 1016 | - tagline = self.getUniqueString() |
| 1017 | - categories = self.getUniqueString() |
| 1018 | - desktop_file = get_binary_desktop_file( |
| 1019 | - package_name, tempdir.path, tagline=tagline, categories=categories) |
| 1020 | - self.assertThat( |
| 1021 | - {'Comment': tagline, 'Categories': categories}, |
| 1022 | - AreDesktopValuesFor(desktop_file)) |
| 1023 | - |
| 1024 | - def test_pdf_exec_line(self): |
| 1025 | - tempdir = self.useFixture(TempdirFixture()) |
| 1026 | - tempdir.touch('foo.pdf') |
| 1027 | - package_name = self.getUniqueString() |
| 1028 | - tagline = self.getUniqueString() |
| 1029 | - categories = self.getUniqueString() |
| 1030 | - desktop_file = get_pdf_desktop_file( |
| 1031 | - package_name, tempdir.path, tagline=tagline, categories=categories) |
| 1032 | - self.assertThat( |
| 1033 | - {'Exec': '/usr/bin/xdg-open /opt/%s/%s' |
| 1034 | - % (package_name, 'foo.pdf')}, |
| 1035 | - AreDesktopValuesFor(desktop_file)) |
| 1036 | + backend = BinaryBackend(tempdir.path) |
| 1037 | + self.assertEqual( |
| 1038 | + '/opt/%s/the-best' % (package_name,), |
| 1039 | + backend.get_executable(package_name)) |
| 1040 | |
| 1041 | |
| 1042 | class FindExecutableTests(TestCase): |
| 1043 | @@ -380,7 +219,7 @@ |
| 1044 | self.assertEqual(set(['libc6']), deps) |
| 1045 | |
| 1046 | def test_guess_dependencies_error_on_unknown_dependency(self): |
| 1047 | - db = self.useFixture(DatabaseFixture()).db |
| 1048 | + self.useFixture(DatabaseFixture()) |
| 1049 | e = self.assertRaises(UnknownDependency, |
| 1050 | guess_dependencies, get_test_data_dir_path('hello')) |
| 1051 | self.assertEqual('Can\'t find dependency for "libc.so.6".', str(e)) |
| 1052 | |
| 1053 | === modified file 'devportalbinary/tests/test_binary_backend.py' |
| 1054 | --- devportalbinary/tests/test_binary_backend.py 2011-12-22 22:41:37 +0000 |
| 1055 | +++ devportalbinary/tests/test_binary_backend.py 2012-01-10 15:29:28 +0000 |
| 1056 | @@ -1,8 +1,6 @@ |
| 1057 | # Copyright 2011 Canonical Ltd. This software is licensed under the |
| 1058 | # GNU Affero General Public License version 3 (see the file LICENSE). |
| 1059 | |
| 1060 | -import json |
| 1061 | -import os |
| 1062 | import shutil |
| 1063 | |
| 1064 | from fixtures import TempDir |
| 1065 | @@ -12,7 +10,6 @@ |
| 1066 | Matcher, |
| 1067 | ) |
| 1068 | |
| 1069 | -from pkgme.backend import ExternalHelpersBackend, get_backend_dir |
| 1070 | from pkgme.info_elements import ( |
| 1071 | BuildDepends, |
| 1072 | Description, |
| 1073 | @@ -22,15 +19,11 @@ |
| 1074 | ) |
| 1075 | |
| 1076 | from devportalbinary.binary import ( |
| 1077 | - CATEGORIES, |
| 1078 | - DESCRIPTION, |
| 1079 | - DEPENDS, |
| 1080 | - get_binary_desktop_file, |
| 1081 | - get_install_file, |
| 1082 | + BinaryBackend, |
| 1083 | guess_dependencies, |
| 1084 | - PACKAGE_NAME, |
| 1085 | - TAGLINE, |
| 1086 | + MetadataBackend, |
| 1087 | ) |
| 1088 | +from devportalbinary.metadata import get_install_file |
| 1089 | from devportalbinary.testing import ( |
| 1090 | DatabaseFixture, |
| 1091 | get_test_data_file_path, |
| 1092 | @@ -38,11 +31,6 @@ |
| 1093 | ) |
| 1094 | |
| 1095 | |
| 1096 | -BACKEND_NAME = 'binary' |
| 1097 | - |
| 1098 | -backend_dir = get_backend_dir(__file__, BACKEND_NAME) |
| 1099 | - |
| 1100 | - |
| 1101 | class HasField(Matcher): |
| 1102 | """Matches if 'info' has a field with the given value.""" |
| 1103 | |
| 1104 | @@ -52,86 +40,95 @@ |
| 1105 | self.field_value = field_value |
| 1106 | |
| 1107 | def match(self, info): |
| 1108 | - return Equals( |
| 1109 | - {self.field.name: self.field_value}).match( |
| 1110 | - info.get_all([self.field.name])) |
| 1111 | + return Equals(self.field_value).match(info[self.field]) |
| 1112 | |
| 1113 | |
| 1114 | class BinaryBackendTests(TestCase): |
| 1115 | |
| 1116 | + def make_metadata(self, package_name=None, description=None, tagline=None, |
| 1117 | + categories=None): |
| 1118 | + if package_name is None: |
| 1119 | + package_name = self.getUniqueString('package-name') |
| 1120 | + metadata = {MetadataBackend.PACKAGE_NAME: package_name} |
| 1121 | + if description is not None: |
| 1122 | + metadata[MetadataBackend.DESCRIPTION] = description |
| 1123 | + if tagline is not None: |
| 1124 | + metadata[MetadataBackend.TAGLINE] = tagline |
| 1125 | + if categories is not None: |
| 1126 | + metadata[MetadataBackend.CATEGORIES] = categories |
| 1127 | + return metadata |
| 1128 | + |
| 1129 | + def make_backend(self, path=None): |
| 1130 | + if path is None: |
| 1131 | + path = self.useFixture(TempDir()).path |
| 1132 | + backend = BinaryBackend(path) |
| 1133 | + shutil.copy( |
| 1134 | + get_test_data_file_path('hello', 'hello'), path) |
| 1135 | + db = self.useFixture(DatabaseFixture()).db |
| 1136 | + db.update_source_package('eglibc', [[('libc.so.6', 'libc6')]]) |
| 1137 | + return backend |
| 1138 | + |
| 1139 | def test_want_with_metadata(self): |
| 1140 | # If we detect a binary, then we score 10. The way we determine if |
| 1141 | # something is a binary is if it has a devportal-metadata.json in its |
| 1142 | # top-level. |
| 1143 | path = self.useFixture(MetadataFixture({})).path |
| 1144 | - backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) |
| 1145 | - self.assertEqual(10, backend.want(path)) |
| 1146 | + backend = self.make_backend(path) |
| 1147 | + self.assertEqual(10, backend.want()) |
| 1148 | |
| 1149 | def test_want_without_metadata(self): |
| 1150 | # If we do *not* detect a binary, then we score 0. The way we |
| 1151 | # determine if something is a binary is if it has a |
| 1152 | # devportal-metadata.json in its top-level. |
| 1153 | - tempdir = self.useFixture(TempDir()) |
| 1154 | - backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) |
| 1155 | - self.assertEqual(0, backend.want(tempdir.path)) |
| 1156 | + backend = self.make_backend() |
| 1157 | + self.assertEqual(0, backend.want()) |
| 1158 | |
| 1159 | def test_package_name(self): |
| 1160 | # The binary backend gets the package name from the metadata file. |
| 1161 | - path = self.useFixture(MetadataFixture({PACKAGE_NAME: 'foo'})).path |
| 1162 | - backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) |
| 1163 | - info = backend.get_info(path) |
| 1164 | + backend = self.make_backend() |
| 1165 | + metadata = self.make_metadata(package_name='foo') |
| 1166 | + info = backend.get_info(metadata) |
| 1167 | self.assertThat(info, HasField(PackageName, 'foo')) |
| 1168 | |
| 1169 | def test_description(self): |
| 1170 | # The binary backend uses the package description that's in the |
| 1171 | # metadata. |
| 1172 | description = self.getUniqueString() |
| 1173 | - path = self.useFixture(MetadataFixture({ |
| 1174 | - PACKAGE_NAME: 'foo', |
| 1175 | - DESCRIPTION: description, |
| 1176 | - })).path |
| 1177 | - backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) |
| 1178 | - info = backend.get_info(path) |
| 1179 | + metadata = self.make_metadata(description=description) |
| 1180 | + backend = self.make_backend() |
| 1181 | + info = backend.get_info(metadata) |
| 1182 | self.assertThat(info, HasField(Description, description)) |
| 1183 | |
| 1184 | def test_no_description(self): |
| 1185 | # If no description is provided in the metadata then the description |
| 1186 | # in the package info is just an empty string. |
| 1187 | - path = self.useFixture(MetadataFixture({PACKAGE_NAME: 'foo'})).path |
| 1188 | - backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) |
| 1189 | - info = backend.get_info(path) |
| 1190 | + backend = self.make_backend() |
| 1191 | + metadata = self.make_metadata() |
| 1192 | + info = backend.get_info(metadata) |
| 1193 | self.assertThat(info, HasField(Description, '')) |
| 1194 | |
| 1195 | def test_build_depends(self): |
| 1196 | # Make sure there's a database. |
| 1197 | - db = self.useFixture(DatabaseFixture()).db |
| 1198 | - db.update_source_package('eglibc', [[('libc.so.6', 'libc6')]]) |
| 1199 | - path = self.useFixture(MetadataFixture({PACKAGE_NAME: 'foo'})).path |
| 1200 | - shutil.copy( |
| 1201 | - get_test_data_file_path('hello', 'hello'), |
| 1202 | - path) |
| 1203 | - backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) |
| 1204 | - info = backend.get_info(path) |
| 1205 | - deps = ', '.join(guess_dependencies(path)) |
| 1206 | + backend = self.make_backend() |
| 1207 | + info = backend.get_info(self.make_metadata()) |
| 1208 | + deps = ', '.join(guess_dependencies(backend.path)) |
| 1209 | self.assertThat(info, HasField(BuildDepends, deps)) |
| 1210 | |
| 1211 | def test_depends(self): |
| 1212 | - path = self.useFixture(MetadataFixture({PACKAGE_NAME: 'foo'})).path |
| 1213 | - backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) |
| 1214 | - info = backend.get_info(path) |
| 1215 | - self.assertThat(info, HasField(Depends, DEPENDS)) |
| 1216 | + backend = self.make_backend() |
| 1217 | + info = backend.get_info(self.make_metadata()) |
| 1218 | + self.assertThat(info, HasField(Depends, BinaryBackend.DEPENDS)) |
| 1219 | |
| 1220 | def test_extra_files_install_file(self): |
| 1221 | # We create an 'install' file that tells debhelper to just copy |
| 1222 | # everything to opt. |
| 1223 | package_name = self.getUniqueString() |
| 1224 | - path = self.useFixture(MetadataFixture({PACKAGE_NAME: package_name})).path |
| 1225 | - backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) |
| 1226 | - info = backend.get_info(path) |
| 1227 | - extra_files = info.get_all([ExtraFiles.name])[ExtraFiles.name] |
| 1228 | - install_file = json.loads(extra_files)['debian/install'] |
| 1229 | + metadata = self.make_metadata(package_name=package_name) |
| 1230 | + backend = self.make_backend() |
| 1231 | + info = backend.get_info(metadata) |
| 1232 | + install_file = info[ExtraFiles]['debian/install'] |
| 1233 | self.assertEqual( |
| 1234 | - get_install_file(package_name, path, True), |
| 1235 | + get_install_file(package_name, backend.path, True), |
| 1236 | install_file) |
| 1237 | |
| 1238 | def test_extra_files_desktop_file(self): |
| 1239 | @@ -139,20 +136,16 @@ |
| 1240 | package_name = self.getUniqueString() |
| 1241 | tagline = self.getUniqueString() |
| 1242 | categories = self.getUniqueString() |
| 1243 | - metadata = { |
| 1244 | - PACKAGE_NAME: package_name, |
| 1245 | - TAGLINE: tagline, |
| 1246 | - CATEGORIES: categories, |
| 1247 | - } |
| 1248 | - tempdir = self.useFixture(MetadataFixture(metadata)).tempdir |
| 1249 | - # We need to create an executable in order to be able to generate a |
| 1250 | - # desktop. |
| 1251 | - tempdir.touch('executable', 0755) |
| 1252 | - expected_desktop_file = get_binary_desktop_file( |
| 1253 | - package_name, tempdir.path, tagline=tagline, |
| 1254 | + metadata = self.make_metadata( |
| 1255 | + package_name=package_name, |
| 1256 | + tagline=tagline, |
| 1257 | + categories=categories, |
| 1258 | + ) |
| 1259 | + backend = self.make_backend() |
| 1260 | + expected_desktop_file = backend.get_desktop_file( |
| 1261 | + package_name, tagline=tagline, |
| 1262 | categories=categories).get_contents() |
| 1263 | - backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) |
| 1264 | - info = backend.get_info(tempdir.path) |
| 1265 | - extra_files = info.get_all([ExtraFiles.name])[ExtraFiles.name] |
| 1266 | - desktop = json.loads(extra_files)['debian/%s.desktop' % (package_name,)] |
| 1267 | + info = backend.get_info(metadata) |
| 1268 | + extra_files = info[ExtraFiles] |
| 1269 | + desktop = extra_files['debian/%s.desktop' % (package_name,)] |
| 1270 | self.assertEqual(expected_desktop_file, desktop) |
| 1271 | |
| 1272 | === added file 'devportalbinary/tests/test_metadata.py' |
| 1273 | --- devportalbinary/tests/test_metadata.py 1970-01-01 00:00:00 +0000 |
| 1274 | +++ devportalbinary/tests/test_metadata.py 2012-01-10 15:29:28 +0000 |
| 1275 | @@ -0,0 +1,178 @@ |
| 1276 | +# Copyright 2011-2012 Canonical Ltd. This software is licensed under the |
| 1277 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
| 1278 | + |
| 1279 | +import os |
| 1280 | + |
| 1281 | +from pkgme.package_files import DEBIAN_DIR |
| 1282 | +from pkgme.testing import ( |
| 1283 | + AreDesktopValuesFor, |
| 1284 | + TempdirFixture, |
| 1285 | + ) |
| 1286 | +from testtools import TestCase |
| 1287 | + |
| 1288 | +from devportalbinary.metadata import ( |
| 1289 | + get_install_file, |
| 1290 | + get_metadata, |
| 1291 | + MetadataBackend, |
| 1292 | + ) |
| 1293 | +from devportalbinary.testing import ( |
| 1294 | + MetadataFixture, |
| 1295 | + ) |
| 1296 | + |
| 1297 | + |
| 1298 | +class MetadataTests(TestCase): |
| 1299 | + |
| 1300 | + def test_metadata_file(self): |
| 1301 | + self.assertEqual('devportal-metadata.json', MetadataBackend.METADATA_FILE) |
| 1302 | + |
| 1303 | + def test_get_metadata_field_present(self): |
| 1304 | + # get_metadata returns the metadata value of the requested field. |
| 1305 | + metadata = { |
| 1306 | + 'foo': self.getUniqueString(), |
| 1307 | + 'bar': self.getUniqueInteger(), |
| 1308 | + } |
| 1309 | + path = self.useFixture(MetadataFixture(metadata)).metadata_path |
| 1310 | + foo = get_metadata('foo', path=path) |
| 1311 | + self.assertEqual(metadata['foo'], foo) |
| 1312 | + |
| 1313 | + def test_get_metadata_default_file(self): |
| 1314 | + # By default, get_metadata looks for the METADATA_FILE in the current |
| 1315 | + # working directory. |
| 1316 | + metadata = { |
| 1317 | + 'foo': self.getUniqueString(), |
| 1318 | + 'bar': self.getUniqueInteger(), |
| 1319 | + } |
| 1320 | + path = self.useFixture(MetadataFixture(metadata)).path |
| 1321 | + self.addCleanup(os.chdir, os.getcwd()) |
| 1322 | + os.chdir(path) |
| 1323 | + foo = get_metadata('foo') |
| 1324 | + self.assertEqual(metadata['foo'], foo) |
| 1325 | + |
| 1326 | + def test_get_metadata_field_not_present_default_provided(self): |
| 1327 | + # get_metadata returns the provided default value if the field is not |
| 1328 | + # present in the metadata. |
| 1329 | + metadata = {} |
| 1330 | + path = self.useFixture(MetadataFixture(metadata)).metadata_path |
| 1331 | + default = object() |
| 1332 | + foo = get_metadata('foo', default, path=path) |
| 1333 | + self.assertIs(default, foo) |
| 1334 | + |
| 1335 | + def test_get_metadata_field_not_present_no_default(self): |
| 1336 | + # get_metadata raises an exception if the field isn't there and no |
| 1337 | + # default was provided. |
| 1338 | + metadata = {} |
| 1339 | + field = self.getUniqueString() |
| 1340 | + path = self.useFixture(MetadataFixture(metadata)).metadata_path |
| 1341 | + e = self.assertRaises(KeyError, get_metadata, field, path=path) |
| 1342 | + self.assertEqual(repr(field), str(e)) |
| 1343 | + |
| 1344 | + def test_get_metadata_all_fields(self): |
| 1345 | + # get_metadata returns the metadata value of the requested field. |
| 1346 | + metadata = { |
| 1347 | + 'foo': self.getUniqueString(), |
| 1348 | + 'bar': self.getUniqueInteger(), |
| 1349 | + } |
| 1350 | + path = self.useFixture(MetadataFixture(metadata)).metadata_path |
| 1351 | + found_metadata = get_metadata(path=path) |
| 1352 | + self.assertEqual(metadata, found_metadata) |
| 1353 | + |
| 1354 | + |
| 1355 | +class InstallFileTests(TestCase): |
| 1356 | + |
| 1357 | + def test_install_file(self): |
| 1358 | + # The install file instructs debhelper to copy everything in the |
| 1359 | + # top-level to /opt/<package-name>. |
| 1360 | + tempdir = self.useFixture(TempdirFixture()) |
| 1361 | + tempdir.touch('some-file') |
| 1362 | + install_file = get_install_file('package-name', tempdir.path) |
| 1363 | + self.assertEqual("some-file opt/package-name\n", install_file) |
| 1364 | + |
| 1365 | + def test_install_file_many_files_and_directories(self): |
| 1366 | + # The install file instructs debhelper to copy everything in the |
| 1367 | + # top-level to /opt/<package-name>. |
| 1368 | + tempdir = self.useFixture(TempdirFixture()) |
| 1369 | + tempdir.touch('some-file') |
| 1370 | + tempdir.mkdir('directory') |
| 1371 | + install_file = get_install_file('package-name', tempdir.path) |
| 1372 | + self.assertEqual( |
| 1373 | + "directory opt/package-name\n" |
| 1374 | + "some-file opt/package-name\n", |
| 1375 | + install_file) |
| 1376 | + |
| 1377 | + def test_skip_debian(self): |
| 1378 | + # The install file instructs debhelper to copy everything in the |
| 1379 | + # top-level to /opt/<package-name>, except for the 'debian' directory. |
| 1380 | + tempdir = self.useFixture(TempdirFixture()) |
| 1381 | + tempdir.touch('some-file') |
| 1382 | + tempdir.mkdir('directory') |
| 1383 | + tempdir.mkdir(DEBIAN_DIR) |
| 1384 | + install_file = get_install_file('package-name', tempdir.path) |
| 1385 | + self.assertEqual( |
| 1386 | + "directory opt/package-name\n" |
| 1387 | + "some-file opt/package-name\n", |
| 1388 | + install_file) |
| 1389 | + |
| 1390 | + def test_skip_metadata(self): |
| 1391 | + # The install file instructs debhelper to copy everything in the |
| 1392 | + # top-level to /opt/<package-name>, except for the 'debian' directory |
| 1393 | + # and the metadata file. |
| 1394 | + tempdir = self.useFixture(TempdirFixture()) |
| 1395 | + tempdir.touch('some-file') |
| 1396 | + tempdir.mkdir('directory') |
| 1397 | + tempdir.touch(MetadataBackend.METADATA_FILE) |
| 1398 | + install_file = get_install_file('package-name', tempdir.path) |
| 1399 | + self.assertEqual( |
| 1400 | + "directory opt/package-name\n" |
| 1401 | + "some-file opt/package-name\n", |
| 1402 | + install_file) |
| 1403 | + |
| 1404 | + def test_include_desktop_file(self): |
| 1405 | + tempdir = self.useFixture(TempdirFixture()) |
| 1406 | + tempdir.touch('some-file') |
| 1407 | + install_file = get_install_file( |
| 1408 | + 'package-name', tempdir.path, include_desktop=True) |
| 1409 | + self.assertEqual( |
| 1410 | + "some-file opt/package-name\n" |
| 1411 | + "debian/package-name.desktop usr/share/applications\n", |
| 1412 | + install_file) |
| 1413 | + |
| 1414 | + |
| 1415 | +class DesktopFileTests(TestCase): |
| 1416 | + |
| 1417 | + def make_backend(self, executable=None): |
| 1418 | + tempdir = self.useFixture(TempdirFixture()) |
| 1419 | + backend = MetadataBackend(tempdir.path) |
| 1420 | + backend.get_executable = lambda package_name: executable |
| 1421 | + return backend |
| 1422 | + |
| 1423 | + def test_app_name_is_capitalized_package_name(self): |
| 1424 | + # We don't have any information on the package name, so try to guess |
| 1425 | + # the application name. |
| 1426 | + backend = self.make_backend() |
| 1427 | + package_name = self.getUniqueString() |
| 1428 | + desktop_file = backend.get_desktop_file(package_name) |
| 1429 | + self.assertThat( |
| 1430 | + {'Name': package_name.capitalize()}, |
| 1431 | + AreDesktopValuesFor(desktop_file)) |
| 1432 | + |
| 1433 | + def test_category_and_tagline_are_specified(self): |
| 1434 | + # We just pass the category and comment through. |
| 1435 | + package_name = self.getUniqueString() |
| 1436 | + tagline = self.getUniqueString() |
| 1437 | + categories = self.getUniqueString() |
| 1438 | + backend = self.make_backend() |
| 1439 | + desktop_file = backend.get_desktop_file( |
| 1440 | + package_name, tagline=tagline, categories=categories) |
| 1441 | + self.assertThat( |
| 1442 | + {'Comment': tagline, 'Categories': categories}, |
| 1443 | + AreDesktopValuesFor(desktop_file)) |
| 1444 | + |
| 1445 | + def test_executable_from_get_executable(self): |
| 1446 | + # The executable in the desktop file is just whatever get_desktop |
| 1447 | + # returns. |
| 1448 | + package_name = self.getUniqueString() |
| 1449 | + executable = self.getUniqueString() |
| 1450 | + backend = self.make_backend(executable) |
| 1451 | + desktop_file = backend.get_desktop_file(package_name) |
| 1452 | + self.assertThat( |
| 1453 | + {'Exec': executable}, AreDesktopValuesFor(desktop_file)) |
| 1454 | |
| 1455 | === added file 'devportalbinary/tests/test_pdf.py' |
| 1456 | --- devportalbinary/tests/test_pdf.py 1970-01-01 00:00:00 +0000 |
| 1457 | +++ devportalbinary/tests/test_pdf.py 2012-01-10 15:29:28 +0000 |
| 1458 | @@ -0,0 +1,21 @@ |
| 1459 | +# Copyright 2012 Canonical Ltd. This software is licensed under the |
| 1460 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
| 1461 | + |
| 1462 | +from testtools import TestCase |
| 1463 | + |
| 1464 | +from pkgme.testing import TempdirFixture |
| 1465 | + |
| 1466 | +from devportalbinary.pdf import PdfBackend |
| 1467 | + |
| 1468 | + |
| 1469 | +class BackendTests(TestCase): |
| 1470 | + |
| 1471 | + def test_executable_opens_pdf(self): |
| 1472 | + tempdir = self.useFixture(TempdirFixture()) |
| 1473 | + tempdir.touch('foo.pdf') |
| 1474 | + package_name = self.getUniqueString() |
| 1475 | + backend = PdfBackend(tempdir.path) |
| 1476 | + executable = backend.get_executable(package_name) |
| 1477 | + self.assertEqual( |
| 1478 | + '/usr/bin/xdg-open /opt/%s/%s' % (package_name, 'foo.pdf'), |
| 1479 | + executable) |
| 1480 | |
| 1481 | === modified file 'devportalbinary/tests/test_pdf_backend.py' |
| 1482 | --- devportalbinary/tests/test_pdf_backend.py 2011-12-13 04:23:22 +0000 |
| 1483 | +++ devportalbinary/tests/test_pdf_backend.py 2012-01-10 15:29:28 +0000 |
| 1484 | @@ -1,9 +1,6 @@ |
| 1485 | # Copyright 2011 Canonical Ltd. This software is licensed under the |
| 1486 | # GNU Affero General Public License version 3 (see the file LICENSE). |
| 1487 | |
| 1488 | -import json |
| 1489 | - |
| 1490 | -from fixtures import TestWithFixtures |
| 1491 | from testtools import TestCase |
| 1492 | |
| 1493 | from pkgme.backend import ExternalHelpersBackend, get_backend_dir |
| 1494 | @@ -17,14 +14,10 @@ |
| 1495 | ) |
| 1496 | from pkgme.testing import TempdirFixture |
| 1497 | |
| 1498 | -from devportalbinary.binary import ( |
| 1499 | - CATEGORIES, |
| 1500 | - get_install_file, |
| 1501 | - get_pdf_desktop_file, |
| 1502 | - METADATA_FILE, |
| 1503 | - PACKAGE_NAME, |
| 1504 | - TAGLINE, |
| 1505 | -) |
| 1506 | +from devportalbinary.binary import MetadataBackend |
| 1507 | +from devportalbinary.pdf import PdfBackend |
| 1508 | +from devportalbinary.metadata import get_install_file |
| 1509 | +from devportalbinary.testing import MetadataFixture |
| 1510 | |
| 1511 | |
| 1512 | BACKEND_NAME = 'pdf' |
| 1513 | @@ -32,12 +25,21 @@ |
| 1514 | backend_dir = get_backend_dir(__file__, BACKEND_NAME) |
| 1515 | |
| 1516 | |
| 1517 | -class BinaryBackendTests(TestCase, TestWithFixtures): |
| 1518 | +class PdfBackendTests(TestCase): |
| 1519 | + |
| 1520 | + def with_metadata(self, metadata=None): |
| 1521 | + if metadata is None: |
| 1522 | + metadata = {} |
| 1523 | + metadata.setdefault( |
| 1524 | + MetadataBackend.PACKAGE_NAME, self.getUniqueString('package_name')) |
| 1525 | + metadata.setdefault( |
| 1526 | + MetadataBackend.TAGLINE, self.getUniqueString('tagline')) |
| 1527 | + return self.useFixture(MetadataFixture(metadata)) |
| 1528 | |
| 1529 | def test_want_with_metadata(self): |
| 1530 | # If we detect the metadata file and a pdf, then we score 20. |
| 1531 | tempdir = self.useFixture(TempdirFixture()) |
| 1532 | - tempdir.touch(METADATA_FILE) |
| 1533 | + tempdir.touch(MetadataBackend.METADATA_FILE) |
| 1534 | filename = self.getUniqueString() + ".pdf" |
| 1535 | tempdir.touch(filename) |
| 1536 | backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) |
| 1537 | @@ -46,7 +48,7 @@ |
| 1538 | def test_want_with_just_metadata(self): |
| 1539 | # If we detect just the metadata file then we score 0. |
| 1540 | tempdir = self.useFixture(TempdirFixture()) |
| 1541 | - tempdir.touch(METADATA_FILE) |
| 1542 | + tempdir.touch(MetadataBackend.METADATA_FILE) |
| 1543 | backend = ExternalHelpersBackend(BACKEND_NAME, backend_dir) |
| 1544 | self.assertEqual(0, backend.want(tempdir.path)) |
| 1545 | |
| 1546 | @@ -63,7 +65,7 @@ |
| 1547 | # this backend doesn't trigger on something that just happens |
| 1548 | # to contain a pdf. |
| 1549 | tempdir = self.useFixture(TempdirFixture()) |
| 1550 | - tempdir.touch(METADATA_FILE) |
| 1551 | + tempdir.touch(MetadataBackend.METADATA_FILE) |
| 1552 | filename = self.getUniqueString() + ".pdf" |
| 1553 | tempdir.touch(filename) |
| 1554 | other_filename = self.getUniqueString() + ".foo" |
| 1555 | @@ -75,7 +77,7 @@ |
| 1556 | # If the other file is a debian dir then we score 20 still. |
| 1557 | # This just makes local testing of the backend easier. |
| 1558 | tempdir = self.useFixture(TempdirFixture()) |
| 1559 | - tempdir.touch(METADATA_FILE) |
| 1560 | + tempdir.touch(MetadataBackend.METADATA_FILE) |
| 1561 | filename = self.getUniqueString() + ".pdf" |
| 1562 | tempdir.touch(filename) |
| 1563 | other_filename = "debian" |
| 1564 | @@ -85,15 +87,14 @@ |
| 1565 | |
| 1566 | def test_package_name(self): |
| 1567 | # The pdf backend gets the package name from the metadata file. |
| 1568 | - tempdir = self.useFixture(TempdirFixture()) |
| 1569 | - tempdir.create_file(METADATA_FILE, json.dumps({PACKAGE_NAME: 'foo'})) |
| 1570 | - package_name = self.get_info_for(BACKEND_NAME, PackageName, tempdir.path) |
| 1571 | + path = self.with_metadata({MetadataBackend.PACKAGE_NAME: 'foo'}).path |
| 1572 | + package_name = self.get_info_for(BACKEND_NAME, PackageName, path) |
| 1573 | self.assertEqual("foo", package_name) |
| 1574 | |
| 1575 | def test_architecture(self): |
| 1576 | # The pdf backend set architecture to all |
| 1577 | - tempdir = self.useFixture(TempdirFixture()) |
| 1578 | - architecture = self.get_info_for(BACKEND_NAME, Architecture, tempdir.path) |
| 1579 | + path = self.with_metadata().path |
| 1580 | + architecture = self.get_info_for(BACKEND_NAME, Architecture, path) |
| 1581 | self.assertEqual("all", architecture) |
| 1582 | |
| 1583 | def get_info_for(self, backend_name, info_element, path): |
| 1584 | @@ -103,33 +104,32 @@ |
| 1585 | |
| 1586 | def test_build_depends(self): |
| 1587 | # The pdf backend has simple build dependencies |
| 1588 | - tempdir = self.useFixture(TempdirFixture()) |
| 1589 | - build_depends = self.get_info_for(BACKEND_NAME, BuildDepends, tempdir.path) |
| 1590 | + path = self.with_metadata().path |
| 1591 | + build_depends = self.get_info_for(BACKEND_NAME, BuildDepends, path) |
| 1592 | self.assertEqual('debhelper (>=7)', build_depends) |
| 1593 | |
| 1594 | def test_depends(self): |
| 1595 | # The pdf backend depends on xdg-utils |
| 1596 | - tempdir = self.useFixture(TempdirFixture()) |
| 1597 | - depends = self.get_info_for(BACKEND_NAME, Depends, tempdir.path) |
| 1598 | + path = self.with_metadata().path |
| 1599 | + depends = self.get_info_for(BACKEND_NAME, Depends, path) |
| 1600 | self.assertEqual('xdg-utils, ${misc:Depends}', depends) |
| 1601 | |
| 1602 | def test_description(self): |
| 1603 | # The pdf backend gets the description from the metadata file. |
| 1604 | - tempdir = self.useFixture(TempdirFixture()) |
| 1605 | expected_description = 'best pdf evar' |
| 1606 | - tempdir.create_file(METADATA_FILE, json.dumps({TAGLINE: expected_description})) |
| 1607 | - description = self.get_info_for(BACKEND_NAME, Description, tempdir.path) |
| 1608 | + path = self.with_metadata( |
| 1609 | + {MetadataBackend.TAGLINE: expected_description}).path |
| 1610 | + description = self.get_info_for(BACKEND_NAME, Description, path) |
| 1611 | self.assertEqual(expected_description, description) |
| 1612 | |
| 1613 | def test_extra_files_install_file(self): |
| 1614 | # We create an 'install' file that tells debhelper to copy |
| 1615 | # the pdf to opt |
| 1616 | - tempdir = self.useFixture(TempdirFixture()) |
| 1617 | - tempdir.touch('foo.pdf') |
| 1618 | package_name = self.getUniqueString() |
| 1619 | - tempdir.create_file(METADATA_FILE, json.dumps({PACKAGE_NAME: package_name})) |
| 1620 | + tempdir = self.with_metadata( |
| 1621 | + {MetadataBackend.PACKAGE_NAME: package_name}).tempdir |
| 1622 | extra_files = self.get_info_for(BACKEND_NAME, ExtraFiles, tempdir.path) |
| 1623 | - install_file = json.loads(extra_files)['debian/install'] |
| 1624 | + install_file = extra_files['debian/install'] |
| 1625 | self.assertEqual( |
| 1626 | get_install_file(package_name, tempdir.path, True), |
| 1627 | install_file) |
| 1628 | @@ -137,22 +137,21 @@ |
| 1629 | def test_extra_files_desktop_file(self): |
| 1630 | # We create an 'desktop' file that uses xdg-open to open the |
| 1631 | # pdf. |
| 1632 | - tempdir = self.useFixture(TempdirFixture()) |
| 1633 | package_name = self.getUniqueString() |
| 1634 | tagline = self.getUniqueString() |
| 1635 | categories = self.getUniqueString() |
| 1636 | metadata = { |
| 1637 | - PACKAGE_NAME: package_name, |
| 1638 | - TAGLINE: tagline, |
| 1639 | - CATEGORIES: categories, |
| 1640 | + MetadataBackend.PACKAGE_NAME: package_name, |
| 1641 | + MetadataBackend.TAGLINE: tagline, |
| 1642 | + MetadataBackend.CATEGORIES: categories, |
| 1643 | } |
| 1644 | - tempdir.create_file(METADATA_FILE, json.dumps(metadata)) |
| 1645 | + tempdir = self.with_metadata(metadata).tempdir |
| 1646 | # We need to create a pdf file in order to be able to generate a |
| 1647 | # desktop. |
| 1648 | tempdir.touch('foo.pdf') |
| 1649 | - expected_desktop_file = get_pdf_desktop_file( |
| 1650 | - package_name, tempdir.path, tagline=tagline, |
| 1651 | + expected_desktop_file = PdfBackend(tempdir.path).get_desktop_file( |
| 1652 | + package_name, tagline=tagline, |
| 1653 | categories=categories).get_contents() |
| 1654 | extra_files = self.get_info_for(BACKEND_NAME, ExtraFiles, tempdir.path) |
| 1655 | - desktop = json.loads(extra_files)['debian/%s.desktop' % (package_name,)] |
| 1656 | + desktop = extra_files['debian/%s.desktop' % (package_name,)] |
| 1657 | self.assertEqual(expected_desktop_file, desktop) |

522 + # XXX: Technically this should be an error, but our tests exercise
523 + # this code in directories that have no binaries. Silly them.
Is this some of the tests that you are adding that are doing this?
I think that the dump_json implementation doesn't actually follow the spec,
which says it should return the values for the keys passed in, but I'm not
sure that matters, as it will only be called in the way that it would
return the data as it does now unless pkgme changes, and I don't think pkgme
cares if it gets extra info anyway.
Thanks,
James