22import re
33import subprocess
44
5+ from pkgcore .ebuild .atom import atom as atom_cls
56from pkgcore .restrictions import packages , values
7+ from pkgcore .package .errors import MetadataException
68from snakeoil .osutils import pjoin
9+ from snakeoil .sequences import iflatten_instance
710
811from .. import const , results , sources
912from . import OptionalCheck , SkipCheck
@@ -22,6 +25,24 @@ def desc(self):
2225 return f"DIST_VERSION={ self .dist_version } normalizes to { self .normalized } "
2326
2427
28+ class MissingVersionedVirtualPerlDependency (results .VersionResult , results .Warning ):
29+ """Missing version restriction for virtual perl dependency.
30+
31+ The virtuals ``virtual/perl-*`` stand for packages that have releases both
32+ as part of ``dev-lang/perl`` and standalone in ``perl-core/*``. Apart from
33+ rare special cases, if you require "any" version of such a virtual, this
34+ will always be fulfilled by ``dev-lang/perl``.
35+ """
36+
37+ def __init__ (self , atom , ** kwargs ):
38+ super ().__init__ (** kwargs )
39+ self .atom = atom
40+
41+ @property
42+ def desc (self ):
43+ return f"missing version restriction for virtual perl: { self .atom !r} "
44+
45+
2546class _PerlException (Exception ):
2647 """Generic error during perl script initialization."""
2748
@@ -70,12 +91,13 @@ def __del__(self):
7091class PerlCheck (OptionalCheck ):
7192 """Perl ebuild related checks."""
7293
73- _restricted_source = (
74- sources .RestrictionRepoSource ,
75- (packages .PackageRestriction ("inherited" , values .ContainmentMatch2 ("perl-module" )),),
94+ _source = sources .EbuildFileRepoSource
95+ known_results = frozenset (
96+ {
97+ MismatchedPerlVersion ,
98+ MissingVersionedVirtualPerlDependency ,
99+ }
76100 )
77- _source = (sources .EbuildFileRepoSource , (), (("source" , _restricted_source ),))
78- known_results = frozenset ([MismatchedPerlVersion ])
79101
80102 def __init__ (self , * args ):
81103 super ().__init__ (* args )
@@ -86,12 +108,32 @@ def __init__(self, *args):
86108 # it easier to disable this check if required perl deps are missing.
87109 try :
88110 self .perl = _PerlConnection (self .options )
89- except _PerlException as e :
90- raise SkipCheck (self , str (e ))
111+ except _PerlException as exc :
112+ raise SkipCheck (self , str (exc ))
91113
92114 def feed (self , pkg ):
93- if mo := self .dist_version_re .search ("" .join (pkg .lines )):
94- dist_version = mo .group ("dist_version" )
95- normalized = self .perl .normalize (dist_version )
96- if normalized != pkg .version :
97- yield MismatchedPerlVersion (dist_version , normalized , pkg = pkg )
115+ if "perl-module" in pkg .inherited :
116+ if mo := self .dist_version_re .search ("" .join (pkg .lines )):
117+ dist_version = mo .group ("dist_version" )
118+ normalized = self .perl .normalize (dist_version )
119+ if normalized != pkg .version :
120+ yield MismatchedPerlVersion (dist_version , normalized , pkg = pkg )
121+
122+ missing_virtual_perl = set ()
123+ for attr in (x .lower () for x in pkg .eapi .dep_keys ):
124+ try :
125+ deps = getattr (pkg , attr )
126+ except MetadataException :
127+ continue
128+ for atom in iflatten_instance (deps , (atom_cls ,)):
129+ if (
130+ not atom .op
131+ and atom .key .startswith ("virtual/perl-" )
132+ and pkg .key != "dev-lang/perl"
133+ and pkg .category != "perl-core"
134+ and not pkg .key .startswith ("virtual/perl-" )
135+ ):
136+ missing_virtual_perl .add (str (atom ))
137+
138+ for atom in sorted (missing_virtual_perl ):
139+ yield MissingVersionedVirtualPerlDependency (str (atom ), pkg = pkg )
0 commit comments