Example #1
0
 def test_relationship_evaluation(self):
     # Relationships without versions.
     relationship_set = parse_depends('python')
     self.assertTrue(relationship_set.matches('python'))
     self.assertFalse(relationship_set.matches('python2.7'))
     self.assertEqual(list(relationship_set.names), ['python'])
     # Alternatives (OR) without versions.
     relationship_set = parse_depends('python2.6 | python2.7')
     self.assertFalse(relationship_set.matches('python2.5'))
     self.assertTrue(relationship_set.matches('python2.6'))
     self.assertTrue(relationship_set.matches('python2.7'))
     self.assertFalse(relationship_set.matches('python3.0'))
     self.assertEqual(sorted(relationship_set.names), ['python2.6', 'python2.7'])
     # Combinations (AND) with versions.
     relationship_set = parse_depends('python (>= 2.6), python (<< 3) | python (>= 3.4)')
     self.assertFalse(relationship_set.matches('python', '2.5'))
     self.assertTrue(relationship_set.matches('python', '2.6'))
     self.assertTrue(relationship_set.matches('python', '2.7'))
     self.assertFalse(relationship_set.matches('python', '3.0'))
     self.assertTrue(relationship_set.matches('python', '3.4'))
     self.assertEqual(list(relationship_set.names), ['python'])
     # Testing for matches without providing a version is valid (should not
     # raise an error) but will never match a relationship with a version.
     relationship_set = parse_depends('python (>= 2.6), python (<< 3)')
     self.assertTrue(relationship_set.matches('python', '2.7'))
     self.assertFalse(relationship_set.matches('python'))
     self.assertEqual(list(relationship_set.names), ['python'])
     # Distinguishing between packages whose name was matched but whose
     # version didn't match vs packages whose name wasn't matched.
     relationship_set = parse_depends('python (>= 2.6), python (<< 3) | python (>= 3.4)')
     self.assertEqual(relationship_set.matches('python', '2.7'), True) # name and version match
     self.assertEqual(relationship_set.matches('python', '2.5'), False) # name matched, version didn't
     self.assertEqual(relationship_set.matches('python2.6'), None) # name didn't match
     self.assertEqual(relationship_set.matches('python', '3.0'), False) # name in alternative matched, version didn't
     self.assertEqual(list(relationship_set.names), ['python'])
Example #2
0
 def test_relationship_parsing(self):
     # Happy path (no parsing errors).
     relationship_set = parse_depends('foo, bar (>= 1) | baz')
     self.assertEqual(relationship_set.relationships[0].name, 'foo')
     self.assertEqual(relationship_set.relationships[1].relationships[0].name, 'bar')
     self.assertEqual(relationship_set.relationships[1].relationships[0].operator, '>=')
     self.assertEqual(relationship_set.relationships[1].relationships[0].version, '1')
     self.assertEqual(relationship_set.relationships[1].relationships[1].name, 'baz')
     self.assertEqual(parse_depends('foo (=1.0)'), RelationshipSet(VersionedRelationship(name='foo', operator='=', version='1.0')))
     # Unhappy path (parsing errors).
     self.assertRaises(ValueError, parse_depends, 'foo (bar) (baz)')
     self.assertRaises(ValueError, parse_depends, 'foo (bar baz qux)')
Example #3
0
 def test_architecture_restriction_parsing(self):
     """Test the parsing of architecture restrictions."""
     relationship_set = parse_depends('qux [i386 amd64]')
     assert relationship_set.relationships[0].name == 'qux'
     assert len(relationship_set.relationships[0].architectures) == 2
     assert 'i386' in relationship_set.relationships[0].architectures
     assert 'amd64' in relationship_set.relationships[0].architectures
