Skip to content

Commit d0e061e

Browse files
committed
Rename gen --license-notice-text-location #367
* Rename gen --license-notice-text-location to --reference * Renamere license_notice_text_location arg and variable name to reference_dir everywhere. * Update and refine the command help help for the gen subcommand. Signed-off-by: Philippe Ombredanne <[email protected]>
1 parent b956107 commit d0e061e

File tree

7 files changed

+73
-83
lines changed

7 files changed

+73
-83
lines changed

src/attributecode/cmd.py

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -246,26 +246,19 @@ def inventory(location, output, mapping, mapping_file,
246246
@click.option('--fetch-license',
247247
nargs=2,
248248
type=str,
249-
metavar='KEY',
250-
help='Fetch license data and texts from a a DejaCode License Library API. '
251-
'Create <license>.LICENSE files from the text of each license key '
252-
'side-by-side with the generated .ABOUT file. Also enhance the .ABOUT '
253-
'file with other data such name and category.\n\n'
254-
'The following additional options are required:\n\n'
255-
'api_url - URL to the DejaCode License Library API endpoint\n\n'
256-
'api_key - DejaCode API key'
257-
'\nExample syntax:\n\n'
258-
"about gen --fetch-license 'api_url' 'api_key'")
259-
260-
# TODO: this option help and long name is obscure and would need to be refactored
261-
@click.option('--license-notice-text-location',
262-
type=click.Path(exists=True, dir_okay=True, readable=True, resolve_path=True),
263-
help="Copy the 'license_file' from the directory to the generated location.")
249+
metavar='URL KEY',
250+
help='Fetch license data and text files from a DejaCode License Library '
251+
'API URL using the API KEY.')
252+
253+
@click.option('--reference',
254+
metavar='DIR',
255+
type=click.Path(exists=True, file_okay=False, readable=True, resolve_path=True),
256+
help='Path to a directory with reference license data and text files.')
264257

265258
@click.option('--mapping',
266259
is_flag=True,
267260
help='Use the default file mapping.config (./attributecode/mapping.config) '
268-
'with mapping between input keys and ABOUT field names.')
261+
'with mapping between input keys and ABOUT field names.')
269262

