Skip to content

Commit 5d2753d

Browse files
committed
Refactor plugin
* Group holders and licenses together when counting * Check to see if copyrights or licenses is an attribute instead of requiring the copyright or license option to run the plugin Signed-off-by: Jono Yang <jyang@nexb.com>
1 parent 9291978 commit 5d2753d

1 file changed

Lines changed: 64 additions & 59 deletions

File tree

src/scancode/plugin_summary.py

Lines changed: 64 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,35 @@
3232

3333
import attr
3434

35+
from packagedcode.utils import combine_expressions
3536
from plugincode.post_scan import PostScanPlugin
3637
from plugincode.post_scan import post_scan_impl
3738
from scancode import CommandLineOption
3839
from scancode import POST_SCAN_GROUP
3940

4041

42+
# Tracing flags
43+
TRACE = True
44+
45+
46+
def logger_debug(*args):
47+
pass
48+
49+
50+
if TRACE:
51+
import logging
52+
import sys
53+
54+
logger = logging.getLogger(__name__)
55+
# logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
56+
logging.basicConfig(stream=sys.stdout)
57+
logger.setLevel(logging.DEBUG)
58+
59+
def logger_debug(*args):
60+
return logger.debug(
61+
' '.join(isinstance(a, unicode) and a or repr(a) for a in args))
62+
63+
4164
@post_scan_impl
4265
class OriginSummary(PostScanPlugin):
4366
"""
@@ -46,24 +69,27 @@ class OriginSummary(PostScanPlugin):
4669
"""
4770
resource_attributes = dict(
4871
origin_summary=attr.ib(default=attr.Factory(OrderedDict)),
49-
is_summary=attr.ib(default=False, type=bool),
50-
is_summarized=attr.ib(default=False, type=bool)
72+
summarized_to=attr.ib(default=None, type=str)
5173
)
5274

5375
sort_order = 8
5476

5577
options = [
5678
CommandLineOption(('--origin-summary',),
5779
is_flag=True, default=False,
58-
required_options=['copyright','license'],
5980
help='Origin summary',
6081
help_group=POST_SCAN_GROUP)
6182
]
6283

63-
def is_enabled(self, origin_summary, copyright, license, **kwargs):
64-
return origin_summary and copyright and license
84+
def is_enabled(self, origin_summary, **kwargs):
85+
return origin_summary
6586

6687
def process_codebase(self, codebase, **kwargs):
88+
root = codebase.get_resource(0)
89+
if not hasattr(root, 'copyrights') or not hasattr(root, 'licenses'):
90+
# TODO: Raise warning(?) if these fields are not there
91+
return
92+
6793
for resource in codebase.walk(topdown=False):
6894
# TODO: Consider facets for later
6995
# TODO: Group summarizations by copyright holders and license expressions
@@ -75,64 +101,43 @@ def process_codebase(self, codebase, **kwargs):
75101
if not children:
76102
continue
77103

78-
dir_license_expressions_count = Counter()
79-
dir_holders_count = Counter()
104+
# TODO: Consider using a list of resource id's to avoid walking a codebase multiple times
105+
origin_count = Counter()
80106

81107
for child in children:
82-
for license_expression in child.license_expressions:
83-
if child.is_file:
84-
license_expressions_count = 1
85-
else:
86-
child_license_expressions_count = child.origin_summary.get('license_expressions')
87-
license_expressions_count = child_license_expressions_count[license_expression]
88-
dir_license_expressions_count.update({license_expression: license_expressions_count})
89-
90-
for holder in child.holders:
91-
holder_value = holder['value']
92-
if child.is_file:
93-
holder_count = 1
94-
else:
95-
child_holders_count = child.origin_summary.get('holders')
96-
holder_count = child_holders_count[holder_value]
97-
dir_holders_count.update({holder_value: holder_count})
98-
99-
file_count = resource.files_count
100-
101-
# TODO: Check for contradictions when performing summarizations
102-
for k, v in dir_license_expressions_count.items():
103-
if is_majority(v, file_count):
104-
resource.license_expressions.append(k)
105-
resource.is_summary = True
108+
if child.is_file:
109+
license_expression = combine_expressions(child.license_expressions)
110+
holders = tuple(h['value'] for h in child.holders if h['value'])
111+
if not license_expression or not holders:
112+
continue
113+
origin = holders, license_expression
114+
origin_count[origin] += 1
115+
else:
116+
# We are in a subdirectory
117+
child_origin_count = child.extra_data.get('origin_count', {})
118+
origin_count.update(child_origin_count)
119+
120+
if origin_count:
121+
resource.extra_data['origin_count'] = origin_count
122+
resource.save(codebase)
123+
(holders, license_expression), top_count = origin_count.most_common(1)[0]
124+
# TODO: Check for contradictions when performing summarizations
125+
if is_majority(top_count, resource.files_count):
126+
resource.origin_summary['license_expression'] = license_expression
127+
resource.origin_summary['holders'] = holders
128+
resource.origin_summary['count'] = top_count
106129
codebase.save_resource(resource)
107130

108-
for k, v in dir_holders_count.items():
109-
if is_majority(v, file_count):
110-
resource.holders.append(OrderedDict(value=k, start_line=None, end_line=None))
111-
resource.is_summary = True
112-
codebase.save_resource(resource)
113-
114-
resource.origin_summary['license_expressions'] = dir_license_expressions_count
115-
resource.origin_summary['holders'] = dir_holders_count
116-
codebase.save_resource(resource)
117-
118-
# Pass 2: tag the Resources that have been summarized
119-
for resource in codebase.walk(topdown=True):
120-
if resource.is_file or not resource.is_summary:
121-
continue
122-
123-
children = resource.children(codebase)
124-
if not children:
125-
continue
126-
127-
# TODO: There's probably a more pleasing way to do this
128-
for child in children:
129-
for child_license_expression in child.license_expressions:
130-
for child_holder in child.holders:
131-
for resource_holder in resource.holders:
132-
if (child_license_expression in resource.license_expressions
133-
and child_holder['value'] == resource_holder['value']):
134-
child.is_summarized = True
135-
codebase.save_resource(child)
131+
for descendant in resource.walk(codebase, topdown=True):
132+
if descendant.is_file:
133+
d_license_expression = combine_expressions(descendant.license_expressions)
134+
d_holders = tuple(h['value'] for h in descendant.holders)
135+
else:
136+
d_license_expression = descendant.origin_summary.get('license_expression')
137+
d_holders = descendant.origin_summary.get('holders')
138+
if (d_holders, d_license_expression) == (holders, license_expression):
139+
descendant.summarized_to = resource.path
140+
descendant.save(codebase)
136141

137142

138143
def is_majority(count, files_count):

0 commit comments

Comments
 (0)