Skip to content

posit-dev/picopip

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

picopip

Embed-friendly Python env/package scanner with zero deps.

This is primarily designed so that you can take src/picopip.py and copy it into your own project to use it without having to install dependencies.

Usage

Get list of installed packages

You can use get_packages_from_env to list all installed packages in a Python virtual environment. Here's how to do it using Python's built-in venv module:

>>> from picopip import get_packages_from_env
>>>
>>> pkgs = get_packages_from_env(venvdir)
>>> print(pkgs)
[('certifi', '2025.4.26'), ('charset-normalizer', '3.4.2'), ('idna', '3.10'), 
 ('pip', '21.2.4'), ('requests', '2.32.3'), ('setuptools', '58.0.4'), 
 ('urllib3', '2.4.0')]
  • get_packages_from_env(<venv_path>) returns a list of (name, version) tuples for all installed packages in the given virtual environment.
  • You can use any venv path, and the function will find all packages, including those installed via pip.

Scan a target directory (pip install --target)

By default get_packages_from_env expects a full virtual environment layout (lib/pythonX.Y/site-packages, .pth expansion, system and PYTHONPATH discovery). If you instead installed packages into a flat directory with pip install --target <dir>, pass path_as_target=True to scan that directory directly.

pip install --target ./vendor requests
>>> from picopip import get_packages_from_env
>>>
>>> pkgs = get_packages_from_env("./vendor", path_as_target=True)
>>> print(pkgs)
[('certifi', '2025.4.26'), ('charset-normalizer', '3.4.2'), ('idna', '3.10'),
 ('requests', '2.32.3'), ('urllib3', '2.4.0')]

With path_as_target=True:

  • venv_path is treated as the site-packages directory itself, so no lib/pythonX.Y/site-packages structure is required.
  • .pth files are not expanded and PYTHONPATH is not read.
  • ignore_system_packages is ignored (system packages are never scanned).

Get version of a package

If you only need the version of a specific package, you can get it using get_package_version_from_env

>>> from picopip import get_package_version_from_env
>>>
>>> version = get_package_version_from_env(venvdir, "pip")
>>> print(version)
'21.2.4'

Parse a version string

parse_version normalizes a version into a tuple that follows the same ordering rules used by pip/packaging. The first element is the release components, the second is an offset encoding pre/dev/post markers so you can compare the tuples with standard operators.

>>> from picopip import parse_version
>>>
>>> parse_version("1.13.5")
((1, 13, 5), 0)
>>> parse_version("1.13.5a1") < parse_version("1.13.5")
True
>>> parse_version("1.13.5.post2") > parse_version("1.13.5")
True

Check a version against a constraint

parse_constraints parses a requirement spec like "aiokafka >= 0.8, < 1.0" into the package name and a list of (comparator, parsed_version) pairs. Apply every pair to a parsed version to decide whether it satisfies the spec.

>>> from picopip import parse_constraints, parse_version
>>>
>>> name, constraints = parse_constraints("aiokafka >= 0.8, < 1.0")
>>> name
'aiokafka'
>>> v = parse_version("0.9.1")
>>> all(op(v, cv) for op, cv in constraints)
True
>>> v = parse_version("1.0.0")
>>> all(op(v, cv) for op, cv in constraints)
False

The name is None for bare specs (">= 0.8, < 1.0").

Releasing

Releases are cut by pushing a N.N.N git tag. The Release workflow runs lint and tests, then publishes a GitHub release with auto-generated notes.

  1. Bump the Version: line in src/picopip.py on main and merge.

  2. Tag the release commit with the matching version and push the tag:

    git tag 0.5.1
    git push origin 0.5.1

The workflow fails if the tag does not match N.N.N or does not match the Version: line in src/picopip.py, so both must be kept in sync.

About

Embed-friendly Python env/package scanner with zero deps

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages