Merge lp:~zyga/checkbox/fix-1476678 into lp:checkbox

Proposed by Zygmunt Krynicki
Status: Merged
Approved by: Sylvain Pineau
Approved revision: 3912
Merged at revision: 3912
Proposed branch: lp:~zyga/checkbox/fix-1476678
Merge into: lp:checkbox
Diff against target: 264 lines (+146/-20)
2 files modified
plainbox/plainbox/impl/unit/packaging.py (+92/-20)
plainbox/plainbox/impl/unit/test_packging.py (+54/-0)
To merge this branch: bzr merge lp:~zyga/checkbox/fix-1476678
Reviewer Review Type Date Requested Status
Sylvain Pineau (community) Approve
Review via email: mp+265506@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

This is almost, but not quite. I need to see what's missing :-|

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

Currently this crashes for me like this:

python3 manage.py packaging
CRITICAL plainbox.crashes: Executable 'manage.py' invoked with Namespace(command=<plainbox.provider_manager.PackagingCommand object at 0x7fa10e173518>, debug_console=False, debug_interrupt=False, log_level=None, pdb=False, trace=[]) has crashed
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/plainbox/impl/clitools.py", line 560, in dispatch_and_catch_exceptions
    return self.dispatch_command(ns)
  File "/usr/lib/python3/dist-packages/plainbox/impl/clitools.py", line 556, in dispatch_command
    return ns.command.invoked(ns)
  File "/usr/lib/python3/dist-packages/plainbox/provider_manager.py", line 1295, in invoked
    driver.inspect_provider(provider)
  File "/usr/lib/python3/dist-packages/plainbox/impl/unit/packaging.py", line 260, in inspect_provider
    if self.is_applicable(unit):
  File "/usr/lib/python3/dist-packages/plainbox/impl/unit/packaging.py", line 250, in is_applicable
    if (not _strategy_id_version(unit, os_release)
  File "/usr/lib/python3/dist-packages/plainbox/impl/unit/packaging.py", line 224, in _strategy_id_version
    and unit.os_version_id == os_release['VERSION_ID'])
KeyError: 'VERSION_ID'

I think it's because 'sid' doesn't have VERSION_ID field. I'll patch the code to fix that.

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

Yes, this is from sid:

cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux stretch/sid"
NAME="Debian GNU/Linux"
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support/"
BUG_REPORT_URL="https://bugs.debian.org/"

Sigh :-) I'll report this as a separate bug. Let's land this

Revision history for this message
Zygmunt Krynicki (zyga) wrote :
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

I'll do some more testing and review this myself. Separate review is welcome but if you don't want to test this all the way I can do that.

lp:~zyga/checkbox/fix-1476678 updated
3909. By Sylvain Pineau

"Release_2015_Week30 [r=sylvain-pineau][bug=1331302,1341769,1347120,1382321,1383447,1387782,1387843,1388055,1388747,1389253,1399481,1400646,1403933,1406719,1410501,1428615,1451343,1451541][author=checkbox-dev]"

3910. By Zygmunt Krynicki

"automatic merge of lp:~zyga/checkbox/fix-1477131/ by tarmac [r=sylvain-pineau][bug=1477131][author=zyga]"

3911. By Zygmunt Krynicki

plainbox:unit:packaging: improve documentation

Signed-off-by: Zygmunt Krynicki <email address hidden>

3912. By Zygmunt Krynicki

plainbox:unit:packaging: fix parsing of Debian meta-data

This patch fixes how multiple-entry packaging meta-data units are parsed.
The fix makes the example in the documentation behave as intended.

Fixes: https://bugs.launchpad.net/plainbox/+bug/1476678
Signed-off-by: Zygmunt Krynicki <email address hidden>

Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

