Allow to force encoding (#255)

Co-authored-by: Douglas Parkinson <douglasbebo@gmail.com>
This commit is contained in:
Bernát Gábor 2023-07-07 10:29:58 -07:00 committed by GitHub
parent f08cdec13c
commit 390feab1ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 183 additions and 27 deletions

View File

@ -5,7 +5,7 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.0.275"
rev: "v0.0.277"
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
@ -19,12 +19,12 @@ repos:
- id: tox-ini-fmt
args: ["-p", "fix"]
- repo: https://github.com/tox-dev/pyproject-fmt
rev: "0.12.1"
rev: "0.13.0"
hooks:
- id: pyproject-fmt
additional_dependencies: ["tox>=4.6"]
additional_dependencies: ["tox>=4.6.4"]
- repo: https://github.com/pre-commit/mirrors-prettier
rev: "v3.0.0-alpha.9-for-vscode"
rev: "v3.0.0"
hooks:
- id: prettier
args: ["--print-width=120", "--prose-wrap=always"]

View File

@ -45,12 +45,12 @@ optional-dependencies.graphviz = [
]
optional-dependencies.test = [
"covdefaults>=2.3",
"diff-cover>=7.5",
"diff-cover>=7.6",
"pip>=23.1.2",
"pytest>=7.3.1",
"pytest>=7.4",
"pytest-cov>=4.1",
"pytest-mock>=3.10",
"virtualenv<21,>=20.23",
"pytest-mock>=3.11.1",
"virtualenv<21,>=20.23.1",
]
urls.Changelog = "https://github.com/tox-dev/pipdeptree/blob/main/CHANGES.md"
urls.Documentation = "https://github.com/tox-dev/pipdeptree/blob/main/README.md#pipdeptree"

View File

@ -407,7 +407,7 @@ class PackageDAG(Mapping):
# as we're using array mutation
try:
node = [p for p in m if p.key == v.key][0]
except IndexError:
except IndexError: # noqa: PERF203
node = v
m[node].append(k.as_parent_of(v))
if k.key not in child_keys:
@ -456,7 +456,7 @@ class ReversedPackageDAG(PackageDAG):
for v in vs:
try:
node = [p for p in m if p.key == v.key][0]
except IndexError:
except IndexError: # noqa: PERF203
node = v.as_parent_of(None)
m[node].append(k)
if k.key not in child_keys:
@ -464,7 +464,7 @@ class ReversedPackageDAG(PackageDAG):
return PackageDAG(dict(m))
def render_text(tree, max_depth, list_all=True, frozen=False): # noqa: FBT002
def render_text(tree, max_depth, encoding, list_all=True, frozen=False): # noqa: FBT002
"""
Print tree as text on console.
@ -480,7 +480,7 @@ def render_text(tree, max_depth, list_all=True, frozen=False): # noqa: FBT002
if not list_all:
nodes = [p for p in nodes if p.key not in branch_keys]
if sys.stdout.encoding.lower() in ("utf-8", "utf-16", "utf-32"):
if encoding in ("utf-8", "utf-16", "utf-32"):
_render_text_with_unicode(tree, nodes, max_depth, frozen)
else:
_render_text_without_unicode(tree, nodes, max_depth, frozen)
@ -828,7 +828,7 @@ def print_graphviz(dump_output):
bytestream.write(dump_output)
def conflicting_deps(tree):
def conflicting_deps(tree: PackageDAG) -> dict[DistPackage, list[ReqPackage]]:
"""
Returns dependencies which are not present or conflict with the requirements of other packages.
@ -839,10 +839,10 @@ def conflicting_deps(tree):
:rtype: dict
"""
conflicting = defaultdict(list)
for p, rs in tree.items():
for req in rs:
for package, requires in tree.items():
for req in requires:
if req.is_conflicting():
conflicting[p].append(req)
conflicting[package].append(req) # noqa: PERF401
return conflicting
@ -997,6 +997,12 @@ def get_parser():
" ignore this argument."
),
)
parser.add_argument(
"--encoding",
dest="encoding_type",
default=sys.stdout.encoding,
help="Display dependency tree as text using specified encoding",
)
return parser
@ -1114,4 +1120,4 @@ def _render(args, tree):
output = dump_graphviz(tree, output_format=args.output_format, is_reverse=args.reverse)
print_graphviz(output)
else:
render_text(tree, args.depth, args.all, args.freeze)
render_text(tree, args.depth, args.encoding_type, args.all, args.freeze)

View File

@ -494,10 +494,9 @@ class MockStdout:
def test_render_text(capsys, list_all, reverse, unicode, expected_output):
tree = t.reverse() if reverse else t
encoding = "utf-8" if unicode else "ascii"
with mock.patch("sys.stdout", MockStdout(encoding)):
render_text(tree, float("inf"), list_all=list_all, frozen=False)
captured = capsys.readouterr()
assert "\n".join(expected_output).strip() == captured.out.strip()
render_text(tree, float("inf"), encoding, list_all=list_all, frozen=False)
captured = capsys.readouterr()
assert "\n".join(expected_output).strip() == captured.out.strip()
@pytest.mark.parametrize(
@ -590,11 +589,162 @@ def test_render_text(capsys, list_all, reverse, unicode, expected_output):
],
)
def test_render_text_given_depth(capsys, unicode, level, expected_output):
encoding = "utf-8" if unicode else "ascii"
with mock.patch("sys.stdout", MockStdout(encoding)):
render_text(t, level)
captured = capsys.readouterr()
assert "\n".join(expected_output).strip() == captured.out.strip()
render_text(t, level, encoding="utf-8" if unicode else "ascii")
captured = capsys.readouterr()
assert "\n".join(expected_output).strip() == captured.out.strip()
@pytest.mark.parametrize(
("level", "encoding", "expected_output"),
[
(
0,
"utf-8",
[
"a==3.4.0",
"b==2.3.1",
"c==5.10.0",
"d==2.35",
"e==0.12.1",
"f==3.1",
"g==6.8.3rc1",
],
),
(
0,
"utf-8",
[
"a==3.4.0",
"b==2.3.1",
"c==5.10.0",
"d==2.35",
"e==0.12.1",
"f==3.1",
"g==6.8.3rc1",
],
),
(
2,
"utf-8",
[
"a==3.4.0",
"├── b [required: >=2.0.0, installed: 2.3.1]",
"│ └── d [required: >=2.30,<2.42, installed: 2.35]",
"└── c [required: >=5.7.1, installed: 5.10.0]",
" ├── d [required: >=2.30, installed: 2.35]",
" └── e [required: >=0.12.1, installed: 0.12.1]",
"b==2.3.1",
"└── d [required: >=2.30,<2.42, installed: 2.35]",
" └── e [required: >=0.9.0, installed: 0.12.1]",
"c==5.10.0",
"├── d [required: >=2.30, installed: 2.35]",
"│ └── e [required: >=0.9.0, installed: 0.12.1]",
"└── e [required: >=0.12.1, installed: 0.12.1]",
"d==2.35",
"└── e [required: >=0.9.0, installed: 0.12.1]",
"e==0.12.1",
"f==3.1",
"└── b [required: >=2.1.0, installed: 2.3.1]",
" └── d [required: >=2.30,<2.42, installed: 2.35]",
"g==6.8.3rc1",
"├── e [required: >=0.9.0, installed: 0.12.1]",
"└── f [required: >=3.0.0, installed: 3.1]",
" └── b [required: >=2.1.0, installed: 2.3.1]",
],
),
(
2,
"ascii",
[
"a==3.4.0",
" - b [required: >=2.0.0, installed: 2.3.1]",
" - d [required: >=2.30,<2.42, installed: 2.35]",
" - c [required: >=5.7.1, installed: 5.10.0]",
" - d [required: >=2.30, installed: 2.35]",
" - e [required: >=0.12.1, installed: 0.12.1]",
"b==2.3.1",
" - d [required: >=2.30,<2.42, installed: 2.35]",
" - e [required: >=0.9.0, installed: 0.12.1]",
"c==5.10.0",
" - d [required: >=2.30, installed: 2.35]",
" - e [required: >=0.9.0, installed: 0.12.1]",
" - e [required: >=0.12.1, installed: 0.12.1]",
"d==2.35",
" - e [required: >=0.9.0, installed: 0.12.1]",
"e==0.12.1",
"f==3.1",
" - b [required: >=2.1.0, installed: 2.3.1]",
" - d [required: >=2.30,<2.42, installed: 2.35]",
"g==6.8.3rc1",
" - e [required: >=0.9.0, installed: 0.12.1]",
" - f [required: >=3.0.0, installed: 3.1]",
" - b [required: >=2.1.0, installed: 2.3.1]",
],
),
(
2,
"utf-8",
[
"a==3.4.0",
"├── b [required: >=2.0.0, installed: 2.3.1]",
"│ └── d [required: >=2.30,<2.42, installed: 2.35]",
"└── c [required: >=5.7.1, installed: 5.10.0]",
" ├── d [required: >=2.30, installed: 2.35]",
" └── e [required: >=0.12.1, installed: 0.12.1]",
"b==2.3.1",
"└── d [required: >=2.30,<2.42, installed: 2.35]",
" └── e [required: >=0.9.0, installed: 0.12.1]",
"c==5.10.0",
"├── d [required: >=2.30, installed: 2.35]",
"│ └── e [required: >=0.9.0, installed: 0.12.1]",
"└── e [required: >=0.12.1, installed: 0.12.1]",
"d==2.35",
"└── e [required: >=0.9.0, installed: 0.12.1]",
"e==0.12.1",
"f==3.1",
"└── b [required: >=2.1.0, installed: 2.3.1]",
" └── d [required: >=2.30,<2.42, installed: 2.35]",
"g==6.8.3rc1",
"├── e [required: >=0.9.0, installed: 0.12.1]",
"└── f [required: >=3.0.0, installed: 3.1]",
" └── b [required: >=2.1.0, installed: 2.3.1]",
],
),
(
2,
"ascii",
[
"a==3.4.0",
" - b [required: >=2.0.0, installed: 2.3.1]",
" - d [required: >=2.30,<2.42, installed: 2.35]",
" - c [required: >=5.7.1, installed: 5.10.0]",
" - d [required: >=2.30, installed: 2.35]",
" - e [required: >=0.12.1, installed: 0.12.1]",
"b==2.3.1",
" - d [required: >=2.30,<2.42, installed: 2.35]",
" - e [required: >=0.9.0, installed: 0.12.1]",
"c==5.10.0",
" - d [required: >=2.30, installed: 2.35]",
" - e [required: >=0.9.0, installed: 0.12.1]",
" - e [required: >=0.12.1, installed: 0.12.1]",
"d==2.35",
" - e [required: >=0.9.0, installed: 0.12.1]",
"e==0.12.1",
"f==3.1",
" - b [required: >=2.1.0, installed: 2.3.1]",
" - d [required: >=2.30,<2.42, installed: 2.35]",
"g==6.8.3rc1",
" - e [required: >=0.9.0, installed: 0.12.1]",
" - f [required: >=3.0.0, installed: 3.1]",
" - b [required: >=2.1.0, installed: 2.3.1]",
],
),
],
)
def test_render_text_encoding(capsys, level, encoding, expected_output):
render_text(t, level, encoding, True, False)
captured = capsys.readouterr()
assert "\n".join(expected_output).strip() == captured.out.strip()
# Tests for graph outputs

View File

@ -36,7 +36,7 @@ commands =
description = format the code base to adhere to our styles, and complain about what we cannot do automatically
skip_install = true
deps =
pre-commit>=3.3.2
pre-commit>=3.3.3
commands =
pre-commit run --all-files --show-diff-on-failure