Example #4
0
 def test_custom_pretty_printer(self):
     """Test pretty printing of deb822 objects and parsed relationships."""
     printer = CustomPrettyPrinter()
     # Test pretty printing of debian.deb822.Deb822 objects.
     deb822_object = deb822_from_string('''
         Package: pretty-printed-control-fields
         Version: 1.0
         Architecture: all
     ''')
     formatted_object = printer.pformat(deb822_object)
     assert normalize_repr_output(
         formatted_object) == normalize_repr_output('''
         {'Architecture': u'all',
          'Package': u'pretty-printed-control-fields',
          'Version': u'1.0'}
     ''')
     # Test pretty printing of RelationshipSet objects.
     relationship_set = parse_depends(
         'python-deb-pkg-tools, python-pip, python-pip-accel')
     formatted_object = printer.pformat(relationship_set)
     assert normalize_repr_output(
         formatted_object) == normalize_repr_output('''
         RelationshipSet(Relationship(name='python-deb-pkg-tools', architectures=()),
                         Relationship(name='python-pip', architectures=()),
                         Relationship(name='python-pip-accel', architectures=()))
     ''')
Example #5
0
 def test_architecture_restriction_parsing(self):
     """Test the parsing of architecture restrictions."""
     relationship_set = parse_depends('qux [i386 amd64]')
     assert relationship_set.relationships[0].name == 'qux'
     assert len(relationship_set.relationships[0].architectures) == 2
     assert 'i386' in relationship_set.relationships[0].architectures
     assert 'amd64' in relationship_set.relationships[0].architectures
Example #6
0
 def test_relationship_unparsing(self):
     relationship_set = parse_depends('foo, bar(>=1)|baz')
     self.assertEqual(unicode(relationship_set), 'foo, bar (>= 1) | baz')
     self.assertEqual(
         compact(repr(relationship_set)),
         "RelationshipSet(Relationship(name='foo'), AlternativeRelationship(VersionedRelationship(name='bar', operator='>=', version='1'), Relationship(name='baz')))"
     )
Example #7
0
 def test_custom_pretty_printer(self):
     printer = CustomPrettyPrinter()
     # Test pretty printing of debian.deb822.Deb822 objects.
     self.assertEqual(
         remove_unicode_prefixes(
             printer.pformat(
                 deb822_from_string('''
         Package: pretty-printed-control-fields
         Version: 1.0
         Architecture: all
     '''))),
         remove_unicode_prefixes(
             dedent('''
         {'Architecture': u'all',
          'Package': u'pretty-printed-control-fields',
          'Version': u'1.0'}
     ''')))
     # Test pretty printing of RelationshipSet objects.
     depends_line = 'python-deb-pkg-tools, python-pip, python-pip-accel'
     self.assertEqual(
         printer.pformat(parse_depends(depends_line)),
         dedent('''
         RelationshipSet(Relationship(name='python-deb-pkg-tools'),
                         Relationship(name='python-pip'),
                         Relationship(name='python-pip-accel'))
     '''))
Example #8
0
 def test_relationship_parsing(self):
     """Test the parsing of Debian package relationship declarations."""
     # Happy path (no parsing errors).
     relationship_set = parse_depends('foo, bar (>= 1) | baz')
     assert relationship_set.relationships[0].name == 'foo'
     assert relationship_set.relationships[1].relationships[0].name == 'bar'
     assert relationship_set.relationships[1].relationships[0].operator == '>='
     assert relationship_set.relationships[1].relationships[0].version == '1'
     assert relationship_set.relationships[1].relationships[1].name == 'baz'
     assert parse_depends('foo (=1.0)') == RelationshipSet(VersionedRelationship(
         name='foo',
         operator='=',
         version='1.0',
     ))
     # Unhappy path (parsing errors).
     self.assertRaises(ValueError, parse_depends, 'foo (bar) (baz)')
     self.assertRaises(ValueError, parse_depends, 'foo (bar baz qux)')
Example #9
0
 def test_relationship_parsing(self):
     """Test the parsing of Debian package relationship declarations."""
     # Happy path (no parsing errors).
     relationship_set = parse_depends('foo, bar (>= 1) | baz')
     assert relationship_set.relationships[0].name == 'foo'
     assert relationship_set.relationships[1].relationships[0].name == 'bar'
     assert relationship_set.relationships[1].relationships[0].operator == '>='
     assert relationship_set.relationships[1].relationships[0].version == '1'
     assert relationship_set.relationships[1].relationships[1].name == 'baz'
     assert parse_depends('foo (=1.0)') == RelationshipSet(VersionedRelationship(
         name='foo',
         operator='=',
         version='1.0',
     ))
     # Unhappy path (parsing errors).
     self.assertRaises(ValueError, parse_depends, 'foo (bar) (baz)')
     self.assertRaises(ValueError, parse_depends, 'foo (bar baz qux)')
