Bug#670679: python-debian: deb822 can't parse foreign architecture (package:any) relationships

John Wright jsw at debian.org
Sun Aug 3 04:04:41 UTC 2014


Hi Stuart,

On Sat, Aug 02, 2014 at 07:02:02PM +1000, Stuart Prescott wrote:
> 
> Hi again
> 
> I've had a go at reworking the handling of multiarch qualifiers for Build-
> Depends. My objectives here were:
> 
> * to support all the different qualifiers that are on the horizon (so :native, 
> :i386 etc as well as :any)
> 
> * to expose an API similar to dpkg's Deps.pm (or at least using the same 
> terminology)
> 
> At this stage, I've not exposed any API to interpret the special values like 
> "native" or "any". I think to do so we should move away from the parsed 
> package relationship being only a dict and make it a real object and expose 
> methods or properties to test for these special values.
> 
> Following the spirit of Stefano's work on this, I've done a little 
> housekeeping on this part of the code too in an effort to help make it a little 
> easier to work with when making the later changes. I've actually done the 
> tidying first up as that then makes the later multiarch diffs much smaller toand 
> hopefully easier to review. Thanks to Stefano Rivera for the original set of 
> patches which I made heavy use of in doing this work.
> 
> While I was touching this part of the code, I've also taken the opportunity to 
> take a stab at adding support for build profiles. There's no time like the 
> present to get these things sorted out!
> 
> I've done this work based upon my branch with the previous deb822 paragraphs 
> iterator work -- the patches should actually be portable across branches and 
> I'll do that if it's actually required. The patches are attached or, if you'd 
> rather see the context, 
> 
>   git clone ssh://git.nanonanonano.net/srv/git/python-debian.git -b multiarch
> 
> (if I update the patches based on comments, I can't promise not to rewrite 
> history on that branch!)
> 
> As with the work on the paragraphs iterator, I'd very much like some feedback 
> ;)

Thanks for doing this!  Comments inline.

> From 3c06fe85f52524bbbee06ae514a424d7f1f4a3f9 Mon Sep 17 00:00:00 2001
> From: Stefano Rivera <stefanor at debian.org>
> Date: Fri, 27 Apr 2012 23:35:36 +0200
> Subject: [PATCH 1/6] Break a very long regex up
> 
> ---
>  lib/debian/deb822.py | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/debian/deb822.py b/lib/debian/deb822.py
> index 86ceb7c..7862934 100644
> --- a/lib/debian/deb822.py
> +++ b/lib/debian/deb822.py
> @@ -881,8 +881,11 @@ class PkgRelation(object):
>      # XXX *NOT* a real dependency parser, and that is not even a goal here, we
>      # just parse as much as we need to split the various parts composing a
>      # dependency, checking their correctness wrt policy is out of scope
> -    __dep_RE = re.compile( \
> -            r'^\s*(?P<name>[a-zA-Z0-9.+\-]{2,})(\s*\(\s*(?P<relop>[>=<]+)\s*(?P<version>[0-9a-zA-Z:\-+~.]+)\s*\))?(\s*\[(?P<archs>[\s!\w\-]+)\])?\s*$')
> +    __dep_RE = re.compile(
> +            r'^\s*(?P<name>[a-zA-Z0-9.+\-]{2,})'
> +            r'(\s*\(\s*(?P<relop>[>=<]+)\s*'
> +            r'(?P<version>[0-9a-zA-Z:\-+~.]+)\s*\))?'
> +            r'(\s*\[(?P<archs>[\s!\w\-]+)\])?\s*$')
>      __comma_sep_RE = re.compile(r'\s*,\s*')
>      __pipe_sep_RE = re.compile(r'\s*\|\s*')
>      __blank_sep_RE = re.compile(r'\s*')
> -- 
> 1.9.1
> 

