Skip to content

Commit 8fe489c

Browse files
committed
Merge branch 'license_expression_support' into develop
2 parents f430374 + ce1913f commit 8fe489c

File tree

12 files changed

+199
-91
lines changed

12 files changed

+199
-91
lines changed

src/attributecode/attrib.py

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# -*- coding: utf8 -*-
33

44
# ============================================================================
5-
# Copyright (c) 2013-2016 nexB Inc. http://www.nexb.com/ - All rights reserved.
5+
# Copyright (c) 2013-2017 nexB Inc. http://www.nexb.com/ - All rights reserved.
66
# Licensed under the Apache License, Version 2.0 (the "License");
77
# you may not use this file except in compliance with the License.
88
# You may obtain a copy of the License at
@@ -18,6 +18,7 @@
1818
from __future__ import print_function
1919

2020
import codecs
21+
import collections
2122
import jinja2
2223
import os
2324
from posixpath import basename
@@ -29,6 +30,7 @@
2930
from attributecode import ERROR
3031
from attributecode import Error
3132
from attributecode.licenses import COMMON_LICENSES
33+
from attributecode.model import parse_license_expression
3234
from attributecode.util import add_unc
3335

3436

@@ -46,7 +48,10 @@ def generate(abouts, template_string=None):
4648
try:
4749
captured_license = []
4850
license_key_and_context = {}
51+
sorted_license_key_and_context = {}
4952
license_text_name_and_key = {}
53+
license_key_to_license_name = {}
54+
# FIXME: This need to be simplified
5055
for about in abouts:
5156
# about.license_file.value is a OrderDict with license_text_name as
5257
# the key and the license text as the value
@@ -61,10 +66,40 @@ def generate(abouts, template_string=None):
6166
else:
6267
license_key = license_text_name
6368
license_key_and_context[license_key] = about.license_file.value[license_text_name]
69+
sorted_license_key_and_context = collections.OrderedDict(sorted(license_key_and_context.items()))
6470
license_text_name_and_key[license_text_name] = license_key
6571

66-
rendered = template.render(abouts=abouts, common_licenses=COMMON_LICENSES, license_key_and_context=license_key_and_context,
67-
license_text_name_and_key=license_text_name_and_key)
72+
# Convert/map the key in license expression to license name
73+
if about.license_expression.value and about.license_name.value:
74+
# Split the license expression into list with license key and condition keyword
75+
lic_expression_list = about.license_expression.value.split()
76+
77+
78+
lic_name_list = about.license_name.value
79+
lic_name_expression_list = []
80+
81+
# The order of the license_name and key should be the same
82+
# The length for both list should be the same excluding the condition keyword
83+
# such as 'and' and 'or'
84+
assert len(lic_name_list) <= len(lic_expression_list)
85+
86+
# Map the licence key to license name
87+
index_for_license_name_list = 0
88+
for key in lic_expression_list:
89+
if key.lower() == 'and' or key.lower() == 'or':
90+
lic_name_expression_list.append(key)
91+
else:
92+
lic_name_expression_list.append(lic_name_list[index_for_license_name_list])
93+
license_key_to_license_name[key] = lic_name_list[index_for_license_name_list]
94+
index_for_license_name_list = index_for_license_name_list + 1
95+
# Join the license name expression into a single string
96+
lic_name_expression = ' '.join(lic_name_expression_list)
97+
98+
# Add the license name expression string into the about object
99+
about.license_name_expression = lic_name_expression
100+
101+
rendered = template.render(abouts=abouts, common_licenses=COMMON_LICENSES, license_key_and_context=sorted_license_key_and_context,
102+
license_text_name_and_key=license_text_name_and_key, license_key_to_license_name=license_key_to_license_name)
68103
except Exception, e:
69104
line = getattr(e, 'lineno', None)
70105
ln_msg = ' at line: %r' % line if line else ''
@@ -167,6 +202,17 @@ def generate_and_save(abouts, output_location, mapping, template_loc=None,
167202
if about.about_file_path == fp:
168203
updated_abouts.append(about)
169204

205+
# Parse license_expression and save to the license list
206+
for about in updated_abouts:
207+
if about.license_expression.value:
208+
special_char_in_expression, lic_list = parse_license_expression(about.license_expression.value)
209+
if special_char_in_expression:
210+
msg = (u"The following character(s) cannot be in the licesne_expression: " +
211+
str(special_char_in_expression))
212+
errors.append(Error(ERROR, msg))
213+
else:
214+
about.license.value = lic_list
215+
170216
rendered = generate_from_file(updated_abouts, template_loc=template_loc)
171217

172218
if rendered:

src/attributecode/cmd.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# -*- coding: utf8 -*-
33

44
# ============================================================================
5-
# Copyright (c) 2013-2016 nexB Inc. http://www.nexb.com/ - All rights reserved.
5+
# Copyright (c) 2013-2017 nexB Inc. http://www.nexb.com/ - All rights reserved.
66
# Licensed under the Apache License, Version 2.0 (the "License");
77
# you may not use this file except in compliance with the License.
88
# You may obtain a copy of the License at
@@ -136,12 +136,12 @@ def inventory(location, output, quiet, format):
136136
'\nExample syntax:\n\n'
137137
"about gen --fetch-license 'api_url' 'api_key'")
138138
)
139-
@click.option('--license-text-location', nargs=1,
139+
@click.option('--license-notice-text-location', nargs=1,
140140
type=click.Path(exists=True, dir_okay=True, readable=True, resolve_path=True),
141141
help="Copy the 'license_file' from the directory to the generated location")
142142
@click.option('--mapping', is_flag=True, help='Use for mapping between the input keys and the ABOUT field names - mapping.config')
143143
@click.option('-q', '--quiet', is_flag=True, help='Do not print any error/warning.')
144-
def gen(location, output, mapping, license_text_location, fetch_license, quiet):
144+
def gen(location, output, mapping, license_notice_text_location, fetch_license, quiet):
145145
"""
146146
Given an inventory of ABOUT files at location, generate ABOUT files in base
147147
directory.
@@ -156,7 +156,7 @@ def gen(location, output, mapping, license_text_location, fetch_license, quiet):
156156
return
157157
click.echo('Generating ABOUT files...')
158158

159-
errors, abouts = attributecode.gen.generate(location, output, mapping, license_text_location, fetch_license)
159+
errors, abouts = attributecode.gen.generate(location, output, mapping, license_notice_text_location, fetch_license)
160160

161161
number_of_about_file = len(abouts)
162162
number_of_error = 0

src/attributecode/gen.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def check_duplicated_about_file_path(inventory_dict):
9797
return errors
9898

9999

100-
def load_inventory(mapping, location, base_dir, license_text_location=None):
100+
def load_inventory(mapping, location, base_dir, license_notice_text_location=None):
101101
"""
102102
Load the inventory file at location. Return a list of errors and a list of About
103103
objects validated against the base_dir.
@@ -150,7 +150,7 @@ def load_inventory(mapping, location, base_dir, license_text_location=None):
150150
loc = posixpath.join(base_dir, afp)
151151
about = model.About(about_file_path=afp)
152152
about.location = loc
153-
ld_errors = about.load_dict(fields, base_dir, license_text_location, with_empty=False)
153+
ld_errors = about.load_dict(fields, base_dir, license_notice_text_location, with_empty=False)
154154
# 'about_resource' field will be generated during the process.
155155
# No error need to be raise for the missing 'about_resource'.
156156
for e in ld_errors:
@@ -163,7 +163,7 @@ def load_inventory(mapping, location, base_dir, license_text_location=None):
163163
return errors, abouts
164164

165165

166-
def generate(location, base_dir, mapping, license_text_location, fetch_license, policy=None, conf_location=None,
166+
def generate(location, base_dir, mapping, license_notice_text_location, fetch_license, policy=None, conf_location=None,
167167
with_empty=False, with_absent=False):
168168
"""
169169
Load ABOUT data from an inventory at csv_location. Write ABOUT files to
@@ -182,7 +182,7 @@ def generate(location, base_dir, mapping, license_text_location, fetch_license,
182182
gen_license = True
183183

184184
bdir = to_posix(base_dir)
185-
errors, abouts = load_inventory(mapping, location, bdir, license_text_location)
185+
errors, abouts = load_inventory(mapping, location, bdir, license_notice_text_location)
186186

187187
if gen_license:
188188
license_dict, err = model.pre_process_and_fetch_license_dict(abouts, api_url, api_key)
@@ -239,10 +239,14 @@ def generate(location, base_dir, mapping, license_text_location, fetch_license,
239239
gen_license_name = lic_key + u'.LICENSE'
240240
about.license_file.value[gen_license_name] = lic_context
241241
about.license_file.present = True
242+
if not about.license_name.present:
243+
about.license_name.value.append(lic_name)
242244
if not about.license_url.present:
243245
about.license_url.value.append(lic_url)
244246
if about.license_url.value:
245247
about.license_url.present = True
248+
if about.license_name.value:
249+
about.license_name.present = True
246250

247251
# Write the ABOUT file and check does the referenced file exist
248252
# This function is not purposed to throw error. However, since I've commented

0 commit comments

Comments
 (0)