Example #10
0
 def test_relationship_evaluation(self):
     """Test the evaluation of package relationships."""
     # Relationships without versions.
     relationship_set = parse_depends('python')
     assert relationship_set.matches('python')
     assert not relationship_set.matches('python2.7')
     assert list(relationship_set.names) == ['python']
     # Alternatives (OR) without versions.
     relationship_set = parse_depends('python2.6 | python2.7')
     assert not relationship_set.matches('python2.5')
     assert relationship_set.matches('python2.6')
     assert relationship_set.matches('python2.7')
     assert not relationship_set.matches('python3.0')
     assert sorted(relationship_set.names) == ['python2.6', 'python2.7']
     # Combinations (AND) with versions.
     relationship_set = parse_depends(
         'python (>= 2.6), python (<< 3) | python (>= 3.4)')
     assert not relationship_set.matches('python', '2.5')
     assert relationship_set.matches('python', '2.6')
     assert relationship_set.matches('python', '2.7')
     assert not relationship_set.matches('python', '3.0')
     assert relationship_set.matches('python', '3.4')
     assert list(relationship_set.names) == ['python']
     # Testing for matches without providing a version is valid (should not
     # raise an error) but will never match a relationship with a version.
     relationship_set = parse_depends('python (>= 2.6), python (<< 3)')
     assert relationship_set.matches('python', '2.7')
     assert not relationship_set.matches('python')
     assert list(relationship_set.names) == ['python']
     # Distinguishing between packages whose name was matched but whose
     # version didn't match vs packages whose name wasn't matched.
     relationship_set = parse_depends(
         'python (>= 2.6), python (<< 3) | python (>= 3.4)')
     assert relationship_set.matches(
         'python', '2.7') is True  # name and version match
     assert relationship_set.matches(
         'python', '2.5') is False  # name matched, version didn't
     assert relationship_set.matches(
         'python2.6') is None  # name didn't match
     assert relationship_set.matches(
         'python',
         '3.0') is False  # name in alternative matched, version didn't
     assert list(relationship_set.names) == ['python']
Example #11
0
 def test_relationship_evaluation(self):
     # Relationships without versions.
     relationship_set = parse_depends('python')
     self.assertTrue(relationship_set.matches('python'))
     self.assertFalse(relationship_set.matches('python2.7'))
     self.assertEqual(list(relationship_set.names), ['python'])
     # Alternatives (OR) without versions.
     relationship_set = parse_depends('python2.6 | python2.7')
     self.assertFalse(relationship_set.matches('python2.5'))
     self.assertTrue(relationship_set.matches('python2.6'))
     self.assertTrue(relationship_set.matches('python2.7'))
     self.assertFalse(relationship_set.matches('python3.0'))
     self.assertEqual(sorted(relationship_set.names),
                      ['python2.6', 'python2.7'])
     # Combinations (AND) with versions.
     relationship_set = parse_depends(
         'python (>= 2.6), python (<< 3) | python (>= 3.4)')
     self.assertFalse(relationship_set.matches('python', '2.5'))
     self.assertTrue(relationship_set.matches('python', '2.6'))
     self.assertTrue(relationship_set.matches('python', '2.7'))
     self.assertFalse(relationship_set.matches('python', '3.0'))
     self.assertTrue(relationship_set.matches('python', '3.4'))
     self.assertEqual(list(relationship_set.names), ['python'])
     # Testing for matches without providing a version is valid (should not
     # raise an error) but will never match a relationship with a version.
     relationship_set = parse_depends('python (>= 2.6), python (<< 3)')
     self.assertTrue(relationship_set.matches('python', '2.7'))
     self.assertFalse(relationship_set.matches('python'))
     self.assertEqual(list(relationship_set.names), ['python'])
     # Distinguishing between packages whose name was matched but whose
     # version didn't match vs packages whose name wasn't matched.
     relationship_set = parse_depends(
         'python (>= 2.6), python (<< 3) | python (>= 3.4)')
     self.assertEqual(relationship_set.matches('python', '2.7'),
                      True)  # name and version match
     self.assertEqual(relationship_set.matches('python', '2.5'),
                      False)  # name matched, version didn't
     self.assertEqual(relationship_set.matches('python2.6'),
                      None)  # name didn't match
     self.assertEqual(relationship_set.matches('python', '3.0'),
                      False)  # name in alternative matched, version didn't
     self.assertEqual(list(relationship_set.names), ['python'])
