Skip to content

Commit

Permalink
Added option to write output to json (#125)
Browse files Browse the repository at this point in the history
* added a json writer
* added tests, formatting
* added docs
* fixed pyproject.toml
  • Loading branch information
Florian Maas authored Sep 24, 2022
1 parent 59159dc commit 94730ba
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
docs/source
deptry.json

# From https://raw.githubusercontent.com/github/gitignore/main/Python.gitignore

Expand Down
10 changes: 10 additions & 0 deletions deptry/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@
default=DEFAULTS["requirements_txt_dev"],
show_default=True,
)
@click.option(
"--json-output",
"-o",
type=click.STRING,
help="""If specified, a summary of the dependency issues found will be written to the output location specified. e.g. `deptry . -o deptry.json`""",
default=DEFAULTS["json_output"],
show_default=True,
)
def deptry(
root: pathlib.Path,
verbose: bool,
Expand All @@ -143,6 +151,7 @@ def deptry(
ignore_notebooks: bool,
requirements_txt: str,
requirements_txt_dev: str,
json_output: str,
version: bool,
) -> None:
"""Find dependency issues in your Python project.
Expand Down Expand Up @@ -198,6 +207,7 @@ def deptry(
skip_misplaced_dev=config.skip_misplaced_dev,
requirements_txt=config.requirements_txt,
requirements_txt_dev=config.requirements_txt_dev,
json_output=json_output,
).run()


Expand Down
1 change: 1 addition & 0 deletions deptry/cli_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
"skip_misplaced_dev": False,
"requirements_txt": "requirements.txt",
"requirements_txt_dev": "dev-requirements.txt,requirements-dev.txt",
"json_output": "",
}
7 changes: 7 additions & 0 deletions deptry/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from deptry.issue_finders.missing import MissingDependenciesFinder
from deptry.issue_finders.obsolete import ObsoleteDependenciesFinder
from deptry.issue_finders.transitive import TransitiveDependenciesFinder
from deptry.json_writer import JsonWriter
from deptry.module import Module, ModuleBuilder
from deptry.python_file_finder import PythonFileFinder
from deptry.result_logger import ResultLogger
Expand All @@ -33,6 +34,7 @@ def __init__(
ignore_notebooks: bool,
requirements_txt: str,
requirements_txt_dev: List[str],
json_output: str,
) -> None:
self.ignore_obsolete = ignore_obsolete
self.ignore_missing = ignore_missing
Expand All @@ -47,6 +49,7 @@ def __init__(
self.skip_misplaced_dev = skip_misplaced_dev
self.requirements_txt = requirements_txt
self.requirements_txt_dev = requirements_txt_dev
self.json_output = json_output

def run(self) -> None:

Expand All @@ -65,6 +68,10 @@ def run(self) -> None:

issues = self._find_issues(imported_modules, dependencies, dev_dependencies)
ResultLogger(issues=issues).log_and_exit()

if self.json_output:
JsonWriter(self.json_output).write(issues=issues)

self._exit(issues)

def _find_issues(
Expand Down
18 changes: 18 additions & 0 deletions deptry/json_writer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import json
from typing import Dict


class JsonWriter:
"""
Class to write issues to a json file
Args:
json_output: file path to store output, e.g. `output.json`
"""

def __init__(self, json_output: str) -> None:
self.json_output = json_output

def write(self, issues: Dict):
with open(self.json_output, "w", encoding="utf-8") as f:
json.dump(issues, f, ensure_ascii=False, indent=4)
23 changes: 22 additions & 1 deletion docs/docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,25 @@ deptry . \
--requirements-txt-dev req/dev.txt,req/test.txt
```

Here, the `requirements-txt` takes only a single file as argument, but multiple files can be passed to `requirements-txt-dev` by providing them as a comma-separated list.
Here, the `requirements-txt` takes only a single file as argument, but multiple files can be passed to `requirements-txt-dev` by providing them as a comma-separated list.

## Output as a json file

_deptry_ can be configured to write the detected issues to a json file by specifying the `--json-output` (`-o`) flag. For example:

```
deptry . -o deptry.json
```

An example of the contents of the resulting `deptry.json` file is as follows:

```
{
"obsolete": [
"foo"
],
"missing": [],
"transitive": [],
"misplaced_dev": []
}
```
19 changes: 19 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json
import pathlib
import shlex
import shutil
import subprocess
Expand Down Expand Up @@ -71,5 +73,22 @@ def test_cli_extend_exclude(dir_with_venv_installed):
assert "The project contains obsolete dependencies:\n\n\tisort\n\trequests\n\ttoml\n\n" in result.stderr


def test_cli_with_json_output(dir_with_venv_installed):
with run_within_dir(str(dir_with_venv_installed)):

# assert that there is no json output
subprocess.run(shlex.split("poetry run deptry ."), capture_output=True, text=True)
assert len(list(pathlib.Path(".").glob("*.json"))) == 0

# assert that there is json output
subprocess.run(shlex.split("poetry run deptry . -o deptry.json"), capture_output=True, text=True)
with open("deptry.json", "r") as f:
data = json.load(f)
assert set(data["obsolete"]) == set(["isort", "requests"])
assert set(data["missing"]) == set(["white"])
assert set(data["misplaced_dev"]) == set(["black"])
assert set(data["transitive"]) == set([])


def test_cli_help():
subprocess.check_call(shlex.split("deptry --help")) == 0
16 changes: 16 additions & 0 deletions tests/test_json_writer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import json

from deptry.json_writer import JsonWriter
from deptry.utils import run_within_dir


def test_simple(tmp_path):

with run_within_dir(tmp_path):
JsonWriter(json_output="output.json").write(issues={"one": "two", "three": "four"})

with open("output.json", "r") as f:
data = json.load(f)

assert data["one"] == "two"
assert data["three"] == "four"

0 comments on commit 94730ba

Please sign in to comment.