270263
@click.option('--mapping-file',
271264
metavar='FILE',
@@ -284,7 +277,7 @@ def inventory(location, output, mapping, mapping_file,
284277

285278
def gen(location, output,
286279
fetch_license,
287-
license_notice_text_location,
280+
reference,
288281
mapping, mapping_file,
289282
quiet, verbose):
290283
"""
@@ -309,7 +302,7 @@ def gen(location, output,
309302
errors, abouts = generate_about_files(
310303
location=location,
311304
base_dir=output,
312-
license_notice_text_location=license_notice_text_location,
305+
reference_dir=reference,
313306
fetch_license=fetch_license,
314307
mapping_file=mapping_file
315308
)

src/attributecode/gen.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,22 +101,25 @@ def check_duplicated_about_file_path(inventory_dict):
101101
return errors
102102

103103
# TODO: this should be either the CSV or the ABOUT files but not both???
104-
def load_inventory(location, base_dir, license_notice_text_location=None,
105-
mapping_file=None):
104+
def load_inventory(location, base_dir, reference_dir=None,
105+
mapping_file=None):
106106
"""
107107
Load the inventory file at `location` for ABOUT and LICENSE files
108108
stored in the `base_dir`. Return a list of errors and a list of
109109
About objects validated against the `base_dir`.
110-
Optionally use `license_notice_text_location` as the location of
111-
license and notice texts.
110+
111+
Optionally use `reference_dir` as the directory location of
112+
reference license and notice files to reuse.
112113
113114
Optionally use mappings for field names if `mapping_file` is provided for
114115
the CSV format.
115116
"""
116117
errors = []
117118
abouts = []
118119
base_dir = util.to_posix(base_dir)
120+
# FIXME: do not mix up CSV and JSON
119121
if location.endswith('.csv'):
122+
# FIXME: this should not be done here.
120123
dup_cols_err = check_duplicated_columns(location)
121124
if dup_cols_err:
122125
errors.extend(dup_cols_err)
@@ -126,6 +129,7 @@ def load_inventory(location, base_dir, license_notice_text_location=None,
126129
inventory = util.load_json(location)
127130

128131
try:
132+
# FIXME: this should not be done here.
129133
dup_about_paths_err = check_duplicated_about_file_path(inventory)
130134
if dup_about_paths_err:
131135
errors.extend(dup_about_paths_err)
@@ -157,6 +161,7 @@ def load_inventory(location, base_dir, license_notice_text_location=None,
157161
return errors, abouts
158162
afp = fields.get(model.About.about_file_path_attr)
159163

164+
# FIXME: this should not be a failure condition
160165
if not afp or not afp.strip():
161166
msg = 'Empty column: %(afp)r. Cannot generate .ABOUT file.' % locals()
162167
errors.append(Error(ERROR, msg))
@@ -172,7 +177,7 @@ def load_inventory(location, base_dir, license_notice_text_location=None,
172177
base_dir,
173178
running_inventory,
174179
mapping_file,
175-
license_notice_text_location,
180+
reference_dir,
176181
with_empty=False
177182
)
178183
# 'about_resource' field will be generated during the process.
@@ -184,10 +189,11 @@ def load_inventory(location, base_dir, license_notice_text_location=None,
184189
if not e in errors:
185190
errors.extend(ld_errors)
186191
abouts.append(about)
192+
187193
return unique(errors), abouts
188194

189195

190-
def generate(location, base_dir, license_notice_text_location=None,
196+
def generate(location, base_dir, reference_dir=None,
191197
fetch_license=False, policy=None, conf_location=None,
192198
with_empty=False, with_absent=False, mapping_file=None):
193199
"""
@@ -200,18 +206,20 @@ def generate(location, base_dir, license_notice_text_location=None,
200206
api_url = ''
201207
api_key = ''
202208
gen_license = False
209+
# FIXME: use two different arguments: key and url
203210
# Check if the fetch_license contains valid argument
204211
if fetch_license:
205212
# Strip the ' and " for api_url, and api_key from input
206213
api_url = fetch_license[0].strip("'").strip('"')
207214
api_key = fetch_license[1].strip("'").strip('"')
208215
gen_license = True
209216

217+
# TODO: WHY?
210218
bdir = to_posix(base_dir)
211219
errors, abouts = load_inventory(
212220
location=location,
213221
base_dir=bdir,
214-
license_notice_text_location=license_notice_text_location,
222+
reference_dir=reference_dir,
215223
mapping_file=mapping_file)
216224

217225
if gen_license:

src/attributecode/model.py

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@
3434
import os
3535
# FIXME: why posixpath???
3636
import posixpath
37+
import re
3738

3839
import yaml
39-
import re
4040

4141
from attributecode.util import python2
4242

@@ -420,7 +420,7 @@ def _validate(self, *args, **kwargs):
420420
self.about_file_path = kwargs.get('about_file_path')
421421
self.running_inventory = kwargs.get('running_inventory')
422422
self.base_dir = kwargs.get('base_dir')
423-
self.license_notice_text_location = kwargs.get('license_notice_text_location')
423+
self.reference_dir = kwargs.get('reference_dir')
424424

425425
if self.base_dir:
426426
self.base_dir = util.to_posix(self.base_dir)
@@ -447,16 +447,16 @@ def _validate(self, *args, **kwargs):
447447
# the license files, if need to be copied, are located under the path
448448
# set from the 'license-text-location' option, so the tool should check
449449
# at the 'license-text-location' instead of the 'base_dir'
450-
if not (self.base_dir or self.license_notice_text_location):
450+
if not (self.base_dir or self.reference_dir):
451451
msg = (u'Field %(name)s: Unable to verify path: %(path)s:'
452452
u' No base directory provided' % locals())
453453
errors.append(Error(ERROR, msg))
454454
location = None
455455
paths[path] = location
456456
continue
457457

458-
if self.license_notice_text_location:
459-
location = posixpath.join(self.license_notice_text_location, path)
458+
if self.reference_dir:
459+
location = posixpath.join(self.reference_dir, path)
460460
else:
461461
# The 'about_resource' should be a joined path with
462462
# the 'about_file_path' and the 'base_dir
@@ -669,7 +669,7 @@ def __eq__(self, other):
669669

670670

671671
def validate_fields(fields, about_file_path, running_inventory, base_dir,
672-
license_notice_text_location=None):
672+
reference_dir=None):
673673
"""
674674
Validate a sequence of Field objects. Return a list of errors.
675675
Validation may update the Field objects as needed as a side effect.
@@ -680,7 +680,7 @@ def validate_fields(fields, about_file_path, running_inventory, base_dir,
680680
base_dir=base_dir,
681681
about_file_path=about_file_path,
682682
running_inventory=running_inventory,
683-
license_notice_text_location=license_notice_text_location,
683+
reference_dir=reference_dir,
684684
)
685685
errors.extend(val_err)
686686
return errors
@@ -972,28 +972,29 @@ def hydrate(self, fields, mapping_file=None):
972972
return errors
973973

974974
def process(self, fields, about_file_path, running_inventory=False,
975-
base_dir=None, license_notice_text_location=None,
975+
base_dir=None, reference_dir=None,
976976
mapping_file=None):
977977
"""
978-
Hydrate and validate a sequence of field name/value tuples from an
979-
ABOUT file. Return a list of errors.
978+
Validate and set as attributes on this About object a sequence of
979+
`fields` name/value tuples. Return a list of errors.
980980
"""
981981
self.base_dir = base_dir
982-
self.license_notice_text_location = license_notice_text_location
982+
self.reference_dir = reference_dir
983983
afp = self.about_file_path
984984
errors = []
985985
hydratation_errors = self.hydrate(fields, mapping_file=mapping_file)
986986
errors.extend(hydratation_errors)
987987

988988
# We want to copy the license_files before the validation
989-
if license_notice_text_location:
989+
if reference_dir:
990990
copy_license_notice_files(
991-
fields, base_dir, license_notice_text_location, afp)
991+
fields, base_dir, reference_dir, afp)
992+
992993
# we validate all fields, not only these hydrated
993994
all_fields = self.all_fields()
994995
validation_errors = validate_fields(
995996
all_fields, about_file_path, running_inventory,
996-
self.base_dir, self.license_notice_text_location)
997+
self.base_dir, self.reference_dir)
997998
errors.extend(validation_errors)
998999

9991000
# do not forget to resolve about resource paths The
@@ -1043,12 +1044,10 @@ def load(self, location, mapping_file=None):
10431044
# FIXME: an About object should not know about mappings
10441045
def load_dict(self, fields_dict, base_dir, running_inventory=False,
10451046
mapping_file=None,
1046-
license_notice_text_location=None, with_empty=True):
1047+
reference_dir=None, with_empty=True):
10471048
"""
1048-
Load the ABOUT file from a fields name/value mapping.
1049-
If with_empty, create fields with no value for empty fields.
1050-
Return a list of
1051-
errors.
1049+
Load this About object file from a `fields_dict` name/value mapping.
1050+
Return a list of errors.
10521051
"""
10531052
fields = list(fields_dict.items())
10541053
about_file_path = self.about_file_path
@@ -1076,7 +1075,7 @@ def load_dict(self, fields_dict, base_dir, running_inventory=False,
10761075
about_file_path=about_file_path,
10771076
running_inventory=running_inventory,
10781077
base_dir=base_dir,
1079-
license_notice_text_location=license_notice_text_location,
1078+
reference_dir=reference_dir,
10801079
mapping_file=mapping_file)
10811080
self.errors = errors
10821081
return errors
@@ -1193,7 +1192,7 @@ def dump_lic(self, location, license_dict):
11931192
# valid field name
11941193
field_name = r'(?P<name>[a-z][0-9a-z_]*)'
11951194

1196-
valid_field_name = re.compile(field_name, re.UNICODE | re.IGNORECASE).match
1195+
valid_field_name = re.compile(field_name, re.UNICODE | re.IGNORECASE).match # NOQA
11971196

11981197
# line in the form of "name: value"
11991198
field_declaration = re.compile(
@@ -1202,7 +1201,7 @@ def dump_lic(self, location, license_dict):
12021201
r'\s*:\s*'
12031202
r'(?P<value>.*)'
12041203
r'\s*$'
1205-
, re.UNICODE | re.IGNORECASE
1204+
, re.UNICODE | re.IGNORECASE # NOQA
12061205
).match
12071206

12081207

@@ -1212,7 +1211,7 @@ def dump_lic(self, location, license_dict):
12121211
r' '
12131212
r'(?P<value>.*)'
12141213
r'\s*$'
1215-
, re.UNICODE | re.IGNORECASE
1214+
, re.UNICODE | re.IGNORECASE # NOQA
12161215
).match
12171216

12181217

src/attributecode/util.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -598,13 +598,21 @@ def add_unc(location):
598598

599599

600600
# FIXME: add docstring
601-
def copy_license_notice_files(fields, base_dir, license_notice_text_location, afp):
601+
def copy_license_notice_files(fields, base_dir, reference_dir, afp):
602+
"""
603+
Given a list of (key, value) `fields` tuples and a `base_dir` where ABOUT
604+
files and their companion LICENSe are store, and an extra `reference_dir`
605+
where reference license an notice files are stored and the `afp`
606+
about_file_path value, this function will copy to the base_dir the
607+
license_file or notice_file if found in the reference_dir
608+
609+
"""
602610
lic_name = ''
603611
for key, value in fields:
604612
if key == 'license_file' or key == 'notice_file':
605613
lic_name = value
606614

607-
from_lic_path = posixpath.join(to_posix(license_notice_text_location), lic_name)
615+
from_lic_path = posixpath.join(to_posix(reference_dir), lic_name)
608616
about_file_dir = os.path.dirname(to_posix(afp)).lstrip('/')
609617
to_lic_path = posixpath.join(to_posix(base_dir), about_file_dir)
610618

tests/test_gen.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,11 @@ def test_generate(self):
177177
def test_generate_not_overwrite_original_license_file(self):
178178
location = get_test_loc('test_gen/inv5.csv')
179179
base_dir = get_temp_dir()
180-
license_notice_text_location = None
180+
reference_dir = None
181181
fetch_license = ['url', 'lic_key']
182182

183183
_errors, abouts = gen.generate(
184-
location, base_dir, license_notice_text_location, fetch_license)
184+
location, base_dir, reference_dir, fetch_license)
185185

186186
in_mem_result = [a.dumps(with_empty=False)for a in abouts][0]
187187
expected = (

tests/test_model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
from testing_utils import get_test_loc
4545

4646

47-
def check_csv(expected, result, regen=True):
47+
def check_csv(expected, result, regen=False):
4848
"""
4949
Assert that the contents of two CSV files locations `expected` and
5050
`result` are equal.

tests/testdata/test_cmd/help/about_gen_help.txt

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,15 @@ Usage: about gen [OPTIONS] LOCATION OUTPUT
88
OUTPUT: Path to a directory where ABOUT files are generated.
99

1010
Options:
11-
--fetch-license KEY Fetch license data and texts from a a DejaCode
12-
License Library API. Create <license>.LICENSE
13-
files from the text of each license key side-
14-
by-side with the generated .ABOUT file. Also
15-
enhance the .ABOUT file with other data such
16-
name and category.
17-
18-
The following additional
19-
options are required:
20-
21-
api_url - URL to the
22-
DejaCode License Library API endpoint
23-
24-
api_key
25-
- DejaCode API key
26-
Example syntax:
27-
28-
about gen
29-
--fetch-license 'api_url' 'api_key'
30-
--license-notice-text-location PATH
31-
Copy the 'license_file' from the directory to
32-
the generated location.
33-
--mapping Use the default file mapping.config
34-
(./attributecode/mapping.config) with mapping
35-
between input keys and ABOUT field names.
36-
--mapping-file FILE Use a custom mapping file with mapping between
37-
input keys and ABOUT field names.
38-
-q, --quiet Do not print error or warning messages.
39-
--verbose Show all error and warning messages.
40-
-h, --help Show this message and exit.
11+
--fetch-license URL KEY Fetch license data and text files from a DejaCode
12+
License Library API URL using the API KEY.
13+
--reference DIR Path to a directory with reference license data and
14+
text files.
15+
--mapping Use the default file mapping.config
16+
(./attributecode/mapping.config) with mapping between
17+
input keys and ABOUT field names.
18+
--mapping-file FILE Use a custom mapping file with mapping between input
19+
keys and ABOUT field names.
20+
-q, --quiet Do not print error or warning messages.
21+
--verbose Show all error and warning messages.
22+
-h, --help Show this message and exit.

0 commit comments

Comments
 (0)