Example #12
0
 def test_relationship_parsing(self):
     # Happy path (no parsing errors).
     relationship_set = parse_depends('foo, bar (>= 1) | baz')
     self.assertEqual(relationship_set.relationships[0].name, 'foo')
     self.assertEqual(
         relationship_set.relationships[1].relationships[0].name, 'bar')
     self.assertEqual(
         relationship_set.relationships[1].relationships[0].operator, '>=')
     self.assertEqual(
         relationship_set.relationships[1].relationships[0].version, '1')
     self.assertEqual(
         relationship_set.relationships[1].relationships[1].name, 'baz')
     self.assertEqual(
         parse_depends('foo (=1.0)'),
         RelationshipSet(
             VersionedRelationship(name='foo', operator='=',
                                   version='1.0')))
     # Unhappy path (parsing errors).
     self.assertRaises(ValueError, parse_depends, 'foo (bar) (baz)')
     self.assertRaises(ValueError, parse_depends, 'foo (bar baz qux)')
Example #13
0
 def test_relationship_unparsing(self):
     """Test the unparsing (serialization) of parsed relationship declarations."""
     def strip(text):
         return re.sub(r'\s+', '', text)
     relationship_set = parse_depends('foo, bar(>=1)|baz[i386]')
     assert text_type(relationship_set) == 'foo, bar (>= 1) | baz [i386]'
     assert strip(repr(relationship_set)) == strip("""
         RelationshipSet(
             Relationship(name='foo', architectures=()),
             AlternativeRelationship(
                 VersionedRelationship(name='bar', operator='>=', version='1', architectures=()),
                 Relationship(name='baz', architectures=('i386',))
             )
         )
     """)
Example #14
0
 def test_relationship_evaluation(self):
     """Test the evaluation of package relationships."""
     # Relationships without versions.
     relationship_set = parse_depends('python')
     assert relationship_set.matches('python')
     assert not relationship_set.matches('python2.7')
     assert list(relationship_set.names) == ['python']
     # Alternatives (OR) without versions.
     relationship_set = parse_depends('python2.6 | python2.7')
     assert not relationship_set.matches('python2.5')
     assert relationship_set.matches('python2.6')
     assert relationship_set.matches('python2.7')
     assert not relationship_set.matches('python3.0')
     assert sorted(relationship_set.names) == ['python2.6', 'python2.7']
     # Combinations (AND) with versions.
     relationship_set = parse_depends('python (>= 2.6), python (<< 3) | python (>= 3.4)')
     assert not relationship_set.matches('python', '2.5')
     assert relationship_set.matches('python', '2.6')
     assert relationship_set.matches('python', '2.7')
     assert not relationship_set.matches('python', '3.0')
     assert relationship_set.matches('python', '3.4')
     assert list(relationship_set.names) == ['python']
     # Testing for matches without providing a version is valid (should not
     # raise an error) but will never match a relationship with a version.
     relationship_set = parse_depends('python (>= 2.6), python (<< 3)')
     assert relationship_set.matches('python', '2.7')
     assert not relationship_set.matches('python')
     assert list(relationship_set.names) == ['python']
     # Distinguishing between packages whose name was matched but whose
     # version didn't match vs packages whose name wasn't matched.
     relationship_set = parse_depends('python (>= 2.6), python (<< 3) | python (>= 3.4)')
     assert relationship_set.matches('python', '2.7') is True  # name and version match
     assert relationship_set.matches('python', '2.5') is False  # name matched, version didn't
     assert relationship_set.matches('python2.6') is None  # name didn't match
     assert relationship_set.matches('python', '3.0') is False  # name in alternative matched, version didn't
     assert list(relationship_set.names) == ['python']
