Skip to content

Commit d3bd629

Browse files
author
Olivier Chédru
authored
Merge pull request #85 from ticdenis/master
support pyproject.toml for loading dependencies from [project.dependencies] and [project.optional-dependencies]
2 parents d322ef6 + a09e62b commit d3bd629

File tree

3 files changed

+126
-13
lines changed

3 files changed

+126
-13
lines changed

README.rst

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,64 @@ If some dependencies are unknown or are not matching the strategy, the output wi
135135
dependency:
136136
feedparser
137137

138+
Also supports pyproject.toml like:
139+
::
140+
141+
[project]
142+
dependencies = [
143+
"Flask>=0.12.1",
144+
"flask_restful",
145+
"jsonify",
146+
"psycopg2>=2.7.1",
147+
"nose",
148+
"scipy",
149+
"scikit-learn",
150+
"pandas",
151+
"numpy",
152+
"argparse",
153+
"uuid",
154+
"sqlbuilder",
155+
"proboscis",
156+
"pyyaml>=3.12",
157+
]
158+
159+
[project.optional-dependencies]
160+
test = [
161+
"pytest>=3.6.3",
162+
]
163+
164+
[tool.liccheck]
165+
authorized_licenses = [
166+
"bsd",
167+
"new bsd",
168+
"bsd license",
169+
"new bsd license",
170+
"simplified bsd",
171+
"apache",
172+
"apache 2.0",
173+
"apache software license",
174+
"gnu lgpl",
175+
"lgpl with exceptions or zpl",
176+
"isc license",
177+
"isc license (iscl)",
178+
"mit",
179+
"mit license",
180+
"python software foundation license",
181+
"zpl 2.1",
182+
]
183+
unauthorized_licenses = [
184+
"gpl v3",
185+
]
186+
# strategy_ini_file = "./liccheck.ini"
187+
# level = "STANDARD"
188+
# requirement_txt_file = "./requirements.txt" # ignored if dependencies or optional_dependencies are defined
189+
# reporting_txt_file = "path/to/reporting.txt file" # by default is None
190+
# no_deps = false
191+
dependencies = true # to load [project.dependencies]
192+
optional_dependencies = ["test"] # to load extras from [project.optional-dependencies]
193+
194+
[tool.liccheck.authorized_packages]
195+
uuid = 1.30
138196

139197
Using liccheck with pre-commit
140198
==============================

liccheck/__main__.py

100755100644
File mode changed.

liccheck/command_line.py

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
import semantic_version
1717
import toml
1818

19-
import pkg_resources
20-
2119
try:
2220
FileNotFoundError
2321
except NameError:
@@ -28,6 +26,17 @@ class NoValidConfigurationInPyprojectToml(BaseException):
2826
pass
2927

3028

29+
def from_pyproject_toml():
30+
try:
31+
pyproject_toml = toml.load("pyproject.toml")
32+
try:
33+
return pyproject_toml["tool"]["liccheck"]
34+
except KeyError:
35+
raise NoValidConfigurationInPyprojectToml
36+
except FileNotFoundError:
37+
raise NoValidConfigurationInPyprojectToml
38+
39+
3140
class Strategy:
3241
def __init__(self, authorized_licenses, unauthorized_licenses, authorized_packages):
3342
self.AUTHORIZED_LICENSES = authorized_licenses
@@ -36,15 +45,7 @@ def __init__(self, authorized_licenses, unauthorized_licenses, authorized_packag
3645

3746
@classmethod
3847
def from_pyproject_toml(cls):
39-
try:
40-
pyproject_toml = toml.load("pyproject.toml")
41-
except FileNotFoundError:
42-
raise NoValidConfigurationInPyprojectToml
43-
44-
try:
45-
liccheck_section = pyproject_toml["tool"]["liccheck"]
46-
except KeyError:
47-
raise NoValidConfigurationInPyprojectToml
48+
liccheck_section = from_pyproject_toml()
4849

4950
def elements_to_lower_str(lst):
5051
return [str(_).lower() for _ in lst]
@@ -334,9 +335,63 @@ def parse_args(args):
334335
return parser.parse_args(args)
335336

336337

338+
def merge_args(args):
339+
try:
340+
config = from_pyproject_toml()
341+
except NoValidConfigurationInPyprojectToml:
342+
return args
343+
return {
344+
'strategy_ini_file': config.get('strategy_ini_file', args['strategy_ini_file']),
345+
'requirement_txt_file': config.get('requirement_txt_file', args['requirement_txt_file']),
346+
'level': config.get('level', args['level']),
347+
'reporting_txt_file': config.get('reporting_txt_file', args['reporting_txt_file']),
348+
'no_deps': config.get('no_deps', args['no_deps']),
349+
'dependencies': config.get('dependencies', args['dependencies']),
350+
'optional_dependencies': config.get('optional_dependencies', args['optional_dependencies'])
351+
}
352+
353+
354+
def generate_requirements_file_from_pyproject(include_dependencies, extra_dependencies):
355+
import tempfile
356+
directory = tempfile.mkdtemp(prefix='liccheck_')
357+
requirements_txt_file = directory + '/requirements.txt'
358+
with open(requirements_txt_file, 'w') as f:
359+
project = toml.load('pyproject.toml').get('project', {})
360+
dependencies = project.get('dependencies', []) if include_dependencies else []
361+
optional_dependencies = project.get('optional-dependencies', {}) if extra_dependencies else {}
362+
for extra_dependency in extra_dependencies:
363+
if extra_dependency in optional_dependencies:
364+
dependencies += optional_dependencies[extra_dependency]
365+
f.write(os.linesep.join(dependencies))
366+
return requirements_txt_file
367+
368+
337369
def run(args):
338-
strategy = read_strategy(args.strategy_ini_file)
339-
return process(args.requirement_txt_file, strategy, args.level, args.reporting_txt_file, args.no_deps)
370+
args = merge_args({
371+
'strategy_ini_file': args.strategy_ini_file,
372+
'requirement_txt_file': args.requirement_txt_file,
373+
'level': args.level,
374+
'reporting_txt_file': args.reporting_txt_file,
375+
'no_deps': args.no_deps,
376+
'dependencies': False,
377+
'optional_dependencies': []
378+
})
379+
strategy = read_strategy(args['strategy_ini_file'])
380+
requirements_file_generated = False
381+
if args['dependencies'] is True or len(args['optional_dependencies']) > 0:
382+
args['requirement_txt_file'] = generate_requirements_file_from_pyproject(
383+
args['dependencies'],
384+
args['optional_dependencies']
385+
)
386+
requirements_file_generated = True
387+
try:
388+
return process(args['requirement_txt_file'], strategy, args['level'], args['reporting_txt_file'],
389+
args['no_deps'])
390+
finally:
391+
if requirements_file_generated:
392+
import pathlib
393+
import shutil
394+
shutil.rmtree(pathlib.Path(args['requirement_txt_file']).parent, ignore_errors=True)
340395

341396

342397
def main():

0 commit comments

Comments
 (0)