+1, thanks for the fix

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'plainbox/plainbox/impl/unit/packaging.py'
--- plainbox/plainbox/impl/unit/packaging.py 2015-07-22 12:57:27 +0000
+++ plainbox/plainbox/impl/unit/packaging.py 2015-07-22 13:45:52 +0000
@@ -114,6 +114,7 @@
114import abc114import abc
115import errno115import errno
116import logging116import logging
117import re
117import sys118import sys
118119
119from plainbox.i18n import gettext as _120from plainbox.i18n import gettext as _
@@ -142,12 +143,12 @@
142143
143 @property144 @property
144 def os_id(self):145 def os_id(self):
145 """ Identifier of the operating system. """146 """Identifier of the operating system."""
146 return self.get_record_value(self.Meta.fields.os_id)147 return self.get_record_value(self.Meta.fields.os_id)
147148
148 @property149 @property
149 def os_version_id(self):150 def os_version_id(self):
150 """ Version of the operating system. """151 """Version of the operating system."""
151 return self.get_record_value(self.Meta.fields.os_version_id)152 return self.get_record_value(self.Meta.fields.os_version_id)
152153
153 class Meta:154 class Meta:
@@ -156,7 +157,7 @@
156157
157 class fields(SymbolDef):158 class fields(SymbolDef):
158159
159 """ Symbols for each field of a packaging meta-data unit. """160 """Symbols for each field of a packaging meta-data unit."""
160161
161 os_id = 'os-id'162 os_id = 'os-id'
162 os_version_id = 'os-version-id'163 os_version_id = 'os-version-id'
@@ -174,46 +175,108 @@
174175
175class PackagingDriverError(Exception):176class PackagingDriverError(Exception):
176177
177 """ Base for all packaging driver exceptions. """178 """Base for all packaging driver exceptions."""
178179
179180
180class NoPackagingDetected(PackagingDriverError):181class NoPackagingDetected(PackagingDriverError):
181182
182 """ Exception raised when packaging cannot be found. """183 """Exception raised when packaging cannot be found."""
183184
184185
185class NoApplicableBinaryPackages(PackagingDriverError):186class NoApplicableBinaryPackages(PackagingDriverError):
186187
187 """ Exception raised when no applicable binary packages are found. """188 """Exception raised when no applicable binary packages are found."""
188189
189190
190class IPackagingDriver(metaclass=abc.ABCMeta):191class IPackagingDriver(metaclass=abc.ABCMeta):
191192
192 """ Interface for all packaging drivers. """193 """Interface for all packaging drivers."""
193194
194 @abc.abstractmethod195 @abc.abstractmethod
195 def __init__(self, os_release: 'Dict[str, str]'):196 def __init__(self, os_release: 'Dict[str, str]'):
196 pass197 """
198 Initialize the packaging driver.
199
200 :param os_release:
201 The dictionary that represents the contents of the
202 ``/etc/os-release`` file. Using this file the packaging driver can
203 infer information about the target operating system that the
204 packaging will be built for.
205
206 This assumes that packages are built natively, not through a
207 cross-compiler of some sort where the target distribution is
208 different from the host distribution.
209 """
197210
198 @abc.abstractmethod211 @abc.abstractmethod
199 def inspect_provider(self, provider: 'Provider1') -> None:212 def inspect_provider(self, provider: 'Provider1') -> None:
200 pass213 """
214 Inspect a provider looking for packaging meta-data.
215
216 :param provider:
217 A provider object to look at. All of the packaging meta-data units
218 there are inspected, if they are applicable (see
219 :meth:`is_applicable()`. Information from applicable units is
220 collected using the :meth:`collect()` method.
221 """
201222
202 @abc.abstractmethod223 @abc.abstractmethod
203 def is_applicable(self, unit: Unit) -> bool:224 def is_applicable(self, unit: Unit) -> bool:
204 pass225 """
226 Check if the given unit is applicable for collecting.
227
228 :param unit:
229 The unit to inspect. This doesn't have to be a packaging meta-data
230 unit. In fact, all units are checked with this method.
231 :returns:
232 True if the unit is applicable for collection.
233
234 Packaging meta-data units that have certain properties are applicable.
235 Refer to the documentation of the module for details.
236 """
205237
206 @abc.abstractmethod238 @abc.abstractmethod
207 def collect(self, unit: Unit) -> None:239 def collect(self, unit: Unit) -> None:
208 pass240 """
241 Collect information from the given applicable unit.
242
243 :param unit:
244 The unit to collect information from. This is usually expressed as
245 additional fields that are specific to the type of native packaging
246 for the system.
247
248 Collected information is recorded and made available for the
249 :meth:`modify_packaging_tree()` method later.
250 """
209251
210 @abc.abstractmethod252 @abc.abstractmethod
211 def inspect_packaging(self) -> None:253 def inspect_packaging(self) -> None:
212 pass254 """
255 Inspect the packaging tree for additional information.
256
257 :raises NoPackagingDetected:
258 Exception raised when packaging cannot be found.
259 :raises NoApplicableBinaryPackages:
260 Exception raised when no applicable binary packages are found.
261
262 This method looks at the packaging system located in the current
263 directory. This can be the ``debian/`` directory, a particular
264 ``.spec`` file or anything else. Information obtained from the package
265 is used to infer additional properties that can aid in the packaging
266 process.
267 """
213268
214 @abc.abstractmethod269 @abc.abstractmethod
215 def modify_packaging_tree(self) -> None:270 def modify_packaging_tree(self) -> None:
216 pass271 """
272 Modify the packaging tree with information from the packaging units.
273
274 This method uses all of the available information collected from
275 particular packaging meta-data units and from the native packaging to
276 modify the packaging. Additional dependencies may be injected in
277 appropriate places. Please refer to the documentation specific to your
278 packaging system for details.
279 """
217280
218281
219def _strategy_id_version(unit, os_release):282def _strategy_id_version(unit, os_release):
@@ -237,7 +300,7 @@
237300
238class PackagingDriverBase(IPackagingDriver):301class PackagingDriverBase(IPackagingDriver):
239302
240 """ Base implementation of a packaging driver. """303 """Base implementation of a packaging driver."""
241304
242 def __init__(self, os_release: 'Dict[str, str]'):305 def __init__(self, os_release: 'Dict[str, str]'):
243 self.os_release = os_release306 self.os_release = os_release
@@ -262,7 +325,12 @@
262325
263class NullPackagingDriver(PackagingDriverBase):326class NullPackagingDriver(PackagingDriverBase):
264327
265 """ Null implementation of a packaging driver. """328 """
329 Null implementation of a packaging driver.
330
331 This driver just does nothing at all. It is used as a fall-back when
332 nothing better is detected.
333 """
266334
267 def is_applicable(self, unit: Unit) -> bool:335 def is_applicable(self, unit: Unit) -> bool:
268 return False336 return False
@@ -316,10 +384,14 @@
316 def collect(self, unit: Unit) -> None:384 def collect(self, unit: Unit) -> None:
317 def rel_list(field):385 def rel_list(field):
318 relations = unit.get_record_value(field, '').replace('\n', ' ')386 relations = unit.get_record_value(field, '').replace('\n', ' ')
319 return ', '.join([rel.strip() for rel in relations.split(',')])387 return (
320 self._depends.append(rel_list('Depends'))388 rel.strip()
321 self._suggests.append(rel_list('Suggests'))389 for rel in re.split(', *', relations)
322 self._recommends.append(rel_list('Recommends'))390 if rel.strip()
391 )
392 self._depends.extend(rel_list('Depends'))
393 self._suggests.extend(rel_list('Suggests'))
394 self._recommends.extend(rel_list('Recommends'))
323395
324 def _write_pkg_substvars(self, pkg):396 def _write_pkg_substvars(self, pkg):
325 fname = 'debian/{}.substvars'.format(pkg)397 fname = 'debian/{}.substvars'.format(pkg)
@@ -357,7 +429,7 @@
357429
358430
359def get_packaging_driver() -> IPackagingDriver:431def get_packaging_driver() -> IPackagingDriver:
360 """ Get the packaging driver appropriate for the current platform. """432 """Get the packaging driver appropriate for the current platform."""
361 if sys.platform.startswith("linux"):433 if sys.platform.startswith("linux"):
362 os_release = get_os_release()434 os_release = get_os_release()
363 if (os_release.get('ID') == 'debian'435 if (os_release.get('ID') == 'debian'
364436
=== added file 'plainbox/plainbox/impl/unit/test_packging.py'
--- plainbox/plainbox/impl/unit/test_packging.py 1970-01-01 00:00:00 +0000
+++ plainbox/plainbox/impl/unit/test_packging.py 2015-07-22 13:45:52 +0000
@@ -0,0 +1,54 @@
1# This file is part of Checkbox.
2#
3# Copyright 2015 Canonical Ltd.
4# Written by:
5# Zygmunt Krynicki <zygmunt.krynicki@canonical.com>
6#
7# Checkbox is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 3,
9# as published by the Free Software Foundation.
10#
11# Checkbox is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
18
19"""Tests for the PackagingMetaDataUnit and friends."""
20
21from unittest import TestCase
22
23from plainbox.impl.unit.packaging import DebianPackagingDriver
24from plainbox.impl.unit.packaging import PackagingMetaDataUnit
25
26
27class DebianPackagingDriverTests(TestCase):
28
29 """Tests for the DebianPackagingDriver class."""
30
31 def test_fix_1476678(self):
32 """Check https://bugs.launchpad.net/plainbox/+bug/1476678."""
33 driver = DebianPackagingDriver({})
34 driver.collect(PackagingMetaDataUnit({
35 'Depends': (
36 'python3-checkbox-support (>= 0.2),\n'
37 'python3 (>= 3.2),\n'),
38 'Recommends': (
39 'dmidecode,\n'
40 'dpkg (>= 1.13),\n'
41 'lsb-release,\n'
42 'wodim')
43 }))
44 self.assertEqual(driver._depends, [
45 'python3-checkbox-support (>= 0.2)',
46 'python3 (>= 3.2)',
47 ])
48 self.assertEqual(driver._recommends, [
49 'dmidecode',
50 'dpkg (>= 1.13)',
51 'lsb-release',
52 'wodim'
53 ])
54 self.assertEqual(driver._suggests, [])

Subscribers

People subscribed via source and target branches