Example #15
0
 def test_relationship_unparsing(self):
     """Test the unparsing (serialization) of parsed relationship declarations."""
     def strip(text):
         return re.sub(r'\s+', '', text)
     relationship_set = parse_depends('foo, bar(>=1)|baz[i386]')
     assert text_type(relationship_set) == 'foo, bar (>= 1) | baz [i386]'
     assert strip(repr(relationship_set)) == strip("""
         RelationshipSet(
             Relationship(name='foo', architectures=()),
             AlternativeRelationship(
                 VersionedRelationship(name='bar', operator='>=', version='1', architectures=()),
                 Relationship(name='baz', architectures=('i386',))
             )
         )
     """)
Example #16
0
 def test_custom_pretty_printer(self):
     printer = CustomPrettyPrinter()
     # Test pretty printing of debian.deb822.Deb822 objects.
     self.assertEqual(remove_unicode_prefixes(printer.pformat(deb822_from_string('''
         Package: pretty-printed-control-fields
         Version: 1.0
         Architecture: all
     '''))), remove_unicode_prefixes(dedent('''
         {'Architecture': u'all',
          'Package': u'pretty-printed-control-fields',
          'Version': u'1.0'}
     ''')))
     # Test pretty printing of RelationshipSet objects.
     depends_line = 'python-deb-pkg-tools, python-pip, python-pip-accel'
     self.assertEqual(printer.pformat(parse_depends(depends_line)), dedent('''
         RelationshipSet(Relationship(name='python-deb-pkg-tools'),
                         Relationship(name='python-pip'),
                         Relationship(name='python-pip-accel'))
     '''))
Example #17
0
 def test_custom_pretty_printer(self):
     """Test pretty printing of deb822 objects and parsed relationships."""
     printer = CustomPrettyPrinter()
     # Test pretty printing of debian.deb822.Deb822 objects.
     deb822_object = deb822_from_string('''
         Package: pretty-printed-control-fields
         Version: 1.0
         Architecture: all
     ''')
     formatted_object = printer.pformat(deb822_object)
     assert normalize_repr_output(formatted_object) == normalize_repr_output('''
         {'Architecture': u'all',
          'Package': u'pretty-printed-control-fields',
          'Version': u'1.0'}
     ''')
     # Test pretty printing of RelationshipSet objects.
     relationship_set = parse_depends('python-deb-pkg-tools, python-pip, python-pip-accel')
     formatted_object = printer.pformat(relationship_set)
     assert normalize_repr_output(formatted_object) == normalize_repr_output('''
         RelationshipSet(Relationship(name='python-deb-pkg-tools', architectures=()),
                         Relationship(name='python-pip', architectures=()),
                         Relationship(name='python-pip-accel', architectures=()))
     ''')
Example #18
0
 def test_relationship_sorting(self):
     relationship_set = parse_depends('foo | bar, baz | qux')
     self.assertEqual(relationship_set, RelationshipSet(
         AlternativeRelationship(Relationship(name='baz'), Relationship(name='qux')),
         AlternativeRelationship(Relationship(name='foo'), Relationship(name='bar'))))
Example #19
0
 def test_relationship_unparsing(self):
     relationship_set = parse_depends('foo, bar(>=1)|baz')
     self.assertEqual(unicode(relationship_set), 'foo, bar (>= 1) | baz')
     self.assertEqual(compact(repr(relationship_set)), "RelationshipSet(Relationship(name='foo'), AlternativeRelationship(VersionedRelationship(name='bar', operator='>=', version='1'), Relationship(name='baz')))")
