Vc@sBddkZddkiiZddkiiZddkZddk Zddk l Z ddk l Z lZddkZddkZddkZddkZddkZddkZdZdZeeii_defdYZdefd YZd fd YZd efd YZeedZ dZ!dS(iN(t ApiException(t DotSequencetVersiontpkglintiRtLintEngineExceptioncBseZdZdZRS(svAn exception thrown when something fatal goes wrong with the engine, such that linting can no longer continue.cCs t|S(N(tstr(tself((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyt __unicode__2s(t__name__t __module__t__doc__R(((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyR.stLintEngineSetupExceptioncBseZdZdZRS(sAAn exception thrown when the engine failed to complete its setup.cCs t|S(N(R(R((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyR;s(RR R R(((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyR 8stLintEngineCachecBsPeZdZddZdZdZdZdZdZ dZ RS( sThis class provides two caches for the LintEngine. A cache of the latest packages for one or more ImageInterface objects intended to be seeded at startup, and a generic manifest cachecCsh|_h|_tid|_t|_||_||_|iovd|i dd|f}y t |i dd|_ Wqt i ij o ttd|iqXndS(NRs%s%st,it-sInvalid release string: %s(t latest_cachet misc_cachetloggingt getLoggertloggertFalsetseededtversion_patterntreleasetsplitRtbranchtpkgtversiontIllegalDotSequenceR t_(RRRtcombined((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyt__init__Fs        cCsBtiiii}dg}t|_h}h|i||p |Vq>q>WndS(s A generator function to return the latest version of the packages matching the supplied pattern from the publishers set for api_instsCache has not been seededN(RRRtsortedRR-t glob_matchR(RR7tpatternR=tmf((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyt gen_latests  cCsV|iptdn||ijo(||i|jo|i||SndS(s[ Return the package matching pkg_name from the publishers set for api_inst sCache has not been seededN(RRRR0(RR7tpkg_name((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyt get_latests  cCs|iptdn|pt|i|Sd}xS|i|D]D}|i||}tiit|i|o|d}qGqGW|S(sReturns the number of manifests in the given api_inst cache that match the provided pattern. If pattern is None, we return the length of the api_inst cache.sCache has not been seededii(RRR3RRR-RFR(RR7RGtcountR=RH((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyt count_latests cCs||i||/ref_image/ The image for linting is stored in /lint_image/ We can also lint pkg.manifest.Manifest objects, passed as the lint_manifests list to the setup(..) method. The config object for the engine has the following keys: 'log_level' The minimum level at which to emit lint messages. Lint messages lower than this level are discarded. By default, this is set to INFO. Log levels in order of least to most severe are: DEBUG, INFO, WARNING, ERROR, CRITICAL 'do_pub_checks' Whether to perform checks which may only make sense for published packages. Set to True by default. 'pkglint.ext.*' Multiple keys, specifying modules to load which contain subclasses of pkg.lint.base.Checker. The value of this property should be fully specified python module name, assumed to be in $PYTHONPATH 'pkglint.exclude' A space-separated list of fully-specified Python modules, classes or function names which should be omitted from the set of checks performed. eg. 'pkg.lint.opensolaris.ActionChecker' or 'my.lint.module' or 'my.lint.module.ManifestChecker.crosscheck_paths' 'version.pattern' A version pattern, used when specifying a build number to lint against (-b). If not specified in the rcfile, this pattern is "*,5.11-0.", matching all components of the '5.11' build, with a branch prefix of '0.' 'info_classification_path' A path the file used to check the values of info.classification attributes in manifests. 'use_progress_tracker' Whether to use progress tracking. 'ignore_different_publishers' Whether to ignore differences in publisher when comparing package FMRIs. The engine has support for a "/* LINTED */"-like functionality, see the comment for .execute()cCsd|_d|_d|_d|_g|_g|_d|_ti d|_ ||_ |g|_ t |_t |_|i|d||_|dj o ||_nd|_t|_|i|_d|_d|_g|_g|_d|_d|_g|_d|_dS(sCreates a lint engine a given pkg.lint.log.LogFormatter. 'verbose' overrides any log_level settings in the config file to DEBUG 'config_file' specifies a path to a pkglintrc configuration file 'use_tracker' overrides any pkglintrc settings to either explicitly enable or disable the use of a tracker, set to None, we don't override the config file setting.s *,5.11-0.RtverboseiN(R0tbasedirRGRRtcheckerstexcluded_checkersR8RRRtenginetlogsR*t do_pub_checkst ignore_pubst load_configtconft use_trackert tracker_phaseRtin_setupt get_trackert ref_imaget lint_imaget lint_uristref_urist ref_api_instt lint_api_insttlint_manifeststmf_cache(Rt formatterRRt config_fileR\((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyR$s4                      c CsyW|iid|t|ddgdtiti||\}}||fSWn*tt fj o}ti |nXdS(sDynamically loads a given checker module, returning new instances of the checker classes the module declares, assuming they haven't been excluded by the config object.sLoading module %siN( Rtdebugt __import__R0tbaset get_checkerstsystmodulestKeyErrort ImportErrort LintException(RR?tconfigRTtexcludedterr((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyt_load_checker_modulefscCst}x|iD]}|i|jo+ttdh|id6|d6n|i|it}xj|i|iD]X\}}||jo2ttdh|id6|d6|d6n|i|q~WqWdS( sUEnsure that the engine has unique names for all of the loaded checks.s>loading extensions: duplicate checker name %(name)s: %(class)sR?tclasssPloading extension %(checker)s: duplicate pkglint_id %(pkglint_id)s in %(method)stcheckert pkglint_idtmethodN(tsetRTR?R RROtincluded_checkstexcluded_checks(Rt unique_namesRxtunique_methodsRzRy((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyt_unique_checkersts(         c Csytiiid|i}Wn*tiiij o}t|nXg}y9|idd}|djo d}n |i}Wnt i j onXy|idd|_ Wnt i j onXx|i dD]\}}d|jo||jo?|i ||\}} |ii||ii| qny<|i ||\}} |ii||ii| Wqtij o"}ttdtqXqqW|i|o!xG|iD]} d| _qWn*x&|iD]} |idd | _qWy|idd |_Wnt i j onXy%|idd id j|_Wnt i j onXy%|idd id j|_Wnt i j onX|S(s]Loads configuration from supplied config file, allowing a verbosity override.RiRspkglint.excludetsversion.patterns pkglint.exts/Error parsing config value for %(key)s: %(err)stDEBUGt log_levelRXtuse_progress_trackerttruetignore_different_publishersN(RtlintRst PkglintConfigtPkglintConfigExceptionR RPR0Rt ConfigParsert NoOptionErrorRtitemsRvRUtextendRTRlRrRtlocalsRRWtlevelt getbooleanRXtlowerR\RY( RRsRRR[RutexclRBtvalueRTtexcludetlint_log((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyRZsz                c Cs||_||_||_|iidt||_||_t|_t |i d||_ | o| ot t dn| o$|p|ot t dn|otii||_ytii|id|_tii|ioQ|i|i|_|io.|o'|ii|iit dqTn|i o&|o|i|i|i|_n|io6|id|_|i i|i|i|inWn1tj o%}t t dt |nXytii|id |_!tii|i!oQ|i|i!|_"|i"o.|o'|ii|iit d qn|i" oG|o@|ip|pt d n|i|i!|i|_"n|i"o6|id|_|i i|i"|i|inWn1tj o%}t t d t |nX|i"p|ipt t d |qxnx|i#D]}|i$|qW|ii%t&|_dS(sStarts a pkglint session, creates our image, pulls manifests, etc. from servers if necessary. 'cache' An area where we create images to access repos for both reference and linting purposes 'lint_manifests' An array of paths to manifests for linting 'ref_uris' A list of repositories which will be added to the image used as a reference for linting 'lint_uris' A list of repositories which will be added to th image we want to lint 'pattern' A regexp to match the packages we want to lint, if empty, we match everything. Note that this is only applied when searching for packages to lint: we lint against all packages for a given release in the reference repository (if configured) 'release' A release value that narrows the set of packages we lint with. This affects both the packages presented for linting as well as the packages in the repository we are linting against. If release if set to None, we lint with and against the latest available packages in the repositories.RBRsHEither a cache directory, or some local manifest files must be provided.sKA cache directory must be provided if using reference or lint repositories.Ras)Ignoring -l option, existing image found.isUnable to create lint image: %sR`s)Ignoring -r option, existing image found.s$No lint image or manifests provided.s$Unable to create reference image: %ss,Unable to access any pkglint images under %sN('RcRbRftsortt_manifest_sort_keyRGRR*R^R RRgR RtostpathtabspathRStjoinRatexistst _get_imageReR8tflushRtinfot _create_imageR]RDR_RRR`RdRTtstartupt lint_doneR( RRfRcRbtcacheRGRRuRx((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pytsetups                          c Cs>g}g}d}x|iD]}}|t|i}t|tio|i|qt|tio|i|qtt dt |qW|i i |i it d|x$|iD]}|i|||qWx?|i|id|id|iD]}|i|||qW|i i dS(sRun the checks that have been configured for this engine. We run checks on all lint_manifests as well as all manifests in a configured lint repository that match both our pattern and release (if they have been configured). We allow for pkg.linted=True and pkg.linted.=True, where is a substring of a pkglint id to skip logging errors for that action or manifest. As much of the pkg.linted functionality as possible is handled by the logging system, in combination with the engine calling advise_loggers() as appropriate, however some ManifestChecker methods may still need to use engine.linted() or .advise_loggers() manually when iterating over manifest actions in order to properly respect pkg.linted attributes.isT%s does not subclass a known Checker subclass intended for use by pkglint extensionss Total number of checks found: %sRGRN(RTR3R|t isinstanceRltManifestCheckertappendt ActionCheckerR RRR8RRRjRft_check_manifestt gen_manifestsReRGR(Rtmanifest_checkst action_checksRLRxRHRN((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pytexecute`s2        ccs|pdS|i}|io |i}n |i}|i|ii|||x,|ii||D]}|i|VqmWdS(sA generator to return package manifests for a given image. With a given pattern, it narrows the set of manifests returned to match that pattern. With the given 'release' number, it searches for manifests for that release using "@" where is set in pkglintrc and and are the keyword arguments to this method. N( R_R^tLINT_PHASETYPE_SETUPtLINT_PHASETYPE_EXECUTEtlint_next_phaseRgRMRItlint_add_progress(RR7RGRR8tpttm((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyRs       iicsD|idpd|}ndfdfd}|o7iptitdn|i||SxiD]y}|}|ijo!t|i|di o|St |i|jo|S|ii |jo|SqW|i ||}|o|S|i||S(sUReturns the first available manifest for a given package name, searching hierarchically in the lint manifests, the lint_repo or the ref_repo for that single package. By default, we search for an exact match on the provided pkg_name, throwing a LintEngineException if we get more than one match for the supplied pkg_name. When search_type is LintEngine.LATEST_SUCCESSOR, we return the most recent successor of the provided package, using the lint_fmri_successor() method defined in this module. If 'reference' is True, only search for the package using the reference image. If no reference image has been configured, this raises a pkg.lint.base.LintException. spkg:/spkg:/%scSsytii|}|SWnbtiij oPy tii|dd}|SWqtd|}ti|qXnXdS(s(builds a pkg.fmri.PkgFmri from a string.t build_releases5.11s unable to construct fmri from %sN(RR-R.t IllegalFmriRRlRr(RJR-tmsg((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyt build_fmris  c sYd|jp d|jotitd|nd|jo'iod|iif}ng}xI|itiii i d|gdt dt D]}|i |d qWg}x!|D]}|i |i qWt|d jo |d St|d jodSttd h|d 6t|d 6di|d6dS(s.Retrieve an fmri string that matches pkg_name.R t?sinvalid pkg name %st@s%s@%s%sR!R"t return_fmrisiisBget_fmri(pattern) %(pattern)s matched %(count)s packages: %(pkgs)sRGRLt tpkgsN(RlRrRRRR+RR&R'R(R/R*Rtget_fmriR3R0RR(R7RJtfmrisR=t fmri_list(R(s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyRs6      cs|pdS|}|ijobd|i}ii||}|pdS|io|i|iijo|Sq|Snyii||}|SWnetj oYd}||}|o|i t ii |}nii ||||SXdS(sfFetch a manifest for the given package name using the ImageInterface provided.spkg:/%sN( R0tLATEST_SUCCESSORtget_nameRgRKt publisherR-RPRpR4RR.RO(R7RJR:t search_fmriR?RHR-(RRR(s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyt mf_from_images0   s+No reference repository has been configuredRY( t startswithRdRlRrRRfRR1R-RYRRRe(RRJR:t referenceRRHR((RRRs5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyR4s4 ((      c Csti}|i}d}yOtiii|t|dt }|i |jo d}n|i dt Wn?t j o3}ttdh|d6t|d6nXti||S(sXReturn a pkg.client.api.ImageInterface for the provided image directory.t immediates*Unable to get image at %(dir)s: %(reason)stdirtreasonN(RtgetcwdR_R0RR&R'R(tCLIENT_API_VERSIONtPKG_CLIENT_NAMEtroottrefreshR*t ExceptionR RRtchdir(Rt image_dirtcdirR8R7Ru((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyR=s"       cCs7t|djottdn|i}t}t}|ii|ii td|t i i |di p+dt i tii|d|d css"x|]}t|iVqWdS(N(RR-(t.0ts((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pys 's Rtdependt incorporationR-Rittargettold_mfstwarn_on_obsoletetlegacyRYN(RRR4RRPR0RlRrRR-RRRtgen_actions_by_typetattrstfollow_renamesR1RY( RRJRRRR t leaf_nametleaf_mfRHtold_mftdeptfollow((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyR sR       %         cCsd|}d}|o!||ijo|i|}n|o||jo||}n|o&t|to|Sdi|Sny1|iid|}|o|iddSWnti j odSXdS(sReturns a string value of a given pkglint parameter, intended for use by pkglint Checker objects to provide hints as to how particular checks should be run. Keys are searched for first in the action, if provided, then as manifest attributes, finally falling back to the pkglintrc config file. The return value is a space-separated string of parameters. When searching for keys in the manifest or action, we prepend "pkg.lint" to the key name to ensure that we play in our own namespace and don't clash with other manifest or action attrs. s pkg.lint.%sRRs N( R0R Rt basestringRR[RPtreplaceRR(RRBRRNt param_keytval((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyt get_paramFs  cCsf||jottd|nx8|idD]'}|iidd|jo|Sq7WdS(sReturn the AttributeAction that sets a given attribute in a manifest. This is available for clients, particularly ManifestCheckers that need to see whether a lint flag has been set on a given 'set' action. s%s is not set in manifestR{R?RN(RpRR R RPR0(RtattrRNR((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pytget_attr_actionhs  c CsZt}y"tid|d|d|}Wn+tij o}|i|ddnX|S(sDetermine whether pkg.linted.* flags are present on the action and/or manifest passed as arguments. If lint_id is set, we look for pkg.linted. attributes as well.RRNtlint_idRs pkglint001.6(RRltlintedtDuplicateLintedAttrExceptionR(RRRNRtretRu((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyRws N( RR R RR0RRvRRZRRRtEXACTRR4RRRRRRjRRRRRRR_R RRR(((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyRQs>D A   O  /  #    M" cCs| o|i|ijotS|i}|i}||jotS|iptS|io|io|ii|iijotS|ii|iijotS|ii|iijotS|ii|iijotS|ii|iijotS|ii|iijotS|pF|ii }|ii }||jotS||jotSq{ntS(snGiven two FMRIs, determine if new_fmri is a successor of old_fmri. This differs from pkg.fmri.is_successor() in that it treats un-versioned FMRIs as being newer than versioned FMRIs of the same package name, and un-timestamped packages as being newer than versioned FMRIs of the same package name and version. For published packages, where the version and pkg names are identical, but the publisher differs, it also treats the new package as being a successor of the old. If ignore_pubs is set, any differences in publishers between the provided FMRIs are ignored. if ignore_timestamps is set, timestamps are not used as a basis for comparison between new and old FMRIs. We use this when looking for dependencies, or when comparing FMRIs presented in manifests for linting against those present in an existing repository (where, eg. a new timestamp would be supplied to a package during the import process and the timestamp would not necessarily be in the manifest file presented for linting) ( RRRt has_versionR*RRRRt get_timestamp(tnewtoldRYR$tnew_nametold_nametnew_tstold_ts((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyR1s:       cCs|io|iS|idS(sThe lint engine uses the FMRI of a package to deterine the order in which to iterate over manifests. This is done using the 'key' attribute to the Python sort() and sorted() methods.spkg.fmri(R-RP(RH((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyRs ("tpkg.client.apiRtpkg.client.progressR&Rt pkg.lint.baseRRltpkg.lint.configtpkg.fmritpkg.client.api_errorsRt pkg.versionRRRRRRRnRRRtglobal_settingst client_nameRRR R tobjectRQR*R1R(((s5/usr/lib/python2.6/vendor-packages/pkg/lint/engine.pyts0           @