oelint-adv


Nameoelint-adv JSON
Version 5.3.0 PyPI version JSON
download
home_pagehttps://github.com/priv-kweihmann/oelint-adv
SummaryAdvanced bitbake-recipe linter
upload_time2024-04-20 08:06:27
maintainerNone
docs_urlNone
authorKonrad Weihmann
requires_python>=3.8
licenseNone
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            # oelint-adv

![Build status](https://github.com/priv-kweihmann/oelint-adv/workflows/Python%20package/badge.svg)
[![PyPI version](https://badge.fury.io/py/oelint-adv.svg)](https://badge.fury.io/py/oelint-adv)
[![Python version](https://img.shields.io/pypi/pyversions/oelint-adv)](https://img.shields.io/pypi/pyversions/oelint-adv)
[![Downloads](https://img.shields.io/pypi/dm/oelint-adv)](https://img.shields.io/pypi/dm/oelint-adv)

Advanced oelint

## Purpose

Based on the [OpenEmbedded Styleguide](https://www.openembedded.org/wiki/Styleguide) and work done by [oe-stylize-tool](https://github.com/openembedded/meta-openembedded/blob/master/contrib/oe-stylize.py) this module offers a (nearly) complete linter for bitbake-recipes.

The tool should help anyone working with YOCTO/OpenEmbedded to write more clean, less 'magical' recipes, without the need to know all the internals of your used poky/OpenEmbedded version.

It could also be used as part of a CI to avoid hard to debug issues slipping to your code base - be sure to checkout [rulefile](#defining-a-ruleset) for that use case.

As every linter this tool is sometimes extra picky, but for the good of it, not just to bug people.
Especially for novice users it might be a help to avoid the most common pitfalls of bitbake recipes.

The tool does handle includes/requires automatically, so you don't have to pass them via CLI.

**NOTE**: .bbappend-files have to be passed via CLI - these are NOT gathered automatically.

## Install

With pip (**recommended**)

```shell
pip3 install oelint_adv
```

from source

```shell
git clone https://github.com/priv-kweihmann/oelint-adv
cd oelint-adv
python3 setup.py install # might require sudo/root permissions
```

**NOTE** if you install from source, you'll have to provide all matching
required python libraries on your own. See [requirements.txt](requirements.txt) for details

## Usage

```shell
usage: oelint-adv [-h] [--suppress SUPPRESS] [--output OUTPUT] [--fix] [--nobackup] [--addrules ADDRULES [ADDRULES ...]]
                  [--customrules CUSTOMRULES [CUSTOMRULES ...]] [--rulefile RULEFILE] [--jobs JOBS] [--color] [--quiet] [--noinfo]
                  [--nowarn] [--relpaths] [--noid] [--messageformat MESSAGEFORMAT] [--constantmods CONSTANTMODS [CONSTANTMODS ...]] [--print-rulefile] [--exit-zero]
                  [--version]
                  [files ...]

Advanced OELint - Check bitbake recipes against OECore styleguide

positional arguments:
  files                 File to parse

options:
  -h, --help            show this help message and exit
  --suppress SUPPRESS   Rules to suppress
  --output OUTPUT       Where to flush the findings (default: stderr)
  --fix                 Automatically try to fix the issues
  --nobackup            Don't create backup file when auto fixing
  --addrules ADDRULES [ADDRULES ...]
                        Additional non-default rulessets to add
  --customrules CUSTOMRULES [CUSTOMRULES ...]
                        Additional directories to parse for rulessets
  --rulefile RULEFILE   Rulefile
  --jobs JOBS           Number of jobs to run (default all cores)
  --color               Add color to the output based on the severity
  --quiet               Print findings only
  --noinfo              Don't print information level findings
  --nowarn              Don't print warning level findings
  --relpaths            Show relative paths instead of absolute paths in results
  --noid                Don't show the error-ID in the output
  --messageformat MESSAGEFORMAT
                        Format of message output
  --constantmods CONSTANTMODS [CONSTANTMODS ...]
                        Modifications to the constant db.
                        prefix with: + - to add to DB, - - to remove from DB, None - to override DB
  --print-rulefile      Print loaded rules as a rulefile and exit
  --release             Run against a specific Yocto release (default: latest)
  --exit-zero           Always return a 0 (non-error) status code, even if lint errors are found
  --version             show program's version number and exit
```

## Output

Will be [file]:[line]:[severity]:[id]:[message].
To change the default message format, please see [Output message format](#output-message-format) section.

Example:

```shell
/disk/meta-some/cppcheck-native/cppcheck.inc:26:error:oelint.task.nomkdir:'mkdir' shall not be used in do_install. Use 'install'
/disk/meta-some/cppcheck-native/cppcheck-native_1.87.bb:0:error:oelint.var.mandatoryvar.SECTION:Variable 'SECTION' should be set
/disk/meta-some/cppcheck-native/cppcheck.inc:1:warning:oelint.vars.summary80chars:'SUMMARY' should not be longer than 80 characters
/disk/meta-some/cppcheck-native/cppcheck.inc:4:warning:oelint.vars.homepageprefix:'HOMEPAGE' should start with 'http://' or 'https://'
/disk/meta-some/cppcheck-native/cppcheck.inc:28:warning:oelint.spaces.lineend:Line shall not end with a space
/disk/meta-some/cppcheck-native/cppcheck-native_1.87.bb:0:error:oelint.var.mandatoryvar.AUTHOR:Variable 'AUTHOR' should be set
/disk/meta-some/cppcheck-native/cppcheck.inc:26:error:oelint.task.nocopy:'cp' shall not be used in do_install. Use 'install'
/disk/meta-some/cppcheck-native/cppcheck.inc:12:warning:oelint.var.order.DEPENDS:'DEPENDS' should be placed before 'inherit'
```

## Apply automatic fixing

Some of the rules are capable of fixing the issues found automatically.
This will be done if you pass **--fix** as a startup parameter.

As long as you don't pass **--nobackup** a backup copy (filename + .bak) will be created for all files fixed.

## Available rules

Rules marked with **[F]** are able to perform automatic fixing
Rules marked with **[S]** can have multiple sub-IDs

* [oelint.append.protvars](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.append.protvars.md) - Variables that shouldn't be set in a bbappend **[S]**
* [oelint.bbclass.underscores](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.bbclass.underscores.md) - bbclass filenames shall not contain dashes
* [oelint.exportfunction.dash](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.exportfunction.dash.md) - EXPORT_FUNCTIONS shall not contain dashes
* [oelint.file.inactiveupstreamdetails](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.inactiveupstreamdetails.md) - Patches with Upstream-Status: Inactive-Upstream require more details
* [oelint.file.inappropriatemsg](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.inappropriatemsg.md) - Patches with Upstream-Status: Inappropriate should provide a valid reasoning
* [oelint.file.includenotfound](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.includenotfound.md) - File to be included not found
* [oelint.file.includerelpath](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.includerelpath.md) - Require should be used instead of include
* [oelint.file.inlinesuppress_na](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.inlinesuppress_na.md) - A not applicable inline suppression has been found
* [oelint.file.nospaces](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.nospaces.md) - Path to file should not contain spaces
* [oelint.file.patchsignedoff](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.patchsignedoff.md) - Patches should contain a Signed-Of-By entry
* [oelint.file.requireinclude](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.requireinclude.md) - Require should be used instead of include
* [oelint.file.requirenotfound](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.requirenotfound.md) - File to be required not found
* [oelint.file.underscores](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.underscores.md) - Checks the correct usage of underscores in filename
* [oelint.file.upstreamstatus](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.upstreamstatus.md) - Patches should contain a Upstream-Status entry
* [oelint.func.specific](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.func.specific.md) - Function is specific to an unknown identifier
* [oelint.newline.consecutive](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.newline.consecutive.md) - Consecutive blank lines should be avoided **[F]**
* [oelint.newline.eof](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.newline.eof.md) - File shall end on a newline **[F]**
* [oelint.spaces.emptyline](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.spaces.emptyline.md) - Empty line should not contain spaces or tabs **[F]**
* [oelint.spaces.linebeginning](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.spaces.linebeginning.md) - No space at a line beginning **[F]**
* [oelint.spaces.linecont](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.spaces.linecont.md) - Safe line continuation **[F]**
* [oelint.spaces.lineend](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.spaces.lineend.md) - No spaces at line end **[F]**
* [oelint.tabs.notabs](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.tabs.notabs.md) - No tabs allowed **[F]**
* [oelint.task.addnotaskbody](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.addnotaskbody.md) - Task added by addtask cannot be found
* [oelint.task.customorder](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.customorder.md) - order of custom tasks added via addtask
* [oelint.task.dash](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.dash.md) - Functions and related statements shall not contain dashes
* [oelint.task.docstrings](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.docstrings.md) - Custom tasks should have docstrings
* [oelint.task.heredocs](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.heredocs.md) - Usage of heredocs should be avoided. Use files instead
* [oelint.task.multifragments](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.multifragments.md) - Multiple fragments of the same function in the same file should be merged
* [oelint.task.noanonpython](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.noanonpython.md) - Avoid anonymous python functions
* [oelint.task.nocopy](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.nocopy.md) - No cp usage in do_install
* [oelint.task.nomkdir](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.nomkdir.md) - No mkdir usage in do_install
* [oelint.task.nopythonprefix](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.nopythonprefix.md) - Tasks containing shell code should NOT be prefixed with 'python' in function header
* [oelint.task.order](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.order.md) - Order of tasks **[S]**
* [oelint.task.pythonprefix](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.pythonprefix.md) - Tasks containing python code should be prefixed with 'python' in function header
* [oelint.var.addpylib](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.addpylib.md) - addpylib is only valid in .conf files
* [oelint.var.bbclassextend](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.bbclassextend.md) - Use BBCLASSEXTEND when possible
* [oelint.var.filesoverride](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.filesoverride.md) - FILES:*(FILES_*) variables should not be overridden
* [oelint.var.improperinherit](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.improperinherit.md) - Warn about improperly named inherits
* [oelint.var.inherit](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.inherit.md) - Check the correct usage of inherit and inherit_defer (scarthgap+)
* [oelint.var.inheritdevtool](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.inheritdevtool.md) - inherit_defer is recommended for native and nativesdk class **[S]** (scarthgap+)
* [oelint.var.licenseremotefile](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.licenseremotefile.md) - License shall be a file in remote source not a local file
* [oelint.var.mandatoryvar](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.mandatoryvar.md) - Check for mandatory variables **[S]**
* [oelint.var.multiinclude](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.multiinclude.md) - Warn on including the same file more than once
* [oelint.var.multiinherit](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.multiinherit.md) - Warn on inherit the same file more than once
* [oelint.var.nativefilename](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.nativefilename.md) - Native only recipes should be named.md -native
* [oelint.var.nativesdkfilename](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.nativesdkfilename.md) - NativeSDK only recipes should be named nativesdk-
* [oelint.var.order](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.order.md) - Variable order **[S]**
* [oelint.var.override](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.override.md) - Check if include/append is overriding a variable
* [oelint.var.rootfspostcmd](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.rootfspostcmd.md) - ROOTFS_POSTPROCESS_COMMAND should not have trailing blanks
* [oelint.var.srcuriwildcard](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.srcuriwildcard.md) - 'SRC_URI' should not contain any wildcards
* [oelint.var.suggestedvar](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.suggestedvar.md) - Notice on suggested variables **[S]**
* [oelint.vars.appendop](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.appendop.md) - Use ':append(_append)' instead of ' += '
* [oelint.vars.autorev](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.autorev.md) - The usage of 'AUTOREV' for SRCREV leads to not reproducible builds
* [oelint.vars.bbvars](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.bbvars.md) - Variables that shouldn't be altered in recipe scope **[S]**
* [oelint.vars.bugtrackerisurl](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.bugtrackerisurl.md) - BUGTRACKER should be an URL
* [oelint.vars.dependsappend](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.dependsappend.md) - DEPENDS should only be appended, not overwritten
* [oelint.vars.dependsclass](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.dependsclass.md) - DEPENDS should use the correct class variants
* [oelint.vars.dependsordered](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.dependsordered.md) - RDEPENDS entries should be ordered alphabetically
* [oelint.vars.descriptionsame](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.descriptionsame.md) - 'DESCRIPTION' is the same a 'SUMMARY'.md) - it can be removed then
* [oelint.vars.descriptiontoobrief](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.descriptiontoobrief.md) - 'DESCRIPTION' is the shorter than 'SUMMARY'
* [oelint.vars.doublemodify](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.doublemodify.md) - Multiple modifiers of append/prepend/remove/+= found in one operation
* [oelint.vars.downloadfilename](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.downloadfilename.md) - Fetcher does create a download artifact without 'PV' in the filename
* [oelint.vars.duplicate](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.duplicate.md) - No duplicates in DEPENDS and RDEPENDS
* [oelint.vars.dusageinpkgfuncs](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.dusageinpkgfuncs.md) - use \$D instead of \$\{D\} in pkg functions **[F]**
* [oelint.vars.fileextrapaths](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.fileextrapaths.md) - 'FILESEXTRAPATHS' shouldn't be used in a bb file
* [oelint.vars.fileextrapathsop](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.fileextrapathsop.md) - 'FILESEXTRAPATHS' should only be used in combination with ' := '
* [oelint.vars.filessetting](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.filessetting.md) - unnecessary FILES settings
* [oelint.vars.homepageping](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.homepageping.md) - 'HOMEPAGE' isn't reachable
* [oelint.vars.homepageprefix](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.homepageprefix.md) - HOMEPAGE should begin with https:// or http://
* [oelint.vars.inconspaces](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.inconspaces.md) - Inconsistent use of spaces on append operation
* [oelint.vars.insaneskip](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.insaneskip.md) - INSANE_SKIP should be avoided at any cost
* [oelint.vars.licensesdpx](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.licensesdpx.md) - Check for correct SPDX syntax in licenses
* [oelint.vars.licfileprefix](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.licfileprefix.md) - Unnecessary prefix to LIC_FILES_CHKSUM detected **[F]**
* [oelint.vars.listappend](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.listappend.md) - Proper append/prepend to lists **[F]**
* [oelint.vars.mispell.unknown](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.mispell.unknown.md) - Variable is not known from CONSTANTS, typo is unlikely
* [oelint.vars.mispell](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.mispell.md) - Possible typo detected
* [oelint.vars.multilineident](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.multilineident.md) - On a multiline assignment, line indent is desirable
* [oelint.vars.notneededspace](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.notneededspace.md) - Space at the beginning of the var is not needed **[F]**
* [oelint.vars.notrailingslash](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.notrailingslash.md) - Variable shall not end on a slash
* [oelint.vars.overrideappend](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.overrideappend.md) - Check correct order of append/prepend on variables with override syntax
* [oelint.vars.pathhardcode](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.pathhardcode.md) - Warn about the usage of hardcoded paths **[S]**
* [oelint.vars.pbpusage](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.pbpusage.md) - \$\{BP\} should be used instead of \$\{P\} **[F]**
* [oelint.vars.pkgspecific](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.pkgspecific.md) - Variable is package-specific, but isn't set in that way **[S]**
* [oelint.vars.pnbpnusage](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.pnbpnusage.md) - \$\{BPN\} should be used instead of \$\{PN\} **[F]**
* [oelint.vars.pnusagediscouraged](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.pnusagediscouraged.md) - Variable shouldn't contain \$\{PN\} or \$\{BPN\}
* [oelint.vars.pythonpnusage](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.pythonpnusage.md) - python3 should be used instead of \$\{PYTHON_PN\} **[F]** (scarthgap+)
* [oelint.vars.sectionlowercase](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.sectionlowercase.md) - SECTION should be lowercase only **[F]**
* [oelint.vars.spacesassignment](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.spacesassignment.md) - ' = ' should be correct variable assignment
* [oelint.vars.specific](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.specific.md) - Variable is specific to an unknown identifier
* [oelint.vars.srcuriappend](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcuriappend.md) - Use SRC_URI:append(SRC_URI_append) otherwise this will override weak defaults by inherit
* [oelint.vars.srcurichecksum](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcurichecksum.md) - If SRC_URI has URLs pointing single file that is not from VCS, then checksusm is required
* [oelint.vars.srcuridomains](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcuridomains.md) - Recipe is pulling from different domains, this will likely cause issues
* [oelint.vars.srcurifile](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcurifile.md) - First item of SRC_URI should not be a file:// fetcher, if multiple fetcher are used
* [oelint.vars.srcurigittag](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcurigittag.md) - 'tag' in SRC_URI-options leads to not-reproducible builds
* [oelint.vars.srcurioptions](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcurioptions.md) - Unsupported fetcher or invalid options detected
* [oelint.vars.srcurisrcrevtag](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcurisrcrevtag.md) - 'tag' in SRC_URI and a SRCREV for the same component doesn't compute
* [oelint.vars.summary80chars](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.summary80chars.md) - SUMMARY should max. be 80 characters long
* [oelint.vars.summarylinebreaks](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.summarylinebreaks.md) - No line breaks in SUMMARY
* [oelint.vars.valuequoted](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.valuequoted.md) - Variable values should be properly quoted
* [oelint.vars.virtual](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.virtual.md) - no virtual/ items in RDEPENDS/RPROVIDES

### Non-default rulesets

To enable rulesets that are not part of the standard ruleset pass
**--addrules \<ruleset-name\>** to CLI.

These rules are sometimes contrary to OE-style-guide, so use them with caution.

#### jetm ruleset

To enable pass **--addrules jetm** to CLI.

Rules marked with **[F]** are able to perform automatic fixing.

* [oelint.jetm.vars.dependssingleline](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.jetm.vars.dependssingleline.md) - Each [R]DEPENDS entry should be put into a single line
  
### Writing your own additional rules

By passing `--customrules` via CLI you could add additional rules to be checked.
The argument should point to a directory - every class derived from `Rule` will be automatically loaded.
Please use the following as a template for your own:

```python
from oelint_adv.cls_rule import Rule


class FooMagicRule(Rule):
    def __init__(self):
        super().__init__(id="foocorp.foo.magic",
                         severity="error",
                         message="Too much foo happening here")

    def check(self, _file, stash):
        res = []
        items = stash.GetItemsFor(filename=_file)
        for i in items:
            if "Foo" in i.Raw:
                res += self.finding(i.Origin, i.InFileLine)
        return res

    # To provide automatic fixing capability
    # add the following optional function
    def fix(self, _file, stash):
        res = []
        items = stash.GetItemsFor(filename=_file)
        for i in items:
            if 'Foo' in i.Raw:
                # you have to replace the content of `RealRaw` and `Raw`
                # with the fixed content
                # `Raw` is the raw block with expanded inlines blocks
                # `RealRaw` is the raw block without any modifications
                #           this is what will be actually written to the file
                i.RealRaw = i.RealRaw.replace('Foo', 'Bar')
                i.Raw = i.Raw.replace('Foo', 'Bar')
                # Return the file name to signalize that fixes have been
                # applied
                res.append(_file)
        return res
```

For more details please see the function docstrings of the API.

You can find this example also in the development [source tree](https://github.com/priv-kweihmann/oelint-adv/tree/master/docs)

Additional real-life examples can be found in e.g. [meta-rubygems](https://github.com/priv-kweihmann/meta-rubygems/tree/master/files/lint/oelint-custom)

### Release constrained rules

Rules can be also configured to work on specific releases of YP only, if determined not to be applicable, the rules will
be skipped during the loading process and therefore won't show up if e.g. `--print-rulefile` is used

#### Rules working up to a certain release

```python
from oelint_adv.cls_rule import Rule


class FooMagicRule(Rule):
    def __init__(self):
        super().__init__(id="foocorp.foo.magic",
                         severity="error",
                         message="Too much foo happening here",
                         valid_till_release="kirkstone")
```

Would enable the rule, but only if `--release` is set to a YP release earlier than `kirkstone`

#### Rules working from a certain release

```python
from oelint_adv.cls_rule import Rule


class FooMagicRule(Rule):
    def __init__(self):
        super().__init__(id="foocorp.foo.magic",
                         severity="error",
                         message="Too much foo happening here",
                         valid_from_release="kirkstone")
```

Would enable the rule, but only if `--release` is set to a YP release later than `kirkstone` (including `kirkstone`)

#### Enable special settings per release

```python
from oelint_adv.cls_rule import Rule


class FooMagicRule(Rule):
    def __init__(self):
        super().__init__(id="foocorp.foo.magic",
                         severity="error",
                         message="Too much foo happening here")

    def check_release_range(self, release_range: List[str]) -> bool:
        if 'kirkstone' in release_range:
            self._we_are_running_on_kirkstone = True
            self.Appendix.append('kirkstone')
        return super().check_release_range(release_range)
```

Enables the special `Appendix` `kirkstone`, if `kirkstone` is part of the calculated `--release` list.

It also sets the variable `self._we_are_running_on_kirkstone`, which can be used as part of `check()` to
code special code paths.

## Defining a ruleset

If you pass the option `--rulefile` you could define the rules to be checked and their severity via a simple json file.

The rule file could look like this:

```json
{
  "<rule>": "<severity>"
}
```

to override the severity, or

```json
{
  "<rule>": ""
}
```

to keep the original severity.

### Example

```json
{
  "oelint.file.includenotfound": "",
  "oelint.file.requirenotfound": "warning"
}
```

would enable the two rules `oelint.file.includenotfound` and `oelint.file.requirenotfound`.
The severity of `oelint.file.includenotfound` will be the default of the tool, while `oelint.file.requirenotfound` will report `warning` instead of the original suggested severity.

### Adding additional constants

Please see [oelint-parser](https://github.com/priv-kweihmann/oelint-parser) for further details, how to add your own constants to the parser.

## Output message format

You can freely define a custom output format.
The following placeholder symbols will be automatically replaced

| name       | replaced by                |
| ---------- | -------------------------- |
| {path}     | path of the file           |
| {line}     | line of the finding        |
| {severity} | severity of the finding    |
| {id}       | error-ID of the finding    |
| {msg}      | description of the finding |
| {wikiurl}  | a link to the online wiki  |

## Configuration file

You can define your own global or project wide defaults for all CLI parameters with an ini-style configuration file.

In the following order files are probed

* file pointed to by environment variable `OELINT_CONFIG`
* file `.oelint.cfg` in current work directory
* file `.oelint.cfg` in your `HOME` directory

Explicitly passed options to CLI are always chosen over the defaults defined by the configuration file.

To skip the loading of any configuration file, set `OELINT_SKIP_CONFIG` to a non empty value in your environment.

### File format

```ini
[oelint]
# this will set the --nowarn parameter automatically
nowarn = True
# this will set A + B as suppress item
# use indent (tab) and line breaks for multiple items
suppress = 
  A
  B
# this will set messageformat parameter
messageformat = {severity}:{id}:{msg}
# will configure --release to dunfell
release=dunfell
```

You can find an example file [here](docs/.oelint.cfg.example)

## Inline suppression

You can suppress one or more checks on a line by line basis

```bitbake
# nooelint: <id>[,<id>,...]
```

suppresses all the specified IDs for the next line.
Multiple IDs can be separated by commas.

### Example

```bitbake
# nooelint: oelint.vars.insaneskip
INSANE_SKIP:${PN} = "foo"
```

will not warn about the usage of `INSANE_SKIP`.

## Configure your custom machine or distro settings

You can let `oelint-adv` know about your custom `MACHINE` and `DISTRO` overrides, so they won't produce any findings, when
used in your setup.

### Create a layer specific oelint configuration file

Copy over the template this [file](docs/.oelint.cfg.custom-layer) to the root of your layer

```shell
LAYER_PATH=<path to your layer>
cp docs/.oelint.cfg.custom-layer $LAYER_PATH/.oelint.cfg
```

### Create the known MACHINE and DISTRO settings

Source your bitbake build directory and run the following commands (\*\*) (\*\*\*)

```shell
LAYER_PATH=<path to your layer>
bitbake-getvar --quiet --value MACHINEOVERRIDES | tr ':' '\n' | jq -Rn  '{replacements:{ machines: [inputs]}}' > $LAYER_PATH/.oelint-custom-machines.json
bitbake-getvar --quiet --value DISTROOVERRIDES | tr ':' '\n' | jq -Rn  '{replacements:{ distros: [inputs]}}' > $LAYER_PATH/.oelint-custom-distros.json
```

(**) you'll need to have `jq` installed on your local machine.

(***) `bitbake-getvar` command is available since `kirkstone` release. For older release you can use `bitbake core-image-minimal -e | grep ^MACHINEOVERRIDES` resp. `bitbake core-image-minimal -e | grep ^DISTROOVERRIDES` and pass them into the rest of the pipe.

## vscode extension

Find the extension in the [marketplace](https://marketplace.visualstudio.com/items?itemName=kweihmann.oelint-vscode), or search for `oelint-vscode`.

## Vim / NeoVim integration

Integration for Vim / NeoVim is provided by [ale](https://github.com/dense-analysis/ale) or [nvim-lint](https://github.com/mfussenegger/nvim-lint).

## Jenkins integration

Jenkins integration is provided by [warnings-ng](https://plugins.jenkins.io/warnings-ng/).

## Use as a library

To use the linter as part of calling application do

```python
from oelint_adv.core import create_lib_arguments, run

args = create_lib_arguments(['file to check', 'another file to check']])

# check the docstring of create_lib_arguments for more options

results = run(args)

# the results will be a List[Tuple[Tuple[str, int], str]]
# each item is
#  [0] - 'path to the finding', 'line of the finding'
#  [1] - 'message'
```

The caller is responsible for appropriate exception handling

## Missing anything?

You think there's something missing, wrong, 'improvable'...
Just file an issue to get in contact.

## Contribute

Any sort of ideas, pull requests, bug reports, reports of false positives are welcome.
This project is open to anyone - no pitfalls or legal inconveniences.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/priv-kweihmann/oelint-adv",
    "name": "oelint-adv",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": null,
    "author": "Konrad Weihmann",
    "author_email": "kweihmann@outlook.com",
    "download_url": "https://files.pythonhosted.org/packages/9e/b5/9c26296298aec4a4e5722e9719347016966bf67de7211f0520677274c755/oelint_adv-5.3.0.tar.gz",
    "platform": null,
    "description": "# oelint-adv\n\n![Build status](https://github.com/priv-kweihmann/oelint-adv/workflows/Python%20package/badge.svg)\n[![PyPI version](https://badge.fury.io/py/oelint-adv.svg)](https://badge.fury.io/py/oelint-adv)\n[![Python version](https://img.shields.io/pypi/pyversions/oelint-adv)](https://img.shields.io/pypi/pyversions/oelint-adv)\n[![Downloads](https://img.shields.io/pypi/dm/oelint-adv)](https://img.shields.io/pypi/dm/oelint-adv)\n\nAdvanced oelint\n\n## Purpose\n\nBased on the [OpenEmbedded Styleguide](https://www.openembedded.org/wiki/Styleguide) and work done by [oe-stylize-tool](https://github.com/openembedded/meta-openembedded/blob/master/contrib/oe-stylize.py) this module offers a (nearly) complete linter for bitbake-recipes.\n\nThe tool should help anyone working with YOCTO/OpenEmbedded to write more clean, less 'magical' recipes, without the need to know all the internals of your used poky/OpenEmbedded version.\n\nIt could also be used as part of a CI to avoid hard to debug issues slipping to your code base - be sure to checkout [rulefile](#defining-a-ruleset) for that use case.\n\nAs every linter this tool is sometimes extra picky, but for the good of it, not just to bug people.\nEspecially for novice users it might be a help to avoid the most common pitfalls of bitbake recipes.\n\nThe tool does handle includes/requires automatically, so you don't have to pass them via CLI.\n\n**NOTE**: .bbappend-files have to be passed via CLI - these are NOT gathered automatically.\n\n## Install\n\nWith pip (**recommended**)\n\n```shell\npip3 install oelint_adv\n```\n\nfrom source\n\n```shell\ngit clone https://github.com/priv-kweihmann/oelint-adv\ncd oelint-adv\npython3 setup.py install # might require sudo/root permissions\n```\n\n**NOTE** if you install from source, you'll have to provide all matching\nrequired python libraries on your own. See [requirements.txt](requirements.txt) for details\n\n## Usage\n\n```shell\nusage: oelint-adv [-h] [--suppress SUPPRESS] [--output OUTPUT] [--fix] [--nobackup] [--addrules ADDRULES [ADDRULES ...]]\n                  [--customrules CUSTOMRULES [CUSTOMRULES ...]] [--rulefile RULEFILE] [--jobs JOBS] [--color] [--quiet] [--noinfo]\n                  [--nowarn] [--relpaths] [--noid] [--messageformat MESSAGEFORMAT] [--constantmods CONSTANTMODS [CONSTANTMODS ...]] [--print-rulefile] [--exit-zero]\n                  [--version]\n                  [files ...]\n\nAdvanced OELint - Check bitbake recipes against OECore styleguide\n\npositional arguments:\n  files                 File to parse\n\noptions:\n  -h, --help            show this help message and exit\n  --suppress SUPPRESS   Rules to suppress\n  --output OUTPUT       Where to flush the findings (default: stderr)\n  --fix                 Automatically try to fix the issues\n  --nobackup            Don't create backup file when auto fixing\n  --addrules ADDRULES [ADDRULES ...]\n                        Additional non-default rulessets to add\n  --customrules CUSTOMRULES [CUSTOMRULES ...]\n                        Additional directories to parse for rulessets\n  --rulefile RULEFILE   Rulefile\n  --jobs JOBS           Number of jobs to run (default all cores)\n  --color               Add color to the output based on the severity\n  --quiet               Print findings only\n  --noinfo              Don't print information level findings\n  --nowarn              Don't print warning level findings\n  --relpaths            Show relative paths instead of absolute paths in results\n  --noid                Don't show the error-ID in the output\n  --messageformat MESSAGEFORMAT\n                        Format of message output\n  --constantmods CONSTANTMODS [CONSTANTMODS ...]\n                        Modifications to the constant db.\n                        prefix with: + - to add to DB, - - to remove from DB, None - to override DB\n  --print-rulefile      Print loaded rules as a rulefile and exit\n  --release             Run against a specific Yocto release (default: latest)\n  --exit-zero           Always return a 0 (non-error) status code, even if lint errors are found\n  --version             show program's version number and exit\n```\n\n## Output\n\nWill be [file]:[line]:[severity]:[id]:[message].\nTo change the default message format, please see [Output message format](#output-message-format) section.\n\nExample:\n\n```shell\n/disk/meta-some/cppcheck-native/cppcheck.inc:26:error:oelint.task.nomkdir:'mkdir' shall not be used in do_install. Use 'install'\n/disk/meta-some/cppcheck-native/cppcheck-native_1.87.bb:0:error:oelint.var.mandatoryvar.SECTION:Variable 'SECTION' should be set\n/disk/meta-some/cppcheck-native/cppcheck.inc:1:warning:oelint.vars.summary80chars:'SUMMARY' should not be longer than 80 characters\n/disk/meta-some/cppcheck-native/cppcheck.inc:4:warning:oelint.vars.homepageprefix:'HOMEPAGE' should start with 'http://' or 'https://'\n/disk/meta-some/cppcheck-native/cppcheck.inc:28:warning:oelint.spaces.lineend:Line shall not end with a space\n/disk/meta-some/cppcheck-native/cppcheck-native_1.87.bb:0:error:oelint.var.mandatoryvar.AUTHOR:Variable 'AUTHOR' should be set\n/disk/meta-some/cppcheck-native/cppcheck.inc:26:error:oelint.task.nocopy:'cp' shall not be used in do_install. Use 'install'\n/disk/meta-some/cppcheck-native/cppcheck.inc:12:warning:oelint.var.order.DEPENDS:'DEPENDS' should be placed before 'inherit'\n```\n\n## Apply automatic fixing\n\nSome of the rules are capable of fixing the issues found automatically.\nThis will be done if you pass **--fix** as a startup parameter.\n\nAs long as you don't pass **--nobackup** a backup copy (filename + .bak) will be created for all files fixed.\n\n## Available rules\n\nRules marked with **[F]** are able to perform automatic fixing\nRules marked with **[S]** can have multiple sub-IDs\n\n* [oelint.append.protvars](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.append.protvars.md) - Variables that shouldn't be set in a bbappend **[S]**\n* [oelint.bbclass.underscores](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.bbclass.underscores.md) - bbclass filenames shall not contain dashes\n* [oelint.exportfunction.dash](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.exportfunction.dash.md) - EXPORT_FUNCTIONS shall not contain dashes\n* [oelint.file.inactiveupstreamdetails](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.inactiveupstreamdetails.md) - Patches with Upstream-Status: Inactive-Upstream require more details\n* [oelint.file.inappropriatemsg](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.inappropriatemsg.md) - Patches with Upstream-Status: Inappropriate should provide a valid reasoning\n* [oelint.file.includenotfound](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.includenotfound.md) - File to be included not found\n* [oelint.file.includerelpath](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.includerelpath.md) - Require should be used instead of include\n* [oelint.file.inlinesuppress_na](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.inlinesuppress_na.md) - A not applicable inline suppression has been found\n* [oelint.file.nospaces](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.nospaces.md) - Path to file should not contain spaces\n* [oelint.file.patchsignedoff](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.patchsignedoff.md) - Patches should contain a Signed-Of-By entry\n* [oelint.file.requireinclude](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.requireinclude.md) - Require should be used instead of include\n* [oelint.file.requirenotfound](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.requirenotfound.md) - File to be required not found\n* [oelint.file.underscores](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.underscores.md) - Checks the correct usage of underscores in filename\n* [oelint.file.upstreamstatus](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.file.upstreamstatus.md) - Patches should contain a Upstream-Status entry\n* [oelint.func.specific](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.func.specific.md) - Function is specific to an unknown identifier\n* [oelint.newline.consecutive](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.newline.consecutive.md) - Consecutive blank lines should be avoided **[F]**\n* [oelint.newline.eof](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.newline.eof.md) - File shall end on a newline **[F]**\n* [oelint.spaces.emptyline](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.spaces.emptyline.md) - Empty line should not contain spaces or tabs **[F]**\n* [oelint.spaces.linebeginning](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.spaces.linebeginning.md) - No space at a line beginning **[F]**\n* [oelint.spaces.linecont](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.spaces.linecont.md) - Safe line continuation **[F]**\n* [oelint.spaces.lineend](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.spaces.lineend.md) - No spaces at line end **[F]**\n* [oelint.tabs.notabs](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.tabs.notabs.md) - No tabs allowed **[F]**\n* [oelint.task.addnotaskbody](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.addnotaskbody.md) - Task added by addtask cannot be found\n* [oelint.task.customorder](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.customorder.md) - order of custom tasks added via addtask\n* [oelint.task.dash](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.dash.md) - Functions and related statements shall not contain dashes\n* [oelint.task.docstrings](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.docstrings.md) - Custom tasks should have docstrings\n* [oelint.task.heredocs](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.heredocs.md) - Usage of heredocs should be avoided. Use files instead\n* [oelint.task.multifragments](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.multifragments.md) - Multiple fragments of the same function in the same file should be merged\n* [oelint.task.noanonpython](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.noanonpython.md) - Avoid anonymous python functions\n* [oelint.task.nocopy](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.nocopy.md) - No cp usage in do_install\n* [oelint.task.nomkdir](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.nomkdir.md) - No mkdir usage in do_install\n* [oelint.task.nopythonprefix](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.nopythonprefix.md) - Tasks containing shell code should NOT be prefixed with 'python' in function header\n* [oelint.task.order](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.order.md) - Order of tasks **[S]**\n* [oelint.task.pythonprefix](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.task.pythonprefix.md) - Tasks containing python code should be prefixed with 'python' in function header\n* [oelint.var.addpylib](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.addpylib.md) - addpylib is only valid in .conf files\n* [oelint.var.bbclassextend](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.bbclassextend.md) - Use BBCLASSEXTEND when possible\n* [oelint.var.filesoverride](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.filesoverride.md) - FILES:*(FILES_*) variables should not be overridden\n* [oelint.var.improperinherit](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.improperinherit.md) - Warn about improperly named inherits\n* [oelint.var.inherit](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.inherit.md) - Check the correct usage of inherit and inherit_defer (scarthgap+)\n* [oelint.var.inheritdevtool](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.inheritdevtool.md) - inherit_defer is recommended for native and nativesdk class **[S]** (scarthgap+)\n* [oelint.var.licenseremotefile](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.licenseremotefile.md) - License shall be a file in remote source not a local file\n* [oelint.var.mandatoryvar](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.mandatoryvar.md) - Check for mandatory variables **[S]**\n* [oelint.var.multiinclude](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.multiinclude.md) - Warn on including the same file more than once\n* [oelint.var.multiinherit](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.multiinherit.md) - Warn on inherit the same file more than once\n* [oelint.var.nativefilename](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.nativefilename.md) - Native only recipes should be named.md -native\n* [oelint.var.nativesdkfilename](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.nativesdkfilename.md) - NativeSDK only recipes should be named nativesdk-\n* [oelint.var.order](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.order.md) - Variable order **[S]**\n* [oelint.var.override](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.override.md) - Check if include/append is overriding a variable\n* [oelint.var.rootfspostcmd](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.rootfspostcmd.md) - ROOTFS_POSTPROCESS_COMMAND should not have trailing blanks\n* [oelint.var.srcuriwildcard](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.srcuriwildcard.md) - 'SRC_URI' should not contain any wildcards\n* [oelint.var.suggestedvar](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.var.suggestedvar.md) - Notice on suggested variables **[S]**\n* [oelint.vars.appendop](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.appendop.md) - Use ':append(_append)' instead of ' += '\n* [oelint.vars.autorev](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.autorev.md) - The usage of 'AUTOREV' for SRCREV leads to not reproducible builds\n* [oelint.vars.bbvars](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.bbvars.md) - Variables that shouldn't be altered in recipe scope **[S]**\n* [oelint.vars.bugtrackerisurl](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.bugtrackerisurl.md) - BUGTRACKER should be an URL\n* [oelint.vars.dependsappend](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.dependsappend.md) - DEPENDS should only be appended, not overwritten\n* [oelint.vars.dependsclass](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.dependsclass.md) - DEPENDS should use the correct class variants\n* [oelint.vars.dependsordered](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.dependsordered.md) - RDEPENDS entries should be ordered alphabetically\n* [oelint.vars.descriptionsame](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.descriptionsame.md) - 'DESCRIPTION' is the same a 'SUMMARY'.md) - it can be removed then\n* [oelint.vars.descriptiontoobrief](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.descriptiontoobrief.md) - 'DESCRIPTION' is the shorter than 'SUMMARY'\n* [oelint.vars.doublemodify](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.doublemodify.md) - Multiple modifiers of append/prepend/remove/+= found in one operation\n* [oelint.vars.downloadfilename](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.downloadfilename.md) - Fetcher does create a download artifact without 'PV' in the filename\n* [oelint.vars.duplicate](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.duplicate.md) - No duplicates in DEPENDS and RDEPENDS\n* [oelint.vars.dusageinpkgfuncs](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.dusageinpkgfuncs.md) - use \\$D instead of \\$\\{D\\} in pkg functions **[F]**\n* [oelint.vars.fileextrapaths](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.fileextrapaths.md) - 'FILESEXTRAPATHS' shouldn't be used in a bb file\n* [oelint.vars.fileextrapathsop](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.fileextrapathsop.md) - 'FILESEXTRAPATHS' should only be used in combination with ' := '\n* [oelint.vars.filessetting](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.filessetting.md) - unnecessary FILES settings\n* [oelint.vars.homepageping](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.homepageping.md) - 'HOMEPAGE' isn't reachable\n* [oelint.vars.homepageprefix](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.homepageprefix.md) - HOMEPAGE should begin with https:// or http://\n* [oelint.vars.inconspaces](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.inconspaces.md) - Inconsistent use of spaces on append operation\n* [oelint.vars.insaneskip](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.insaneskip.md) - INSANE_SKIP should be avoided at any cost\n* [oelint.vars.licensesdpx](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.licensesdpx.md) - Check for correct SPDX syntax in licenses\n* [oelint.vars.licfileprefix](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.licfileprefix.md) - Unnecessary prefix to LIC_FILES_CHKSUM detected **[F]**\n* [oelint.vars.listappend](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.listappend.md) - Proper append/prepend to lists **[F]**\n* [oelint.vars.mispell.unknown](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.mispell.unknown.md) - Variable is not known from CONSTANTS, typo is unlikely\n* [oelint.vars.mispell](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.mispell.md) - Possible typo detected\n* [oelint.vars.multilineident](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.multilineident.md) - On a multiline assignment, line indent is desirable\n* [oelint.vars.notneededspace](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.notneededspace.md) - Space at the beginning of the var is not needed **[F]**\n* [oelint.vars.notrailingslash](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.notrailingslash.md) - Variable shall not end on a slash\n* [oelint.vars.overrideappend](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.overrideappend.md) - Check correct order of append/prepend on variables with override syntax\n* [oelint.vars.pathhardcode](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.pathhardcode.md) - Warn about the usage of hardcoded paths **[S]**\n* [oelint.vars.pbpusage](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.pbpusage.md) - \\$\\{BP\\} should be used instead of \\$\\{P\\} **[F]**\n* [oelint.vars.pkgspecific](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.pkgspecific.md) - Variable is package-specific, but isn't set in that way **[S]**\n* [oelint.vars.pnbpnusage](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.pnbpnusage.md) - \\$\\{BPN\\} should be used instead of \\$\\{PN\\} **[F]**\n* [oelint.vars.pnusagediscouraged](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.pnusagediscouraged.md) - Variable shouldn't contain \\$\\{PN\\} or \\$\\{BPN\\}\n* [oelint.vars.pythonpnusage](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.pythonpnusage.md) - python3 should be used instead of \\$\\{PYTHON_PN\\} **[F]** (scarthgap+)\n* [oelint.vars.sectionlowercase](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.sectionlowercase.md) - SECTION should be lowercase only **[F]**\n* [oelint.vars.spacesassignment](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.spacesassignment.md) - ' = ' should be correct variable assignment\n* [oelint.vars.specific](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.specific.md) - Variable is specific to an unknown identifier\n* [oelint.vars.srcuriappend](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcuriappend.md) - Use SRC_URI:append(SRC_URI_append) otherwise this will override weak defaults by inherit\n* [oelint.vars.srcurichecksum](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcurichecksum.md) - If SRC_URI has URLs pointing single file that is not from VCS, then checksusm is required\n* [oelint.vars.srcuridomains](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcuridomains.md) - Recipe is pulling from different domains, this will likely cause issues\n* [oelint.vars.srcurifile](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcurifile.md) - First item of SRC_URI should not be a file:// fetcher, if multiple fetcher are used\n* [oelint.vars.srcurigittag](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcurigittag.md) - 'tag' in SRC_URI-options leads to not-reproducible builds\n* [oelint.vars.srcurioptions](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcurioptions.md) - Unsupported fetcher or invalid options detected\n* [oelint.vars.srcurisrcrevtag](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.srcurisrcrevtag.md) - 'tag' in SRC_URI and a SRCREV for the same component doesn't compute\n* [oelint.vars.summary80chars](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.summary80chars.md) - SUMMARY should max. be 80 characters long\n* [oelint.vars.summarylinebreaks](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.summarylinebreaks.md) - No line breaks in SUMMARY\n* [oelint.vars.valuequoted](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.valuequoted.md) - Variable values should be properly quoted\n* [oelint.vars.virtual](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.vars.virtual.md) - no virtual/ items in RDEPENDS/RPROVIDES\n\n### Non-default rulesets\n\nTo enable rulesets that are not part of the standard ruleset pass\n**--addrules \\<ruleset-name\\>** to CLI.\n\nThese rules are sometimes contrary to OE-style-guide, so use them with caution.\n\n#### jetm ruleset\n\nTo enable pass **--addrules jetm** to CLI.\n\nRules marked with **[F]** are able to perform automatic fixing.\n\n* [oelint.jetm.vars.dependssingleline](https://github.com/priv-kweihmann/oelint-adv/blob/master/docs/wiki/oelint.jetm.vars.dependssingleline.md) - Each [R]DEPENDS entry should be put into a single line\n  \n### Writing your own additional rules\n\nBy passing `--customrules` via CLI you could add additional rules to be checked.\nThe argument should point to a directory - every class derived from `Rule` will be automatically loaded.\nPlease use the following as a template for your own:\n\n```python\nfrom oelint_adv.cls_rule import Rule\n\n\nclass FooMagicRule(Rule):\n    def __init__(self):\n        super().__init__(id=\"foocorp.foo.magic\",\n                         severity=\"error\",\n                         message=\"Too much foo happening here\")\n\n    def check(self, _file, stash):\n        res = []\n        items = stash.GetItemsFor(filename=_file)\n        for i in items:\n            if \"Foo\" in i.Raw:\n                res += self.finding(i.Origin, i.InFileLine)\n        return res\n\n    # To provide automatic fixing capability\n    # add the following optional function\n    def fix(self, _file, stash):\n        res = []\n        items = stash.GetItemsFor(filename=_file)\n        for i in items:\n            if 'Foo' in i.Raw:\n                # you have to replace the content of `RealRaw` and `Raw`\n                # with the fixed content\n                # `Raw` is the raw block with expanded inlines blocks\n                # `RealRaw` is the raw block without any modifications\n                #           this is what will be actually written to the file\n                i.RealRaw = i.RealRaw.replace('Foo', 'Bar')\n                i.Raw = i.Raw.replace('Foo', 'Bar')\n                # Return the file name to signalize that fixes have been\n                # applied\n                res.append(_file)\n        return res\n```\n\nFor more details please see the function docstrings of the API.\n\nYou can find this example also in the development [source tree](https://github.com/priv-kweihmann/oelint-adv/tree/master/docs)\n\nAdditional real-life examples can be found in e.g. [meta-rubygems](https://github.com/priv-kweihmann/meta-rubygems/tree/master/files/lint/oelint-custom)\n\n### Release constrained rules\n\nRules can be also configured to work on specific releases of YP only, if determined not to be applicable, the rules will\nbe skipped during the loading process and therefore won't show up if e.g. `--print-rulefile` is used\n\n#### Rules working up to a certain release\n\n```python\nfrom oelint_adv.cls_rule import Rule\n\n\nclass FooMagicRule(Rule):\n    def __init__(self):\n        super().__init__(id=\"foocorp.foo.magic\",\n                         severity=\"error\",\n                         message=\"Too much foo happening here\",\n                         valid_till_release=\"kirkstone\")\n```\n\nWould enable the rule, but only if `--release` is set to a YP release earlier than `kirkstone`\n\n#### Rules working from a certain release\n\n```python\nfrom oelint_adv.cls_rule import Rule\n\n\nclass FooMagicRule(Rule):\n    def __init__(self):\n        super().__init__(id=\"foocorp.foo.magic\",\n                         severity=\"error\",\n                         message=\"Too much foo happening here\",\n                         valid_from_release=\"kirkstone\")\n```\n\nWould enable the rule, but only if `--release` is set to a YP release later than `kirkstone` (including `kirkstone`)\n\n#### Enable special settings per release\n\n```python\nfrom oelint_adv.cls_rule import Rule\n\n\nclass FooMagicRule(Rule):\n    def __init__(self):\n        super().__init__(id=\"foocorp.foo.magic\",\n                         severity=\"error\",\n                         message=\"Too much foo happening here\")\n\n    def check_release_range(self, release_range: List[str]) -> bool:\n        if 'kirkstone' in release_range:\n            self._we_are_running_on_kirkstone = True\n            self.Appendix.append('kirkstone')\n        return super().check_release_range(release_range)\n```\n\nEnables the special `Appendix` `kirkstone`, if `kirkstone` is part of the calculated `--release` list.\n\nIt also sets the variable `self._we_are_running_on_kirkstone`, which can be used as part of `check()` to\ncode special code paths.\n\n## Defining a ruleset\n\nIf you pass the option `--rulefile` you could define the rules to be checked and their severity via a simple json file.\n\nThe rule file could look like this:\n\n```json\n{\n  \"<rule>\": \"<severity>\"\n}\n```\n\nto override the severity, or\n\n```json\n{\n  \"<rule>\": \"\"\n}\n```\n\nto keep the original severity.\n\n### Example\n\n```json\n{\n  \"oelint.file.includenotfound\": \"\",\n  \"oelint.file.requirenotfound\": \"warning\"\n}\n```\n\nwould enable the two rules `oelint.file.includenotfound` and `oelint.file.requirenotfound`.\nThe severity of `oelint.file.includenotfound` will be the default of the tool, while `oelint.file.requirenotfound` will report `warning` instead of the original suggested severity.\n\n### Adding additional constants\n\nPlease see [oelint-parser](https://github.com/priv-kweihmann/oelint-parser) for further details, how to add your own constants to the parser.\n\n## Output message format\n\nYou can freely define a custom output format.\nThe following placeholder symbols will be automatically replaced\n\n| name       | replaced by                |\n| ---------- | -------------------------- |\n| {path}     | path of the file           |\n| {line}     | line of the finding        |\n| {severity} | severity of the finding    |\n| {id}       | error-ID of the finding    |\n| {msg}      | description of the finding |\n| {wikiurl}  | a link to the online wiki  |\n\n## Configuration file\n\nYou can define your own global or project wide defaults for all CLI parameters with an ini-style configuration file.\n\nIn the following order files are probed\n\n* file pointed to by environment variable `OELINT_CONFIG`\n* file `.oelint.cfg` in current work directory\n* file `.oelint.cfg` in your `HOME` directory\n\nExplicitly passed options to CLI are always chosen over the defaults defined by the configuration file.\n\nTo skip the loading of any configuration file, set `OELINT_SKIP_CONFIG` to a non empty value in your environment.\n\n### File format\n\n```ini\n[oelint]\n# this will set the --nowarn parameter automatically\nnowarn = True\n# this will set A + B as suppress item\n# use indent (tab) and line breaks for multiple items\nsuppress = \n  A\n  B\n# this will set messageformat parameter\nmessageformat = {severity}:{id}:{msg}\n# will configure --release to dunfell\nrelease=dunfell\n```\n\nYou can find an example file [here](docs/.oelint.cfg.example)\n\n## Inline suppression\n\nYou can suppress one or more checks on a line by line basis\n\n```bitbake\n# nooelint: <id>[,<id>,...]\n```\n\nsuppresses all the specified IDs for the next line.\nMultiple IDs can be separated by commas.\n\n### Example\n\n```bitbake\n# nooelint: oelint.vars.insaneskip\nINSANE_SKIP:${PN} = \"foo\"\n```\n\nwill not warn about the usage of `INSANE_SKIP`.\n\n## Configure your custom machine or distro settings\n\nYou can let `oelint-adv` know about your custom `MACHINE` and `DISTRO` overrides, so they won't produce any findings, when\nused in your setup.\n\n### Create a layer specific oelint configuration file\n\nCopy over the template this [file](docs/.oelint.cfg.custom-layer) to the root of your layer\n\n```shell\nLAYER_PATH=<path to your layer>\ncp docs/.oelint.cfg.custom-layer $LAYER_PATH/.oelint.cfg\n```\n\n### Create the known MACHINE and DISTRO settings\n\nSource your bitbake build directory and run the following commands (\\*\\*) (\\*\\*\\*)\n\n```shell\nLAYER_PATH=<path to your layer>\nbitbake-getvar --quiet --value MACHINEOVERRIDES | tr ':' '\\n' | jq -Rn  '{replacements:{ machines: [inputs]}}' > $LAYER_PATH/.oelint-custom-machines.json\nbitbake-getvar --quiet --value DISTROOVERRIDES | tr ':' '\\n' | jq -Rn  '{replacements:{ distros: [inputs]}}' > $LAYER_PATH/.oelint-custom-distros.json\n```\n\n(**) you'll need to have `jq` installed on your local machine.\n\n(***) `bitbake-getvar` command is available since `kirkstone` release. For older release you can use `bitbake core-image-minimal -e | grep ^MACHINEOVERRIDES` resp. `bitbake core-image-minimal -e | grep ^DISTROOVERRIDES` and pass them into the rest of the pipe.\n\n## vscode extension\n\nFind the extension in the [marketplace](https://marketplace.visualstudio.com/items?itemName=kweihmann.oelint-vscode), or search for `oelint-vscode`.\n\n## Vim / NeoVim integration\n\nIntegration for Vim / NeoVim is provided by [ale](https://github.com/dense-analysis/ale) or [nvim-lint](https://github.com/mfussenegger/nvim-lint).\n\n## Jenkins integration\n\nJenkins integration is provided by [warnings-ng](https://plugins.jenkins.io/warnings-ng/).\n\n## Use as a library\n\nTo use the linter as part of calling application do\n\n```python\nfrom oelint_adv.core import create_lib_arguments, run\n\nargs = create_lib_arguments(['file to check', 'another file to check']])\n\n# check the docstring of create_lib_arguments for more options\n\nresults = run(args)\n\n# the results will be a List[Tuple[Tuple[str, int], str]]\n# each item is\n#  [0] - 'path to the finding', 'line of the finding'\n#  [1] - 'message'\n```\n\nThe caller is responsible for appropriate exception handling\n\n## Missing anything?\n\nYou think there's something missing, wrong, 'improvable'...\nJust file an issue to get in contact.\n\n## Contribute\n\nAny sort of ideas, pull requests, bug reports, reports of false positives are welcome.\nThis project is open to anyone - no pitfalls or legal inconveniences.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Advanced bitbake-recipe linter",
    "version": "5.3.0",
    "project_urls": {
        "Homepage": "https://github.com/priv-kweihmann/oelint-adv"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "51ee0c0bd06cd032960fac4ddd27a13dda2363d2795180d0711ada776f5e63c2",
                "md5": "7690f0694317260cc97d42c7411a1e6f",
                "sha256": "ddd39cca0bf58ee9dd10fc8ea3942925bd16a5839cc1358d1cf19b02b2ee5ca2"
            },
            "downloads": -1,
            "filename": "oelint_adv-5.3.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "7690f0694317260cc97d42c7411a1e6f",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 104918,
            "upload_time": "2024-04-20T08:06:24",
            "upload_time_iso_8601": "2024-04-20T08:06:24.040334Z",
            "url": "https://files.pythonhosted.org/packages/51/ee/0c0bd06cd032960fac4ddd27a13dda2363d2795180d0711ada776f5e63c2/oelint_adv-5.3.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9eb59c26296298aec4a4e5722e9719347016966bf67de7211f0520677274c755",
                "md5": "bda5aa51f858983e76951215d591b019",
                "sha256": "100607c69ee95d760d6111ac4375dc911c43335a451e0899afe823f1f24ba9ad"
            },
            "downloads": -1,
            "filename": "oelint_adv-5.3.0.tar.gz",
            "has_sig": false,
            "md5_digest": "bda5aa51f858983e76951215d591b019",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 94542,
            "upload_time": "2024-04-20T08:06:27",
            "upload_time_iso_8601": "2024-04-20T08:06:27.267618Z",
            "url": "https://files.pythonhosted.org/packages/9e/b5/9c26296298aec4a4e5722e9719347016966bf67de7211f0520677274c755/oelint_adv-5.3.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-04-20 08:06:27",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "priv-kweihmann",
    "github_project": "oelint-adv",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": true,
    "requirements": [],
    "lcname": "oelint-adv"
}
        
Elapsed time: 0.24326s