Example #20
0
def parse_control_fields(input_fields):
    r"""
    Parse Debian control file fields.

    :param input_fields: The dictionary to convert (may be an instance of
                         :class:`debian.deb822.Deb822` but doesn't have
                         to be).
    :returns: A :class:`dict` object with the converted fields.

    The :class:`debian.deb822.Deb822` class can be used to parse Debian control
    files but the result is a simple :class:`dict` with string name/value
    pairs. This function takes an existing :class:`debian.deb822.Deb822`
    instance and converts the following fields into friendlier formats:

    - The values of the fields given by :data:`DEPENDS_LIKE_FIELDS` are parsed
      into Python data structures using :func:`.parse_depends()`.

    - The value of the `Installed-Size` field is converted to an integer.

    Let's look at an example. We start with the raw control file contents so
    you can see the complete input:

    >>> from deb_pkg_tools.control import deb822_from_string
    >>> unparsed_fields = deb822_from_string('''
    ... Package: python3.4-minimal
    ... Version: 3.4.0-1+precise1
    ... Architecture: amd64
    ... Installed-Size: 3586
    ... Pre-Depends: libc6 (>= 2.15)
    ... Depends: libpython3.4-minimal (= 3.4.0-1+precise1), libexpat1 (>= 1.95.8), libgcc1 (>= 1:4.1.1), zlib1g (>= 1:1.2.0), foo | bar
    ... Recommends: python3.4
    ... Suggests: binfmt-support
    ... Conflicts: binfmt-support (<< 1.1.2)
    ... ''')

    Here are the control file fields as parsed by the
    :class:`debian.deb822` module:

    >>> print(repr(unparsed_fields))
    {'Architecture': u'amd64',
     'Conflicts': u'binfmt-support (<< 1.1.2)',
     'Depends': u'libpython3.4-minimal (= 3.4.0-1+precise1), libexpat1 (>= 1.95.8), libgcc1 (>= 1:4.1.1), zlib1g (>= 1:1.2.0), foo | bar',
     'Installed-Size': u'3586',
     'Package': u'python3.4-minimal',
     'Pre-Depends': u'libc6 (>= 2.15)',
     'Recommends': u'python3.4',
     'Suggests': u'binfmt-support',
     'Version': u'3.4.0-1+precise1'}

    Notice the value of the `Depends` line is a comma separated string, i.e. it
    hasn't been parsed. Now here are the control file fields parsed by the
    :func:`parse_control_fields()` function:

    >>> from deb_pkg_tools.control import parse_control_fields
    >>> parsed_fields = parse_control_fields(unparsed_fields)
    >>> print(repr(parsed_fields))
    {'Architecture': u'amd64',
     'Conflicts': RelationshipSet(VersionedRelationship(name=u'binfmt-support', operator=u'<<', version=u'1.1.2')),
     'Depends': RelationshipSet(VersionedRelationship(name=u'libpython3.4-minimal', operator=u'=', version=u'3.4.0-1+precise1'),
                                VersionedRelationship(name=u'libexpat1', operator=u'>=', version=u'1.95.8'),
                                VersionedRelationship(name=u'libgcc1', operator=u'>=', version=u'1:4.1.1'),
                                VersionedRelationship(name=u'zlib1g', operator=u'>=', version=u'1:1.2.0'),
                                AlternativeRelationship(Relationship(name=u'foo'), Relationship(name=u'bar'))),
     'Installed-Size': 3586,
     'Package': u'python3.4-minimal',
     'Pre-Depends': RelationshipSet(VersionedRelationship(name=u'libc6', operator=u'>=', version=u'2.15')),
     'Recommends': u'python3.4',
     'Suggests': RelationshipSet(Relationship(name=u'binfmt-support')),
     'Version': u'3.4.0-1+precise1'}

    For more information about fields like `Depends` and `Suggests` please
    refer to the documentation of :func:`.parse_depends()`.
    """
    logger.debug("Parsing %i control fields ..", len(input_fields))
    output_fields = {}
    for name, unparsed_value in input_fields.items():
        name = normalize_control_field_name(name)
        if name in DEPENDS_LIKE_FIELDS:
            parsed_value = parse_depends(unparsed_value)
        elif name == 'Installed-Size':
            parsed_value = int(unparsed_value)
        else:
            parsed_value = unparsed_value
        output_fields[name] = parsed_value
    logger.debug("Parsed fields: %s", output_fields)
    return output_fields
