Skip to content

Commit f5f5885

Browse files
committed
testing and code improvements
1 parent 9f388c1 commit f5f5885

33 files changed

+1426
-239
lines changed

.pre-commit-config.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
3-
rev: v0.2.2
3+
rev: v0.3.3
44
hooks:
55
- id: ruff
66
args: [ --fix ]
77
- id: ruff-format
88

99
- repo: https://github.com/RobertCraigie/pyright-python
10-
rev: v1.1.351
10+
rev: v1.1.354
1111
hooks:
1212
- id: pyright
1313

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
All major and minor version changes will be documented in this file. Details of
44
patch-level version changes can be found in [commit messages](../../commits/master).
55

6+
## 2024.1 - 2024/03/16
7+
8+
- code improvements
9+
- fix issue where onlyLicenses logic caused licensecompat to be `false` when unspecified from the command line
10+
- move `cli()` to `cli.py`
11+
- add tests for the main entry point
12+
613
## 2024 - 2024/01/27
714

815
- code improvements

licensecheck/__init__.py

+3-151
Original file line numberDiff line numberDiff line change
@@ -1,153 +1,5 @@
1-
"""Output the licenses used by dependencies and check if these are compatible with the project
2-
license.
3-
"""
4-
from __future__ import annotations
1+
"""Entry point for python -m licensecheck."""
52

6-
import argparse
7-
from dataclasses import fields
8-
from pathlib import Path
9-
from sys import exit as sysexit
10-
from sys import stdout
3+
from licensecheck.cli import cli, main
114

12-
from fhconfparser import FHConfParser, SimpleConf
13-
14-
from licensecheck import formatter, get_deps, license_matrix, types
15-
16-
stdout.reconfigure(encoding="utf-8") # type: ignore[general-type-issues]
17-
18-
19-
def cli() -> None:
20-
"""Cli entry point."""
21-
exitCode = 0
22-
parser = argparse.ArgumentParser(description=__doc__, argument_default=argparse.SUPPRESS)
23-
parser.add_argument(
24-
"--license",
25-
"-l",
26-
help="",
27-
)
28-
parser.add_argument(
29-
"--format",
30-
"-f",
31-
help=f"Output format. one of: {', '.join(list(formatter.formatMap))}. default=simple",
32-
)
33-
parser.add_argument(
34-
"--file",
35-
"-o",
36-
help="Filename to write to (omit for stdout)",
37-
)
38-
parser.add_argument(
39-
"--using",
40-
"-u",
41-
help="Environment to use e.g. requirements.txt. one of: "
42-
f"{', '.join(get_deps.USINGS)}. default=poetry",
43-
)
44-
parser.add_argument(
45-
"--ignore-packages",
46-
help="a list of packages to ignore (compat=True)",
47-
nargs="+",
48-
)
49-
parser.add_argument(
50-
"--fail-packages",
51-
help="a list of packages to fail (compat=False)",
52-
nargs="+",
53-
)
54-
parser.add_argument(
55-
"--ignore-licenses",
56-
help="a list of licenses to ignore (skipped, compat may still be False)",
57-
nargs="+",
58-
)
59-
parser.add_argument(
60-
"--fail-licenses",
61-
help="a list of licenses to fail (compat=False)",
62-
nargs="+",
63-
)
64-
parser.add_argument(
65-
"--only-licenses",
66-
help="a list of allowed licenses (any other license will fail)",
67-
nargs="+",
68-
)
69-
parser.add_argument(
70-
"--skip-dependencies",
71-
help="a list of packages to skip (compat=True)",
72-
nargs="+",
73-
)
74-
parser.add_argument(
75-
"--hide-output-parameters",
76-
help="a list of parameters to hide from the produced output",
77-
nargs="+"
78-
)
79-
parser.add_argument(
80-
"--zero",
81-
"-0",
82-
help="Return non zero exit code if an incompatible license is found",
83-
action="store_true",
84-
)
85-
args = vars(parser.parse_args())
86-
87-
# ConfigParser (Parses in the following order: `pyproject.toml`,
88-
# `setup.cfg`, `licensecheck.toml`, `licensecheck.json`,
89-
# `licensecheck.ini`, `~/licensecheck.toml`, `~/licensecheck.json`, `~/licensecheck.ini`)
90-
configparser = FHConfParser()
91-
namespace = ["tool"]
92-
configparser.parseConfigList(
93-
[("pyproject.toml", "toml"), ("setup.cfg", "ini")]
94-
+ [
95-
(f"{directory}/licensecheck.{ext}", ext)
96-
for ext in ("toml", "json", "ini")
97-
for directory in [".", str(Path.home())]
98-
],
99-
namespace,
100-
namespace,
101-
)
102-
simpleConf = SimpleConf(configparser, "licensecheck", args)
103-
104-
# File
105-
textIO = (
106-
stdout
107-
if simpleConf.get("file") is None
108-
else open(simpleConf.get("file"), "w", encoding="utf-8")
109-
)
110-
111-
# Get list of licenses
112-
myLice, depsWithLicenses = get_deps.getDepsWithLicenses(
113-
simpleConf.get("using", "poetry"),
114-
list(map(types.ucstr, simpleConf.get("ignore_packages", []))),
115-
list(map(types.ucstr, simpleConf.get("fail_packages", []))),
116-
list(map(types.ucstr, simpleConf.get("ignore_licenses", []))),
117-
list(map(types.ucstr, simpleConf.get("fail_licenses", []))),
118-
list(map(types.ucstr, simpleConf.get("only_licenses", []))),
119-
list(map(types.ucstr, simpleConf.get("skip_dependencies", []))),
120-
)
121-
122-
myLice = license_matrix.licenseType(args["license"])[0] if args.get("license") else myLice
123-
124-
# Are any licenses incompatible?
125-
incompatible = any(not lice.licenseCompat for lice in depsWithLicenses)
126-
127-
# Format the results
128-
hide_output_parameters = list(map(types.ucstr, simpleConf.get("hide_output_parameters", [])))
129-
available_params = [param.name.upper() for param in fields(types.PackageInfo)]
130-
if not all(hop in available_params for hop in hide_output_parameters):
131-
raise ValueError(
132-
f"Invalid parameter(s) in `hide_output_parameters`. "
133-
f"Valid parameters are: {', '.join(available_params)}"
134-
)
135-
if simpleConf.get("format", "simple") in formatter.formatMap:
136-
print(
137-
formatter.formatMap[simpleConf.get("format", "simple")](
138-
myLice,
139-
sorted(depsWithLicenses),
140-
hide_output_parameters,
141-
),
142-
file=textIO,
143-
)
144-
else:
145-
exitCode = 2
146-
147-
# Exit code of 1 if args.zero
148-
if simpleConf.get("zero", False) and incompatible:
149-
exitCode = 1
150-
151-
# Cleanup + exit
152-
textIO.close()
153-
sysexit(exitCode)
5+
_ = (cli, main)

