Metadata-Version: 2.1
Name: creosote
Version: 2.3.2
Summary: Identify unused dependencies and avoid a bloated virtual environment.
Project-URL: Source, https://github.com/fredrikaverpil/creosote
Project-URL: Tracker, https://github.com/fredrikaverpil/creosote/issues
Author-email: Fredrik Averpil <fredrik.averpil@gmail.com>
License-Expression: MIT
License-File: LICENSE
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Requires-Python: >=3.7
Requires-Dist: distlib<0.4,>=0.3.4
Requires-Dist: dotty-dict<1.4,>=1.3.1
Requires-Dist: loguru<0.7,>=0.6.0
Requires-Dist: pip-requirements-parser<33.1,>=32.0.1
Requires-Dist: toml<0.11,>=0.10.2
Provides-Extra: dev
Requires-Dist: creosote[lint,test,types]; extra == 'dev'
Provides-Extra: lint
Requires-Dist: black; extra == 'lint'
Requires-Dist: ruff; extra == 'lint'
Provides-Extra: test
Requires-Dist: pytest; extra == 'test'
Provides-Extra: types
Requires-Dist: loguru-mypy; extra == 'types'
Requires-Dist: mypy; extra == 'types'
Requires-Dist: types-toml; extra == 'types'
Description-Content-Type: text/markdown

# creosote

[![check](https://github.com/fredrikaverpil/creosote/actions/workflows/check.yml/badge.svg)](https://github.com/fredrikaverpil/creosote/actions/workflows/check.yml)
[![test](https://github.com/fredrikaverpil/creosote/actions/workflows/test.yml/badge.svg)](https://github.com/fredrikaverpil/creosote/actions/workflows/test.yml)

Identify unused dependencies and avoid a bloated virtual environment.

## Quickstart

Install creosote in separate virtual environment (using e.g. [pipx](https://github.com/pypa/pipx)):

```bash
pipx install creosote
```

Scan virtual environment for unused packages ([PEP-621](https://peps.python.org/pep-0621/) example below, but [Poetry](https://python-poetry.org/), [Pipenv](https://github.com/pypa/pipenv) and `requirements.txt` files are also supported):

```bash
creosote --venv .venv --paths src --deps-file pyproject.toml --sections project.dependencies
```

Example output (using Poetry dependency definition):

```bash
$ creosote --venv .venv --paths src --deps-file pyproject.toml --sections tool.poetry.dependencies
Parsing src/creosote/formatters.py
Parsing src/creosote/models.py
Parsing src/creosote/resolvers.py
Parsing src/creosote/__init__.py
Parsing src/creosote/parsers.py
Parsing src/creosote/cli.py
Parsing pyproject.toml for packages
Found packages in pyproject.toml: PyYAML, distlib, loguru, protobuf, toml
Resolving...
Unused packages found: PyYAML, protobuf
```

Get help:

```bash
creosote --help
```

## How this works

Some data is required as input:

- The path to the virtual environment (`--venv`).
- The path to one or more Python files, or a folder containing such files (`--paths`).
- A list of package names, fetched from e.g. `pyproject.toml`, `requirements_*.txt|.in` (`--deps-file`).
- One or more toml sections to parse, e.g. `project.dependencies` (`--sections`).

The creosote tool will first scan the given python file(s) for all its imports. Then it fetches all package names (from the dependencies spec file). Finally, all imports are associated with their corresponding package name (requires the virtual environment for resolving). If a package does not have any imports associated, it will be considered to be unused.

## Ambition and history

The idea of a package like this was born from having gotten security vulnerability
reports about production dependencies (shipped into production) which turned out to not not
even be in use.

The goal would be to be able to run this tool in CI, which will catch cases where the developer
forgets to remove unused dependencies. An example of such a case could be when doing refactorings.

Note: The creosote tool supports identifying both unused production dependencies and developer dependencies.

## FAQ

### Are requirements.txt files supported?

Yes, kind of. There is no way to tell which part of `requirements.txt` specifies production vs developer dependencies. Therefore, you have to break your `requirements.txt` file into e.g. `requirements-prod.txt` and `requirements-dev.txt` and use any of them as input.

If you are using [pip-tools](https://github.com/jazzband/pip-tools), you can provide a `*.in` file.

### Can I scan for PEP-621 dependencies?

Yes! Just provide `--sections project.dependencies`.

### Can I scan for PEP-621 optional dependencies?

Yes! Just provide `--sections project.optional-dependencies.<GROUP>` where `<GROUP>` is your dependency group name, e.g. `--sections project.optional-dependencies.lint`.

### Can I scan for Poetry's dependencies?

Yes, see below!

#### Main dependencies

Just provide `--sections tool.poetry.dependencies`.

#### Dev-dependencies?

Just provide `--sections tool.poetry.dev-dependencies`.

#### Dependency groups?

Just provide `--sections tool.poetry.group.<GROUP>.dependencies` where `<GROUP>` is your dependency group, e.g. `--sections tool.poetry.group.lint.dependencies`.

### Can I scan for Pipenv dependencies?

Yes, see below!

#### Dependencies

Just provide `--sections packages`.

#### Developer dependencies

Just provide `--sections dev-packages`.

### Can I scan for multiple toml sections?

Yes! Just provide each section after the `--sections` parameter, e.g. `--sections project.optional-dependencies.test project.optional-dependencies.lint`.

### Can I use this as a GitHub Action?

Yes! See the `action` job in [.github/workflows/test.yml](.github/workflows/test.yml) for a working example.

### Can I use this with pre-commit?

While there is no formal support for [pre-commit](https://pre-commit.com) (at least not now), you can configure pre-commit to run creosote if it is available on `$PATH` (e.g. if you installed it
with `pipx`). Example below:

```yaml
# .pre-commit-config.yaml

repos:
  - repo: local
    hooks:
      - id: system
        name: creosote
        entry: creosote --venv .venv --paths src --deps-file pyproject.toml --sections project.dependencies
        pass_filenames: false
        files: \.(py|toml|txt|in|lock)$
        language: system
```

### What's with the name "creosote"?

This library has borrowed its name from the [Monty Python scene about Mr. Creosote](https://www.youtube.com/watch?v=aczPDGC3f8U).


### Releasing

1. Bump version in `src/creosote/__about__.py`.
2. GitHub Action will run automatically on creating [a release](https://github.com/fredrikaverpil/creosote/releases) and deploy the release onto PyPi.