def parse_control_fields(input_fields):
    r"""
    The :py:class:`debian.deb822.Deb822` class can be used to parse Debian
    control files but the result is a simple :py:class:`dict` with string
    name/value pairs. This function takes an existing :py:class:`debian.deb822.Deb822`
    instance and converts known fields into friendlier formats, for example:

    - The value of `Depends`, `Provides`, `Replaces` and `Conflicts` fields is
      converted to a list of strings.

    - The value of the `Installed-Size` field is converted to an integer.

    :param input_fields: The dictionary to convert (may be an instance of
                         :py:class:`debian.deb822.Deb822` but doesn't have
                         to be).
    :returns: A :py:class:`dict` object with the converted fields.

    Let's look at an example. We start with the raw control file contents so
    you can see the complete input:

    >>> from deb_pkg_tools.control import deb822_from_string
    >>> unparsed_fields = deb822_from_string('''
    ... Package: python3.4-minimal
    ... Version: 3.4.0-1+precise1
    ... Architecture: amd64
    ... Installed-Size: 3586
    ... Pre-Depends: libc6 (>= 2.15)
    ... Depends: libpython3.4-minimal (= 3.4.0-1+precise1), libexpat1 (>= 1.95.8), libgcc1 (>= 1:4.1.1), zlib1g (>= 1:1.2.0), foo | bar
    ... Recommends: python3.4
    ... Suggests: binfmt-support
    ... Conflicts: binfmt-support (<< 1.1.2)
    ... ''')

    Here are the control file fields as parsed by the
    :py:class:`debian.deb822` module:

    >>> print(repr(unparsed_fields))
    {'Architecture': u'amd64',
     'Conflicts': u'binfmt-support (<< 1.1.2)',
     'Depends': u'libpython3.4-minimal (= 3.4.0-1+precise1), libexpat1 (>= 1.95.8), libgcc1 (>= 1:4.1.1), zlib1g (>= 1:1.2.0), foo | bar',
     'Installed-Size': u'3586',
     'Package': u'python3.4-minimal',
     'Pre-Depends': u'libc6 (>= 2.15)',
     'Recommends': u'python3.4',
     'Suggests': u'binfmt-support',
     'Version': u'3.4.0-1+precise1'}

    Notice the value of the `Depends` line is a comma separated string, i.e. it
    hasn't been parsed. Now here are the control file fields parsed by the
    :py:func:`parse_control_fields()` function:

    >>> from deb_pkg_tools.control import parse_control_fields
    >>> parsed_fields = parse_control_fields(unparsed_fields)
    >>> print(repr(parsed_fields))
    {'Architecture': u'amd64',
     'Conflicts': RelationshipSet(VersionedRelationship(name=u'binfmt-support', operator=u'<<', version=u'1.1.2')),
     'Depends': RelationshipSet(VersionedRelationship(name=u'libpython3.4-minimal', operator=u'=', version=u'3.4.0-1+precise1'),
                                VersionedRelationship(name=u'libexpat1', operator=u'>=', version=u'1.95.8'),
                                VersionedRelationship(name=u'libgcc1', operator=u'>=', version=u'1:4.1.1'),
                                VersionedRelationship(name=u'zlib1g', operator=u'>=', version=u'1:1.2.0'),
                                AlternativeRelationship(Relationship(name=u'foo'), Relationship(name=u'bar'))),
     'Installed-Size': 3586,
     'Package': u'python3.4-minimal',
     'Pre-Depends': RelationshipSet(VersionedRelationship(name=u'libc6', operator=u'>=', version=u'2.15')),
     'Recommends': u'python3.4',
     'Suggests': RelationshipSet(Relationship(name=u'binfmt-support')),
     'Version': u'3.4.0-1+precise1'}

    For more information about fields like `Depends` and `Suggests` please
    refer to the documentation of :py:func:`.parse_depends()`.
    """
    logger.debug("Parsing %i control fields ..", len(input_fields))
    output_fields = {}
    for name, unparsed_value in input_fields.items():
        name = normalize_control_field_name(name)
        if name in DEPENDS_LIKE_FIELDS:
            parsed_value = parse_depends(unparsed_value)
        elif name == "Installed-Size":
            parsed_value = int(unparsed_value)
        else:
            parsed_value = unparsed_value
        output_fields[name] = parsed_value
    logger.debug("Parsed fields: %s", output_fields)
    return output_fields