SkillAgentSearch skills...

Vermin

Concurrently detect the minimum Python versions needed to run code

Install / Use

/learn @netromdk/Vermin

README

|Test Status| |Analyze Status| |CodeQL Status| |Coverage| |PyPI version| |Commits since last| |Downloads| |CII best practices|

.. |PyPI version| image:: https://badge.fury.io/py/vermin.svg :target: https://pypi.python.org/pypi/vermin/

.. |Test Status| image:: https://github.com/netromdk/vermin/workflows/Test/badge.svg?branch=master :target: https://github.com/netromdk/vermin/actions

.. |Analyze Status| image:: https://github.com/netromdk/vermin/workflows/Analyze/badge.svg?branch=master :target: https://github.com/netromdk/vermin/actions

.. |CodeQL Status| image:: https://github.com/netromdk/vermin/workflows/CodeQL/badge.svg?branch=master :target: https://github.com/netromdk/vermin/security/code-scanning

.. |Snyk Status| image:: https://github.com/netromdk/vermin/workflows/Snyk%20Schedule/badge.svg?branch=master :target: https://github.com/netromdk/vermin/actions

.. |Coverage| image:: https://coveralls.io/repos/github/netromdk/vermin/badge.svg?branch=master :target: https://coveralls.io/github/netromdk/vermin?branch=master

.. |Commits since last| image:: https://img.shields.io/github/commits-since/netromdk/vermin/latest.svg

.. |Downloads| image:: https://static.pepy.tech/personalized-badge/vermin?period=total&units=international_system&left_color=gray&right_color=blue&left_text=Downloads :target: https://pepy.tech/project/vermin

.. |CII best practices| image:: https://bestpractices.coreinfrastructure.org/projects/6451/badge :target: https://bestpractices.coreinfrastructure.org/projects/6451

Vermin


Concurrently detect the minimum Python versions needed to run code. Additionally, since the code is vanilla Python, and it doesn't have any external dependencies, it can be run with v3+ but still includes detection of v2.x functionality.

It functions by parsing Python code into an abstract syntax tree (AST), which it traverses and matches against internal dictionaries with 4140 rules, covering v2.0-2.7 and v3.0-3.14, divided into 190 modules, 2888 classes/functions/constants members of modules, 932 kwargs of functions, 4 strftime directives, 3 bytes format directives, 3 array typecodes, 3 codecs error handler names, 20 codecs encodings, 78 builtin generic annotation types, 9 builtin dict union (|) types, 8 builtin dict union merge (|=) types, and 2 user function decorators.

Backports of the standard library, like typing, can be enabled for better results. Get full list of backports via --help.

The project is fairly well-tested with 4362 unit and integration tests that are executed on Linux, macOS, and Windows.

It is recommended to use the most recent Python version to run Vermin on projects since Python's own language parser is used to detect language features, like f-strings since Python 3.6 etc.

Table of Contents

  • Usage <#usage>__
  • Features <#features>__
  • Caveats <#caveats>__
  • Configuration File <#configuration-file>__
  • Examples <#examples>__
  • Linting (showing only target versions violations) <#linting-showing-only-target-versions-violations>__
  • API (experimental) <#api-experimental>__
  • Analysis Exclusions <#analysis-exclusions>__
  • Parsable Output <#parsable-output>__
  • GitHub Output <#github-output>__
  • Contributing <#contributing>__

Usage

It is fairly straightforward to use Vermin.

Running it from the repository either directly or through specific interpreter::

% ./vermin.py /path/to/your/project # (1) executing via /usr/bin/env python % python3 vermin.py /path/to/your/project # (2) specifically python3

Or if installed via PyPi <https://pypi.python.org/pypi/vermin/>__::

% pip install vermin % vermin /path/to/your/project

Homebrew <https://brew.sh>__ (pkg <https://formulae.brew.sh/formula/vermin#default>__)::

% brew install vermin

Spack <https://spack.io>__ (pkg <https://github.com/spack/spack-packages/blob/develop/repos/spack_repo/builtin/packages/py_vermin/package.py>__)::

% git clone https://github.com/spack/spack.git % . spack/share/spack/setup-env.sh # depending on shell % spack install py-vermin % spack load py-vermin

Arch Linux (AUR) <https://aur.archlinux.org/packages/python-vermin/>__::

% yay -S python-vermin

When using continuous integration (CI) tools, like Travis CI <https://travis-ci.org/>_, Vermin can be used to check that the minimum required versions didn't change. The following is an excerpt::

install:

  • ./setup_virtual_env.sh
  • pip install vermin script:
  • vermin -t=2.7 -t=3 project_package otherfile.py

Vermin can also be used as a pre-commit <https://pre-commit.com/>__ hook:

.. code-block:: yaml

repos: - repo: https://github.com/netromdk/vermin rev: GIT_SHA_OR_TAG # ex: 'e88bda9' or 'v1.3.4' hooks: - id: vermin # specify your target version here, OR in a Vermin config file as usual: args: ['-t=3.8-', '--violations'] # (if your target is specified in a Vermin config, you may omit the 'args' entry entirely)

When using the hook, a target version must be specified via a Vermin config file in your package, or via the args option in your .pre-commit-config.yaml config. If you're passing the target via args, it's recommended to also include --violations (shown above).

If you're using the vermin-all hook, you can specify any target as you usually would. However, if you're using the vermin hook, your target must be in the form of x.y- (as opposed to x.y), otherwise you will run into issues when your staged changes meet a minimum version that is lower than your target.

See the pre-commit docs <https://pre-commit.com/#quick-start>__ for further general information on how to get hooks set up on your project.

Features

Features detected include v2/v3 print expr and print(expr), long, f-strings, coroutines (async and await), asynchronous generators (await and yield in same function), asynchronous comprehensions, await in comprehensions, asynchronous for-loops, boolean constants, named expressions, keyword-only parameters, positional-only parameters, nonlocal, yield from, exception context cause (raise .. from ..), except*, set literals, set comprehensions, dict comprehensions, infix matrix multiplication, "..".format(..), imports (import X, from X import Y, from X import *), function calls wrt. name and kwargs, strftime + strptime directives used, function and variable annotations (also Final and Literal), continue in finally block, modular inverse pow(), array typecodes, codecs error handler names, encodings, % formatting and directives for bytes and bytearray, with statement, asynchronous with statement, multiple context expressions in a with statement, multiple context expressions in a with statement grouped with parenthesis, unpacking assignment, generalized unpacking, ellipsis literal (...) out of slices, dictionary union ({..} | {..}), dictionary union merge (a = {..}; a |= {..}), builtin generic type annotations (list[str]), function decorators, class decorators, relaxed decorators, metaclass class keyword, pattern matching with match, union types written as X | Y, type alias statements (type X = SomeType), type alias statements with lambdas/comprehensions in class scopes, generic classes (class C[T]: ...), and template string literals (t'{var}'). It tries to detect and ignore user-defined functions, classes, arguments, and variables with names that clash with library-defined symbols.

Caveats

For frequently asked questions, check out the FAQ discussions <https://github.com/netromdk/vermin/discussions/categories/faq>__.

Self-documenting fstrings detection has been disabled by default because the built-in AST cannot distinguish f'{a=}' from f'a={a}', for instance, since it optimizes some information away (#39 <https://github.com/netromdk/vermin/issues/39>__). And this incorrectly marks some source code as using fstring self-doc when only using general fstring. To enable (unstable) fstring self-doc detection, use --feature fstring-self-doc.

Detecting union types (X | Y PEP 604 <https://www.python.org/dev/peps/pep-0604/>) can be tricky because Vermin doesn't know all underlying details of constants and types since it parses and traverses the AST. For this reason, heuristics are employed and this can sometimes yield incorrect results (#103 <https://github.com/netromdk/vermin/issues/103>). To enable (unstable) union types detection, use --feature union-types.

Function and variable annotations aren't evaluated at definition time when from __future__ import annotations is used (PEP 563 <https://www.python.org/dev/peps/pep-0563/>). This is why --no-eval-annotations is on by default (since v1.1.1, #66 <https://github.com/netromdk/vermin/issues/66>). If annotations are being evaluated at runtime, like using typing.get_type_hints or evaluating __annotations__ of an object, --eval-annotations should be used for best results.

Configuration File

Vermin automatically tries to detect a config file, starting in the current working directory where it is run, following parent folders until either the root or project boundary files/folders are reached. However, if --config-file is specified, no config is auto-detected and loaded.

Config file names being looked for: vermin.ini, vermin.conf, .vermin, setup.cfg

Project boundary files/folders: .git, .svn, .hg, .bzr, _darcs, .fslckout, .p4root, .pijul

A sample config file can be found here <sample.vermin.ini>__.

Note that Vermin config can be in the same INI file as other configs, like the commonly used ``setup.cf

View on GitHub
GitHub Stars514
CategoryDevelopment
Updated10d ago
Forks28

Languages

Python

Security Score

100/100

Audited on Mar 27, 2026

No findings