> From 700a36bae738b2fe454cdc7ef2f3ca261a7e6769 Mon Sep 17 00:00:00 2001
> From: Stuart Prescott <stuart at debian.org>
> Date: Sat, 2 Aug 2014 17:32:33 +1000
> Subject: [PATCH 2/6] Tidy creation of relation parsing
> 
> Preliminary house keeping for multiarch work
> ---
>  lib/debian/deb822.py | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/lib/debian/deb822.py b/lib/debian/deb822.py
> index 7862934..07c1dd4 100644
> --- a/lib/debian/deb822.py
> +++ b/lib/debian/deb822.py
> @@ -896,7 +896,7 @@ class PkgRelation(object):
>          Depends, Recommends, Build-Depends ...)
>          """
>          def parse_archs(raw):
> -            # assumption: no space beween '!' and architecture name
> +            # assumption: no space between '!' and architecture name
>              archs = []
>              for arch in cls.__blank_sep_RE.split(raw.strip()):
>                  if len(arch) and arch[0] == '!':
> @@ -909,14 +909,14 @@ class PkgRelation(object):
>              match = cls.__dep_RE.match(raw)
>              if match:
>                  parts = match.groupdict()
> -                d = { 'name': parts['name'] }
> +                d = {
> +                        'name': parts['name'],
> +                        'version': None,
> +                        'arch': None

Please add trailing comma, so adding an entry only requires adding a
line vs. also changing one.

> +                    }

Total nit: I prefer the style like

  d = {
          'foo': 'bar',
          # ...
  }

But consistency is more important, so up to you.

>                  if not (parts['relop'] is None or parts['version'] is None):

Since you're editing stuff in here, this might be easier to read as

  if parts['relop'] is not None and parts['version'] is not None:

and even maybe just drop "is not None" if having an empty value isn't
ever expected or valid.

>                      d['version'] = (parts['relop'], parts['version'])
> -                else:
> -                    d['version'] = None
> -                if parts['archs'] is None:
> -                    d['arch'] = None
> -                else:
> +                if parts['archs']:
>                      d['arch'] = parse_archs(parts['archs'])
>                  return d
>              else:
> -- 
> 1.9.1
> 

> From ff7da03eb19a0e0e8ed59706b8a635f30f106032 Mon Sep 17 00:00:00 2001
> From: Stuart Prescott <stuart at debian.org>
> Date: Sat, 2 Aug 2014 17:46:25 +1000
> Subject: [PATCH 4/6] Use custom assertion for testing package relations
> 
> Output from AssertEquals doesn't help work out where the difference actually
> is, so assert equality on smaller chunks of the larger data structure.
> ---
>  tests/test_deb822.py | 17 +++++++++++++----
>  1 file changed, 13 insertions(+), 4 deletions(-)
> 
> diff --git a/tests/test_deb822.py b/tests/test_deb822.py
> index 187b116..67606cd 100755
> --- a/tests/test_deb822.py
> +++ b/tests/test_deb822.py
> @@ -931,6 +931,13 @@ class TestPkgRelations(unittest.TestCase):
>  
>                  self.assertTrue(any(item.category == warning for item in warning_list))
>  
> +    def assertPkgDictEqual(self, p1, p2):
> +        p1keys = set(p1.keys())
> +        p2keys = set(p2.keys())
> +        self.assertEqual(p1keys, p2keys)
> +        for k in p1keys:
> +            self.assertEqual(p1[k], p2[k])

Might be helpful to print the key as part of the error message (I think
there's an optional arg for assertEqual for that).

> +
>      @staticmethod
>      def rel(dict_):
>          '''Helper for making PkgRelation dicts'''
> @@ -938,6 +945,8 @@ class TestPkgRelations(unittest.TestCase):
>              dict_['version'] = None
>          if 'arch' not in dict_:
>              dict_['arch'] = None
> +        if 'archqual' not in dict_:
> +            dict_['archqual'] = None
>          return dict_
>  
>      def test_packages(self):
> @@ -978,7 +987,7 @@ class TestPkgRelations(unittest.TestCase):
>                          [rel({'name': 'texlive-base-bin'})]
>                      ]
>                  }
> -        self.assertEqual(rel1, pkg1.relations)
> +        self.assertPkgDictEqual(rel1, pkg1.relations)
>          pkg2 = next(pkgs)
>          rel2 = {'breaks': [],
>                  'conflicts': [],
> @@ -998,7 +1007,7 @@ class TestPkgRelations(unittest.TestCase):
>                  'replaces': [],
>                  'suggests': []
>                  }
> -        self.assertEqual(rel2, pkg2.relations)
> +        self.assertPkgDictEqual(rel2, pkg2.relations)
>          pkg3 = next(pkgs)
>          dep3 = [
>                  [rel({'name': 'dcoprss', 'version': ('>=', '4:3.5.9-2')})],
> @@ -1056,7 +1065,7 @@ class TestPkgRelations(unittest.TestCase):
>                          [rel({'name': 'apache2-mpm-itk'})]
>                      ]
>                  }
> -        self.assertEqual(rel1, pkg1.relations)
> +        self.assertPkgDictEqual(rel1, pkg1.relations)
>          pkg2 = next(pkgs)
>          rel2 = {'build-conflicts': [],
>                  'build-conflicts-indep': [],
> @@ -1086,7 +1095,7 @@ class TestPkgRelations(unittest.TestCase):
>                          [rel({'name': 'binutils-source'})]
>                      ]
>                  }
> -        self.assertEqual(rel2, pkg2.relations)
> +        self.assertPkgDictEqual(rel2, pkg2.relations)
>          f.close()
>  
>  
> -- 
> 1.9.1
> 

> From b890bb49b89ee35fce8b850aa389cc786d49e972 Mon Sep 17 00:00:00 2001
> From: Stuart Prescott <stuart at debian.org>
> Date: Sat, 2 Aug 2014 17:33:50 +1000
> Subject: [PATCH 3/6] Sparsify PkgRelations test dictionaries
> 
> Push much of the relation syntax into a factory method to simply the test
> syntax -- more readable and more maintainable.
> 
> Based on patch by Stefano Rivera <stefanor at debian.org>.
> ---
>  tests/test_deb822.py | 172 +++++++++++++++++++++++++++++++--------------------
>  1 file changed, 104 insertions(+), 68 deletions(-)
> 
> diff --git a/tests/test_deb822.py b/tests/test_deb822.py
> index 6fe06e3..187b116 100755
> --- a/tests/test_deb822.py
> +++ b/tests/test_deb822.py
> @@ -931,67 +931,91 @@ class TestPkgRelations(unittest.TestCase):
>  
>                  self.assertTrue(any(item.category == warning for item in warning_list))
>  
> +    @staticmethod
> +    def rel(dict_):
> +        '''Helper for making PkgRelation dicts'''

""" rather than ''' would be more consistent for docstrings.  Also would
be nice if the doc said what it ts input and output was (and that it
modifies the input and returns it).

> +        if 'version' not in dict_:
> +            dict_['version'] = None
> +        if 'arch' not in dict_:
> +            dict_['arch'] = None
> +        return dict_
> +
>      def test_packages(self):
> +        # make the syntax a bit more compact
> +        rel = TestPkgRelations.rel
> +
>          f = open('test_Packages')
>          pkgs = deb822.Packages.iter_paragraphs(f)
>          pkg1 = next(pkgs)
>          rel1 = {'breaks': [],
>                  'conflicts': [],
> -                'depends': [[{'name': 'file', 'version': None, 'arch': None}],
> -                    [{'name': 'libc6', 'version': ('>=', '2.7-1'), 'arch': None}],
> -                    [{'name': 'libpaper1', 'version': None, 'arch': None}],
> -                    [{'name': 'psutils', 'version': None, 'arch': None}]],
> +                'depends': [
> +                        [rel({'name': 'file'})],
> +                        [rel({'name': 'libc6', 'version': ('>=', '2.7-1')})],
> +                        [rel({'name': 'libpaper1'})],
> +                        [rel({'name': 'psutils'})]

Please add trailing comma (here and elsewhere).

> +                    ],
>                  'enhances': [],
>                  'pre-depends': [],
>                  'provides': [],
> -                'recommends': [[{'name': 'bzip2', 'version': None, 'arch': None}],
> -                    [{'name': 'lpr', 'version': None, 'arch': None},
> -                        {'name': 'rlpr', 'version': None, 'arch': None},
> -                        {'name': 'cupsys-client', 'version': None, 'arch': None}],
> -                    [{'name': 'wdiff', 'version': None, 'arch': None}]],
> +                'recommends': [
> +                        [rel({'name': 'bzip2'})],
> +                        [rel({'name': 'lpr'}),
> +                            rel({'name': 'rlpr'}),
> +                            rel({'name': 'cupsys-client'})],
> +                        [rel({'name': 'wdiff'})]
> +                    ],
>                  'replaces': [],
> -                'suggests': [[{'name': 'emacsen-common', 'version': None, 'arch': None}],
> -                    [{'name': 'ghostscript', 'version': None, 'arch': None}],
> -                    [{'name': 'graphicsmagick-imagemagick-compat', 'version': None, 'arch': None},
> -                        {'name': 'imagemagick', 'version': None, 'arch': None}],
> -                    [{'name': 'groff', 'version': None, 'arch': None}],
> -                    [{'name': 'gv', 'version': None, 'arch': None}],
> -                    [{'name': 'html2ps', 'version': None, 'arch': None}],
> -                    [{'name': 't1-cyrillic', 'version': None, 'arch': None}],
> -                    [{'name': 'texlive-base-bin', 'version': None, 'arch': None}]]}
> +                'suggests': [
> +                        [rel({'name': 'emacsen-common'})],
> +                        [rel({'name': 'ghostscript'})],
> +                        [rel({'name': 'graphicsmagick-imagemagick-compat'}),
> +                            rel({'name': 'imagemagick'})],
> +                        [rel({'name': 'groff'})],
> +                        [rel({'name': 'gv'})],
> +                        [rel({'name': 'html2ps'})],
> +                        [rel({'name': 't1-cyrillic'})],
> +                        [rel({'name': 'texlive-base-bin'})]
> +                    ]
> +                }
>          self.assertEqual(rel1, pkg1.relations)
>          pkg2 = next(pkgs)
>          rel2 = {'breaks': [],
>                  'conflicts': [],
> -                'depends': [[{'name': 'lrzsz', 'version': None, 'arch': None}],
> -                    [{'name': 'openssh-client', 'version': None, 'arch': None},
> -                        {'name': 'telnet', 'version': None, 'arch': None},
> -                        {'name': 'telnet-ssl', 'version': None, 'arch': None}],
> -                    [{'name': 'libc6', 'version': ('>=', '2.6.1-1'), 'arch': None}],
> -                    [{'name': 'libncurses5', 'version': ('>=', '5.6'), 'arch': None}],
> -                    [{'name': 'libreadline5', 'version': ('>=', '5.2'), 'arch': None}]],
> +                'depends': [
> +                        [rel({'name': 'lrzsz'})],
> +                        [rel({'name': 'openssh-client'}),
> +                            rel({'name': 'telnet'}),
> +                            rel({'name': 'telnet-ssl'})],
> +                        [rel({'name': 'libc6', 'version': ('>=', '2.6.1-1')})],
> +                        [rel({'name': 'libncurses5', 'version': ('>=', '5.6')})],
> +                        [rel({'name': 'libreadline5', 'version': ('>=', '5.2')})]
> +                    ],
>                  'enhances': [],
>                  'pre-depends': [],
>                  'provides': [],
>                  'recommends': [],
>                  'replaces': [],
> -                'suggests': []}
> +                'suggests': []
> +                }
>          self.assertEqual(rel2, pkg2.relations)
>          pkg3 = next(pkgs)
> -        dep3 = [[{'arch': None, 'name': 'dcoprss', 'version': ('>=', '4:3.5.9-2')}],
> -            [{'arch': None, 'name': 'kdenetwork-kfile-plugins', 'version': ('>=', '4:3.5.9-2')}],
> -            [{'arch': None, 'name': 'kdict', 'version': ('>=', '4:3.5.9-2')}],
> -            [{'arch': None, 'name': 'kdnssd', 'version': ('>=', '4:3.5.9-2')}],
> -            [{'arch': None, 'name': 'kget', 'version': ('>=', '4:3.5.9-2')}],
> -            [{'arch': None, 'name': 'knewsticker', 'version': ('>=', '4:3.5.9-2')}],
> -            [{'arch': None, 'name': 'kopete', 'version': ('>=', '4:3.5.9-2')}],
> -            [{'arch': None, 'name': 'kpf', 'version': ('>=', '4:3.5.9-2')}],
> -            [{'arch': None, 'name': 'kppp', 'version': ('>=', '4:3.5.9-2')}],
> -            [{'arch': None, 'name': 'krdc', 'version': ('>=', '4:3.5.9-2')}],
> -            [{'arch': None, 'name': 'krfb', 'version': ('>=', '4:3.5.9-2')}],
> -            [{'arch': None, 'name': 'ksirc', 'version': ('>=', '4:3.5.9-2')}],
> -            [{'arch': None, 'name': 'kwifimanager', 'version': ('>=', '4:3.5.9-2')}],
> -            [{'arch': None, 'name': 'librss1', 'version': ('>=', '4:3.5.9-2')}]]
> +        dep3 = [
> +                [rel({'name': 'dcoprss', 'version': ('>=', '4:3.5.9-2')})],
> +                [rel({'name': 'kdenetwork-kfile-plugins', 'version': ('>=', '4:3.5.9-2')})],
> +                [rel({'name': 'kdict', 'version': ('>=', '4:3.5.9-2')})],
> +                [rel({'name': 'kdnssd', 'version': ('>=', '4:3.5.9-2')})],
> +                [rel({'name': 'kget', 'version': ('>=', '4:3.5.9-2')})],
> +                [rel({'name': 'knewsticker', 'version': ('>=', '4:3.5.9-2')})],
> +                [rel({'name': 'kopete', 'version': ('>=', '4:3.5.9-2')})],
> +                [rel({'name': 'kpf', 'version': ('>=', '4:3.5.9-2')})],
> +                [rel({'name': 'kppp', 'version': ('>=', '4:3.5.9-2')})],
> +                [rel({'name': 'krdc', 'version': ('>=', '4:3.5.9-2')})],
> +                [rel({'name': 'krfb', 'version': ('>=', '4:3.5.9-2')})],
> +                [rel({'name': 'ksirc', 'version': ('>=', '4:3.5.9-2')})],
> +                [rel({'name': 'kwifimanager', 'version': ('>=', '4:3.5.9-2')})],
> +                [rel({'name': 'librss1', 'version': ('>=', '4:3.5.9-2')})]
> +            ]
>          self.assertEqual(dep3, pkg3.relations['depends'])
>          f.close()
>  
> @@ -1011,45 +1035,57 @@ class TestPkgRelations(unittest.TestCase):
>                      "foo bar")
>  
>      def test_sources(self):
> +        # make the syntax a bit more compact
> +        rel = TestPkgRelations.rel
> +
>          f = open_utf8('test_Sources')
>          pkgs = deb822.Sources.iter_paragraphs(f)
>          pkg1 = next(pkgs)
>          rel1 = {'build-conflicts': [],
>                  'build-conflicts-indep': [],
> -                'build-depends': [[{'name': 'apache2-src', 'version': ('>=', '2.2.9'), 'arch': None}],
> -                    [{'name': 'libaprutil1-dev', 'version': None, 'arch': None}],
> -                    [{'arch': [(False, 'kfreebsd-i386'), (False, 'kfreebsd-amd64'), (False, 'hurd-i386')],
> -                        'name': 'libcap-dev',
> -                        'version': None}],
> -                    [{'name': 'autoconf', 'version': None, 'arch': None}],
> -                    [{'name': 'debhelper', 'version': ('>>', '5.0.0'), 'arch': None}]],
> +                'build-depends': [
> +                        [rel({'name': 'apache2-src', 'version': ('>=', '2.2.9')})],
> +                        [rel({'name': 'libaprutil1-dev'})],
> +                        [rel({'arch': [(False, 'kfreebsd-i386'), (False, 'kfreebsd-amd64'), (False, 'hurd-i386')],
> +                            'name': 'libcap-dev'})],
> +                        [rel({'name': 'autoconf'})],
> +                        [rel({'name': 'debhelper', 'version': ('>>', '5.0.0')})]
> +                    ],
>                  'build-depends-indep': [],
> -                'binary': [[{'name': 'apache2-mpm-itk', 'version': None, 'arch': None}]]}
> +                'binary': [
> +                        [rel({'name': 'apache2-mpm-itk'})]
> +                    ]
> +                }
>          self.assertEqual(rel1, pkg1.relations)
>          pkg2 = next(pkgs)
>          rel2 = {'build-conflicts': [],
>                  'build-conflicts-indep': [],
> -                'build-depends': [[{'name': 'dpkg-dev', 'version': ('>=', '1.13.9'), 'arch': None}],
> -                    [{'name': 'autoconf', 'version': ('>=', '2.13'), 'arch': None}],
> -                    [{'name': 'bash', 'version': None, 'arch': None}],
> -                    [{'name': 'bison', 'version': None, 'arch': None}],
> -                    [{'name': 'flex', 'version': None, 'arch': None}],
> -                    [{'name': 'gettext', 'version': None, 'arch': None}],
> -                    [{'name': 'texinfo', 'version': None, 'arch': None}],
> -                    [{'arch': [(True, 'hppa')], 'name': 'expect-tcl8.3', 'version': ('>=', '5.32.2')}],
> -                    [{'name': 'dejagnu', 'version': ('>=', '1.4.2-1.1'), 'arch': None}],
> -                    [{'name': 'dpatch', 'version': None, 'arch': None}],
> -                    [{'name': 'file', 'version': None, 'arch': None}],
> -                    [{'name': 'bzip2', 'version': None, 'arch': None}],
> -                    [{'name': 'lsb-release', 'version': None, 'arch': None}]],
> +                'build-depends': [
> +                        [rel({'name': 'dpkg-dev', 'version': ('>=', '1.13.9')})],
> +                        [rel({'name': 'autoconf', 'version': ('>=', '2.13')})],
> +                        [rel({'name': 'bash'})],
> +                        [rel({'name': 'bison'})],
> +                        [rel({'name': 'flex'})],
> +                        [rel({'name': 'gettext'})],
> +                        [rel({'name': 'texinfo'})],
> +                        [rel({'arch': [(True, 'hppa')], 'name': 'expect-tcl8.3', 'version': ('>=', '5.32.2')})],
> +                        [rel({'name': 'dejagnu', 'version': ('>=', '1.4.2-1.1'), 'arch': None})],
> +                        [rel({'name': 'dpatch'})],
> +                        [rel({'name': 'file'})],
> +                        [rel({'name': 'bzip2'})],
> +                        [rel({'name': 'lsb-release'})]
> +                    ],
>                  'build-depends-indep': [],
> -                'binary': [[{'name': 'binutils', 'version': None, 'arch': None}],
> -                    [{'name': 'binutils-dev', 'version': None, 'arch': None}],
> -                    [{'name': 'binutils-multiarch', 'version': None, 'arch': None}],
> -                    [{'name': 'binutils-hppa64', 'version': None, 'arch': None}],
> -                    [{'name': 'binutils-spu', 'version': None, 'arch': None}],
> -                    [{'name': 'binutils-doc', 'version': None, 'arch': None}],
> -                    [{'name': 'binutils-source', 'version': None, 'arch': None}]]}
> +                'binary': [
> +                        [rel({'name': 'binutils'})],
> +                        [rel({'name': 'binutils-dev'})],
> +                        [rel({'name': 'binutils-multiarch'})],
> +                        [rel({'name': 'binutils-hppa64'})],
> +                        [rel({'name': 'binutils-spu'})],
> +                        [rel({'name': 'binutils-doc'})],
> +                        [rel({'name': 'binutils-source'})]
> +                    ]
> +                }
>          self.assertEqual(rel2, pkg2.relations)
>          f.close()
>  
> -- 
> 1.9.1
> 

> From 9ecd0331f4fa81af4c06cec31cf7e5f66c12ea87 Mon Sep 17 00:00:00 2001
> From: Stuart Prescott <stuart at debian.org>
> Date: Sat, 2 Aug 2014 18:12:18 +1000
> Subject: [PATCH 5/6] Allow arch-qualifiers in package relationships
> 
> Any relationship is permitted and the relationship is not checked for validity
> just as the rest of the package relation is not checked. The set of qualifiers
> currently accepted in the archive includes :any but dpkg permits even more. There are plans to use :native and real arch-names (:i386, :amd64 etc) in the future.
> ---
>  lib/debian/deb822.py         | 2 ++
>  tests/test_Packages          | 2 +-
>  tests/test_Sources           | 4 ++--
>  tests/test_Sources.iso8859-1 | 4 ++--
>  tests/test_deb822.py         | 8 ++++----
>  5 files changed, 11 insertions(+), 9 deletions(-)
> 
> diff --git a/lib/debian/deb822.py b/lib/debian/deb822.py
> index 07c1dd4..eee7d9c 100644
> --- a/lib/debian/deb822.py
> +++ b/lib/debian/deb822.py
> @@ -883,6 +883,7 @@ class PkgRelation(object):
>      # dependency, checking their correctness wrt policy is out of scope
>      __dep_RE = re.compile(
>              r'^\s*(?P<name>[a-zA-Z0-9.+\-]{2,})'
> +            r'(:(?P<archqual>([a-zA-Z0-9][a-zA-Z0-9-]*)))?'
>              r'(\s*\(\s*(?P<relop>[>=<]+)\s*'
>              r'(?P<version>[0-9a-zA-Z:\-+~.]+)\s*\))?'
>              r'(\s*\[(?P<archs>[\s!\w\-]+)\])?\s*$')
> @@ -911,6 +912,7 @@ class PkgRelation(object):
>                  parts = match.groupdict()
>                  d = {
>                          'name': parts['name'],
> +                        'archqual': parts['archqual'],
>                          'version': None,
>                          'arch': None
>                      }
> diff --git a/tests/test_Packages b/tests/test_Packages
> index 6cbee8b..1ace825 100644
> --- a/tests/test_Packages
> +++ b/tests/test_Packages
> @@ -5,7 +5,7 @@ Installed-Size: 4244
>  Maintainer: Masayuki Hatta (mhatta) <mhatta at debian.org>
>  Architecture: i386
>  Version: 1:4.14-1
> -Depends: file, libc6 (>= 2.7-1), libpaper1, psutils
> +Depends: file:i386, libc6 (>= 2.7-1), libpaper1, psutils
>  Recommends: bzip2, lpr | rlpr | cupsys-client, wdiff
>  Suggests: emacsen-common, ghostscript, graphicsmagick-imagemagick-compat | imagemagick, groff, gv, html2ps, t1-cyrillic, texlive-base-bin
>  Filename: pool/main/a/a2ps/a2ps_4.14-1_i386.deb
> diff --git a/tests/test_Sources b/tests/test_Sources
> index f5d53a9..a77aea9 100644
> --- a/tests/test_Sources
> +++ b/tests/test_Sources
> @@ -26,7 +26,7 @@ Version: 2.18.1~cvs20080103-6
>  Priority: optional
>  Section: devel
>  Maintainer: James Troup <james at nocrew.org>
> -Build-Depends: dpkg-dev (>= 1.13.9), autoconf (>= 2.13), bash, bison, flex, gettext, texinfo, expect-tcl8.3 (>= 5.32.2) [hppa], dejagnu (>= 1.4.2-1.1), dpatch, file, bzip2, lsb-release
> +Build-Depends: dpkg-dev (>= 1.13.9), autoconf (>= 2.13), bash, bison:amd64, flex, gettext:any, texinfo, expect-tcl8.3 (>= 5.32.2) [hppa], dejagnu (>= 1.4.2-1.1), dpatch, file, bzip2:native, lsb-release
>  Architecture: any
>  Standards-Version: 3.7.3
>  Format: 1.0
> @@ -68,7 +68,7 @@ Version: 0.1.14
>  Priority: optional
>  Section: devel
>  Maintainer: Debian python-debian Maintainers <pkg-python-debian-maint at lists.alioth.debian.org>
> -Build-Depends: debhelper (>= 5.0.37.2), python, python-setuptools
> +Build-Depends: debhelper (>= 5.0.37.2), python:any, python-setuptools
>  Build-Depends-Indep: python-support (>= 0.3)
>  Architecture: all
>  Standards-Version: 3.8.1
> diff --git a/tests/test_Sources.iso8859-1 b/tests/test_Sources.iso8859-1
> index 253f9d6..af4dcce 100644
> --- a/tests/test_Sources.iso8859-1
> +++ b/tests/test_Sources.iso8859-1
> @@ -26,7 +26,7 @@ Version: 2.18.1~cvs20080103-6
>  Priority: optional
>  Section: devel
>  Maintainer: James Troup <james at nocrew.org>
> -Build-Depends: dpkg-dev (>= 1.13.9), autoconf (>= 2.13), bash, bison, flex, gettext, texinfo, expect-tcl8.3 (>= 5.32.2) [hppa], dejagnu (>= 1.4.2-1.1), dpatch, file, bzip2, lsb-release
> +Build-Depends: dpkg-dev (>= 1.13.9), autoconf (>= 2.13), bash, bison:amd64, flex, gettext:any, texinfo, expect-tcl8.3 (>= 5.32.2) [hppa], dejagnu (>= 1.4.2-1.1), dpatch, file, bzip2:native, lsb-release
>  Architecture: any
>  Standards-Version: 3.7.3
>  Format: 1.0
> @@ -68,7 +68,7 @@ Version: 0.1.14
>  Priority: optional
>  Section: devel
>  Maintainer: Debian python-debian Maintainers <pkg-python-debian-maint at lists.alioth.debian.org>
> -Build-Depends: debhelper (>= 5.0.37.2), python, python-setuptools
> +Build-Depends: debhelper (>= 5.0.37.2), python:any, python-setuptools
>  Build-Depends-Indep: python-support (>= 0.3)
>  Architecture: all
>  Standards-Version: 3.8.1
> diff --git a/tests/test_deb822.py b/tests/test_deb822.py
> index 67606cd..b864609 100755
> --- a/tests/test_deb822.py
> +++ b/tests/test_deb822.py
> @@ -959,7 +959,7 @@ class TestPkgRelations(unittest.TestCase):
>          rel1 = {'breaks': [],
>                  'conflicts': [],
>                  'depends': [
> -                        [rel({'name': 'file'})],
> +                        [rel({'name': 'file', 'archqual': 'i386'})],
>                          [rel({'name': 'libc6', 'version': ('>=', '2.7-1')})],
>                          [rel({'name': 'libpaper1'})],
>                          [rel({'name': 'psutils'})]
> @@ -1073,15 +1073,15 @@ class TestPkgRelations(unittest.TestCase):
>                          [rel({'name': 'dpkg-dev', 'version': ('>=', '1.13.9')})],
>                          [rel({'name': 'autoconf', 'version': ('>=', '2.13')})],
>                          [rel({'name': 'bash'})],
> -                        [rel({'name': 'bison'})],
> +                        [rel({'name': 'bison', 'archqual': 'amd64'})],
>                          [rel({'name': 'flex'})],
> -                        [rel({'name': 'gettext'})],
> +                        [rel({'name': 'gettext', 'archqual': 'any'})],
>                          [rel({'name': 'texinfo'})],
>                          [rel({'arch': [(True, 'hppa')], 'name': 'expect-tcl8.3', 'version': ('>=', '5.32.2')})],
>                          [rel({'name': 'dejagnu', 'version': ('>=', '1.4.2-1.1'), 'arch': None})],
>                          [rel({'name': 'dpatch'})],
>                          [rel({'name': 'file'})],
> -                        [rel({'name': 'bzip2'})],
> +                        [rel({'name': 'bzip2', 'archqual': 'native'})],
>                          [rel({'name': 'lsb-release'})]
>                      ],
>                  'build-depends-indep': [],
> -- 
> 1.9.1
> 

> From 844112873929fa6ac0ca8e20a4b38474482e9a80 Mon Sep 17 00:00:00 2001
> From: Stuart Prescott <stuart at debian.org>
> Date: Sat, 2 Aug 2014 18:35:52 +1000
> Subject: [PATCH 6/6] Add support for build-profiles
> 
> Parse the <profile.name> syntax, creating a list of profiles and whether
> they are positive or negative specifications in the same style as the architecture
> restriction list.
> 
> The syntactic correctness of the profile name is not enforced.
> 
>     https://wiki.debian.org/BuildProfileSpec
> ---
>  lib/debian/deb822.py         | 10 ++++++++--
>  tests/test_Sources           |  2 +-
>  tests/test_Sources.iso8859-1 |  2 +-
>  tests/test_deb822.py         |  9 +++++++--
>  4 files changed, 17 insertions(+), 6 deletions(-)
> 
> diff --git a/lib/debian/deb822.py b/lib/debian/deb822.py
> index eee7d9c..0b12d3d 100644
> --- a/lib/debian/deb822.py
> +++ b/lib/debian/deb822.py
> @@ -886,7 +886,8 @@ class PkgRelation(object):
>              r'(:(?P<archqual>([a-zA-Z0-9][a-zA-Z0-9-]*)))?'
>              r'(\s*\(\s*(?P<relop>[>=<]+)\s*'
>              r'(?P<version>[0-9a-zA-Z:\-+~.]+)\s*\))?'
> -            r'(\s*\[(?P<archs>[\s!\w\-]+)\])?\s*$')
> +            r'(\s*\[(?P<archs>[\s!\w\-]+)\])?\s*'
> +            r'(<(?P<restrictions>.+)>)?\s*$')

Optional: Put the ) on the next line so adding more bits doesn't require
changing multiple lines?

>      __comma_sep_RE = re.compile(r'\s*,\s*')
>      __pipe_sep_RE = re.compile(r'\s*\|\s*')
>      __blank_sep_RE = re.compile(r'\s*')
> @@ -906,6 +907,8 @@ class PkgRelation(object):
>                      archs.append((True, arch))
>              return archs
>  
> +        parse_profiles = parse_archs
> +
>          def parse_rel(raw):
>              match = cls.__dep_RE.match(raw)
>              if match:
> @@ -914,12 +917,15 @@ class PkgRelation(object):
>                          'name': parts['name'],
>                          'archqual': parts['archqual'],
>                          'version': None,
> -                        'arch': None
> +                        'arch': None,
> +                        'restrictions': None,
>                      }
>                  if not (parts['relop'] is None or parts['version'] is None):
>                      d['version'] = (parts['relop'], parts['version'])
>                  if parts['archs']:
>                      d['arch'] = parse_archs(parts['archs'])
> +                if parts['restrictions']:
> +                    d['restrictions'] = parse_profiles(parts['restrictions'].lower())
>                  return d
>              else:
>                  warnings.warn('cannot parse package' \
> diff --git a/tests/test_Sources b/tests/test_Sources
> index a77aea9..1ffab0d 100644
> --- a/tests/test_Sources
> +++ b/tests/test_Sources
> @@ -26,7 +26,7 @@ Version: 2.18.1~cvs20080103-6
>  Priority: optional
>  Section: devel
>  Maintainer: James Troup <james at nocrew.org>
> -Build-Depends: dpkg-dev (>= 1.13.9), autoconf (>= 2.13), bash, bison:amd64, flex, gettext:any, texinfo, expect-tcl8.3 (>= 5.32.2) [hppa], dejagnu (>= 1.4.2-1.1), dpatch, file, bzip2:native, lsb-release
> +Build-Depends: dpkg-dev (>= 1.13.9), autoconf (>= 2.13), bash, bison:amd64, flex, gettext:any, texinfo <!profile.stage1 !profile.cross>, expect-tcl8.3 (>= 5.32.2) [hppa] <!profile.stage1>, dejagnu (>= 1.4.2-1.1), dpatch, file, bzip2:native, lsb-release
>  Architecture: any
>  Standards-Version: 3.7.3
>  Format: 1.0
> diff --git a/tests/test_Sources.iso8859-1 b/tests/test_Sources.iso8859-1
> index af4dcce..948b190 100644
> --- a/tests/test_Sources.iso8859-1
> +++ b/tests/test_Sources.iso8859-1
> @@ -26,7 +26,7 @@ Version: 2.18.1~cvs20080103-6
>  Priority: optional
>  Section: devel
>  Maintainer: James Troup <james at nocrew.org>
> -Build-Depends: dpkg-dev (>= 1.13.9), autoconf (>= 2.13), bash, bison:amd64, flex, gettext:any, texinfo, expect-tcl8.3 (>= 5.32.2) [hppa], dejagnu (>= 1.4.2-1.1), dpatch, file, bzip2:native, lsb-release
> +Build-Depends: dpkg-dev (>= 1.13.9), autoconf (>= 2.13), bash, bison:amd64, flex, gettext:any, texinfo <!profile.stage1 !profile.cross>, expect-tcl8.3 (>= 5.32.2) [hppa] <!profile.stage1>, dejagnu (>= 1.4.2-1.1), dpatch, file, bzip2:native, lsb-release
>  Architecture: any
>  Standards-Version: 3.7.3
>  Format: 1.0
> diff --git a/tests/test_deb822.py b/tests/test_deb822.py
> index b864609..837966b 100755
> --- a/tests/test_deb822.py
> +++ b/tests/test_deb822.py
> @@ -947,6 +947,8 @@ class TestPkgRelations(unittest.TestCase):
>              dict_['arch'] = None
>          if 'archqual' not in dict_:
>              dict_['archqual'] = None
> +        if 'restrictions' not in dict_:
> +            dict_['restrictions'] = None
>          return dict_
>  
>      def test_packages(self):
> @@ -1076,8 +1078,11 @@ class TestPkgRelations(unittest.TestCase):
>                          [rel({'name': 'bison', 'archqual': 'amd64'})],
>                          [rel({'name': 'flex'})],
>                          [rel({'name': 'gettext', 'archqual': 'any'})],
> -                        [rel({'name': 'texinfo'})],
> -                        [rel({'arch': [(True, 'hppa')], 'name': 'expect-tcl8.3', 'version': ('>=', '5.32.2')})],
> +                        [rel({'name': 'texinfo',
> +                            'restrictions': [(False, 'profile.stage1'), (False, 'profile.cross')]})],
> +                        [rel({'arch': [(True, 'hppa')], 'name': 'expect-tcl8.3',
> +                            'version': ('>=', '5.32.2'),
> +                            'restrictions': [(False, 'profile.stage1')]})],
>                          [rel({'name': 'dejagnu', 'version': ('>=', '1.4.2-1.1'), 'arch': None})],
>                          [rel({'name': 'dpatch'})],
>                          [rel({'name': 'file'})],
> -- 
> 1.9.1
> 

Overall, LGTM, thanks again!

> -- 
> http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-python-debian-maint

-- 
John Wright <jsw at debian.org>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.alioth.debian.org/pipermail/pkg-python-debian-maint/attachments/20140803/70ab4f02/attachment-0001.sig>


More information about the pkg-python-debian-maint mailing list