licensecheck/__main__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Entry point for python -m licensecheck."""
2+
23
from __future__ import annotations
34

4-
from . import cli
5+
from licensecheck import cli
56

67
cli()

licensecheck/cli.py

+161
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
"""Output the licenses used by dependencies and check if these are compatible with the project
2+
license.
3+
"""
4+
5+
from __future__ import annotations
6+
7+
import argparse
8+
from dataclasses import fields
9+
from pathlib import Path
10+
from sys import exit as sysexit
11+
from sys import stdout
12+
13+
from fhconfparser import FHConfParser, SimpleConf
14+
15+
from licensecheck import formatter, get_deps, license_matrix, types
16+
17+
stdout.reconfigure(encoding="utf-8") # type: ignore[general-type-issues]
18+
19+
20+
def cli() -> None: # pragma: no cover
21+
"""Cli entry point."""
22+
parser = argparse.ArgumentParser(description=__doc__, argument_default=argparse.SUPPRESS)
23+
parser.add_argument(
24+
"--license",
25+
"-l",
26+
help="",
27+
)
28+
parser.add_argument(
29+
"--format",
30+
"-f",
31+
help=f"Output format. one of: {', '.join(list(formatter.formatMap))}. default=simple",
32+
)
33+
parser.add_argument(
34+
"--file",
35+
"-o",
36+
help="Filename to write to (omit for stdout)",
37+
)
38+
parser.add_argument(
39+
"--using",
40+
"-u",
41+
help="Environment to use e.g. requirements.txt. one of: "
42+
f"{', '.join(get_deps.USINGS)}. default=poetry",
43+
)
44+
parser.add_argument(
45+
"--ignore-packages",
46+
help="a list of packages to ignore (compat=True)",
47+
nargs="+",
48+
)
49+
parser.add_argument(
50+
"--fail-packages",
51+
help="a list of packages to fail (compat=False)",
52+
nargs="+",
53+
)
54+
parser.add_argument(
55+
"--ignore-licenses",
56+
help="a list of licenses to ignore (skipped, compat may still be False)",
57+
nargs="+",
58+
)
59+
parser.add_argument(
60+
"--fail-licenses",
61+
help="a list of licenses to fail (compat=False)",
62+
nargs="+",
63+
)
64+
parser.add_argument(
65+
"--only-licenses",
66+
help="a list of allowed licenses (any other license will fail)",
67+
nargs="+",
68+
)
69+
parser.add_argument(
70+
"--skip-dependencies",
71+
help="a list of packages to skip (compat=True)",
72+
nargs="+",
73+
)
74+
parser.add_argument(
75+
"--hide-output-parameters",
76+
help="a list of parameters to hide from the produced output",
77+
nargs="+",
78+
)
79+
parser.add_argument(
80+
"--zero",
81+
"-0",
82+
help="Return non zero exit code if an incompatible license is found",
83+
action="store_true",
84+
)
85+
args = vars(parser.parse_args())
86+
sysexit(main(args))
87+
88+
89+
def main(args: dict) -> int:
90+
"""Test entry point."""
91+
exitCode = 0
92+
93+
# ConfigParser (Parses in the following order: `pyproject.toml`,
94+
# `setup.cfg`, `licensecheck.toml`, `licensecheck.json`,
95+
# `licensecheck.ini`, `~/licensecheck.toml`, `~/licensecheck.json`, `~/licensecheck.ini`)
96+
configparser = FHConfParser()
97+
namespace = ["tool"]
98+
configparser.parseConfigList(
99+
[("pyproject.toml", "toml"), ("setup.cfg", "ini")]
100+
+ [
101+
(f"{directory}/licensecheck.{ext}", ext)
102+
for ext in ("toml", "json", "ini")
103+
for directory in [".", str(Path.home())]
104+
],
105+
namespace,
106+
namespace,
107+
)
108+
simpleConf = SimpleConf(configparser, "licensecheck", args)
109+
110+
# File
111+
textIO = (
112+
stdout
113+
if simpleConf.get("file") is None
114+
else Path(simpleConf.get("file")).open("w", encoding="utf-8")
115+
)
116+
117+
# Get list of licenses
118+
myLice, depsWithLicenses = get_deps.getDepsWithLicenses(
119+
simpleConf.get("using", "poetry"),
120+
list(map(types.ucstr, simpleConf.get("ignore_packages", []))),
121+
list(map(types.ucstr, simpleConf.get("fail_packages", []))),
122+
list(map(types.ucstr, simpleConf.get("ignore_licenses", []))),
123+
list(map(types.ucstr, simpleConf.get("fail_licenses", []))),
124+
list(map(types.ucstr, simpleConf.get("only_licenses", []))),
125+
list(map(types.ucstr, simpleConf.get("skip_dependencies", []))),
126+
)
127+
128+
myLice = license_matrix.licenseType(args["license"])[0] if args.get("license") else myLice
129+
130+
# Are any licenses incompatible?
131+
incompatible = any(not lice.licenseCompat for lice in depsWithLicenses)
132+
133+
# Format the results
134+
hide_output_parameters = [types.ucstr(x) for x in simpleConf.get("hide_output_parameters", [])]
135+
available_params = [param.name.upper() for param in fields(types.PackageInfo)]
136+
if not all(hop in available_params for hop in hide_output_parameters):
137+
msg = (
138+
f"Invalid parameter(s) in `hide_output_parameters`. "
139+
f"Valid parameters are: {', '.join(available_params)}"
140+
)
141+
raise ValueError(msg)
142+
if simpleConf.get("format", "simple") in formatter.formatMap:
143+
print(
144+
formatter.formatMap[simpleConf.get("format", "simple")](
145+
myLice,
146+
sorted(depsWithLicenses),
147+
hide_output_parameters,
148+
),
149+
file=textIO,
150+
)
151+
else:
152+
exitCode = 2
153+
154+
# Exit code of 1 if args.zero
155+
if simpleConf.get("zero", False) and incompatible:
156+
exitCode = 1
157+
158+
# Cleanup + exit
159+
if simpleConf.get("file") is not None:
160+
textIO.close()
161+
return exitCode

0 commit comments

Comments
 (0)