Skip to content

Commit

Permalink
Add 'annotation_type' field to the 'annotation' class
Browse files Browse the repository at this point in the history
Signed-off-by: Yash Nisar <yash.nisar@somaiya.edu>
  • Loading branch information
yash-nisar committed Jun 12, 2018
1 parent 8cb3582 commit c049034
Show file tree
Hide file tree
Showing 14 changed files with 140 additions and 2 deletions.
1 change: 1 addition & 0 deletions data/SPDXRdfExample.rdf
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
</reviewed>
<annotation>
<Annotation>
<annotationType rdf:resource="http://spdx.org/rdf/terms#annotationType_review"/>
<rdfs:comment>This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses</rdfs:comment>
<annotationDate>2012-06-13T00:00:00Z</annotationDate>
<annotator>Person: Jim Reviewer</annotator>
Expand Down
1 change: 1 addition & 0 deletions data/SPDXTagExample.tag
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ReviewComment: <text>Another example reviewer.</text>

## Annotation Information
Annotator: Person: Jim Annotator
AnnotationType: REVIEW
AnnotationDate: 2012-03-11T00:00:00Z
AnnotationComment: <text>An example annotation comment.</text>

Expand Down
2 changes: 2 additions & 0 deletions examples/parse_rdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@
for lics in doc.extracted_licenses:
print '\tIdentifier: {0}'.format(lics.identifier)
print '\tName: {0}'.format(lics.full_name)
for an in doc.annotations:
print an.type

else:
print 'Errors while parsing'
19 changes: 17 additions & 2 deletions spdx/annotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@ class Annotation(object):
(Mandatory, one), if there is an Annotation. Type: datetime.
- comment: Annotation comment. Conditional (Mandatory, one), if there is
an Annotation. Type: str.
- annotation_type: Annotation type. Conditional (Mandatory, one), if there is an
Annotation. Type: str.
"""

def __init__(self, annotator=None, annotation_date=None, comment=None):
def __init__(self, annotator=None, annotation_date=None, comment=None,
annotation_type=None):
self.annotator = annotator
self.annotation_date = annotation_date
self.comment = comment
self.annotation_type = annotation_type

def __eq__(self, other):
return (
Expand Down Expand Up @@ -72,7 +76,8 @@ def validate(self, messages=None):
messages = messages if messages is not None else []

return (self.validate_annotator(messages)
and self.validate_annotation_date(messages))
and self.validate_annotation_date(messages)
and self.validate_annotation_type(messages))

def validate_annotator(self, messages=None):
# FIXME: we should return messages instead
Expand All @@ -93,3 +98,13 @@ def validate_annotation_date(self, messages=None):
else:
messages.append('Annotation missing annotation date.')
return False

def validate_annotation_type(self, messages=None):
# FIXME: we should return messages instead
messages = messages if messages is not None else []

if self.annotation_type is not None:
return True
else:
messages.append('Annotation missing annotation type.')
return False
1 change: 1 addition & 0 deletions spdx/parsers/lexers/tagvalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class Lexer(object):
'Annotator': 'ANNOTATOR',
'AnnotationDate': 'ANNOTATION_DATE',
'AnnotationComment': 'ANNOTATION_COMMENT',
'AnnotationType': 'ANNOTATION_TYPE',
# Package Fields
'PackageName': 'PKG_NAME',
'PackageVersion': 'PKG_VERSION',
Expand Down
15 changes: 15 additions & 0 deletions spdx/parsers/rdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,21 @@ def parse_annotation(self, r_term):
comment = self.get_annotation_comment(r_term)
if comment is not None:
self.builder.add_annotation_comment(self.doc, comment)
annotation_type = self.get_annotation_type(r_term)
self.builder.add_annotation_type(self.doc, annotation_type)

def get_annotation_type(self, r_term):
"""Returns annotation type or None if found none or more than one.
Reports errors on failure."""
for _, _, typ in self.graph.triples((
r_term, self.spdx_namespace['annotationType'], None)):
if typ is not None:
return typ
else:
self.error = True
msg = 'Annotation must have exactly one annotation type.'
self.logger.log(msg)
return

def get_annotation_comment(self, r_term):
"""Returns annotation comment or None if found none or more than one.
Expand Down
21 changes: 21 additions & 0 deletions spdx/parsers/rdfbuilders.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,27 @@ def add_annotation_comment(self, doc, comment):
else:
raise OrderError('AnnotationComment')

def add_annotation_type(self, doc, annotation_type):
"""Sets the annotation type. Raises CardinalityError if
already set. OrderError if no annotator defined before.
"""
if len(doc.annotations) != 0:
if not self.annotation_type_set:
if annotation_type.endswith('annotationType_other'):
self.annotation_type_set = True
doc.annotations[-1].annotation_type = 'OTHER'
return True
elif annotation_type.endswith('annotationType_review'):
self.annotation_type_set = True
doc.annotations[-1].annotation_type = 'REVIEW'
return True
else:
raise SPDXValueError('Annotation::AnnotationType')
else:
raise CardinalityError('Annotation::AnnotationType')
else:
raise OrderError('Annotation::AnnotationType')


class Builder(DocBuilder, EntityBuilder, CreationInfoBuilder, PackageBuilder,
FileBuilder, ReviewBuilder, AnnotationBuilder):
Expand Down
26 changes: 26 additions & 0 deletions spdx/parsers/tagvalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
'ANNOTATOR_VALUE_TYPE': 'Invalid Annotator value must be a Person, Organization or Tool. Line: {0}',
'ANNOTATION_DATE_VALUE_TYPE': 'AnnotationDate value must be date in ISO 8601 format, line: {0}',
'ANNOTATION_COMMENT_VALUE_TYPE': 'AnnotationComment value must be free form text between <text></text> tags, line:{0}',
'ANNOTATION_TYPE_VALUE': 'AnnotationType must be "REVIEW" or "OTHER". Line: {0}',
'A_BEFORE_B': '{0} Can not appear before {1}, line: {2}',
'PACKAGE_NAME_VALUE': 'PackageName must be single line of text, line: {0}',
'PKG_VERSION_VALUE': 'PackageVersion must be single line of text, line: {0}',
Expand Down Expand Up @@ -120,6 +121,7 @@ def p_attrib(self, p):
| annotator
| annotation_date
| annotation_comment
| annotation_type
| package_name
| package_version
| pkg_down_location
Expand Down Expand Up @@ -1092,6 +1094,30 @@ def p_annotation_comment_2(self, p):
msg = ERROR_MESSAGES['ANNOTATION_COMMENT_VALUE_TYPE'].format(p.lineno(1))
self.logger.log(msg)

def p_annotation_type_1(self, p):
"""annotation_type : ANNOTATION_TYPE LINE"""
try:
if six.PY2:
value = p[2].decode(encoding='utf-8')
else:
value = p[2]
self.builder.add_annotation_type(self.document, value)
except CardinalityError:
self.more_than_one_error('AnnotationType', p.lineno(1))
except SPDXValueError:
self.error = True
msg = ERROR_MESSAGES['ANNOTATION_TYPE_VALUE'].format(p.lineno(1))
self.logger.log(msg)
except OrderError:
self.order_error('AnnotationType', 'Annotator', p.lineno(1))

def p_annotation_type_2(self, p):
"""annotation_type : ANNOTATION_TYPE error"""
self.error = True
msg = ERROR_MESSAGES['ANNOTATION_TYPE_VALUE'].format(
p.lineno(1))
self.logger.log(msg)

def p_lics_list_ver_1(self, p):
"""locs_list_ver : LIC_LIST_VER LINE"""
try:
Expand Down
19 changes: 19 additions & 0 deletions spdx/parsers/tagvaluebuilders.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ def reset_annotations(self):
# FIXME: this state does not make sense
self.annotation_date_set = False
self.annotation_comment_set = False
self.annotation_type_set = False

def add_annotator(self, doc, annotator):
"""Adds an annotator to the SPDX Document.
Expand Down Expand Up @@ -382,6 +383,24 @@ def add_annotation_comment(self, doc, comment):
else:
raise OrderError('AnnotationComment::Comment')

def add_annotation_type(self, doc, annotation_type):
"""Sets the annotation type. Raises CardinalityError if
already set. OrderError if no annotator defined before.
Raises SPDXValueError if invalid value.
"""
if len(doc.annotations) != 0:
if not self.annotation_type_set:
self.annotation_type_set = True
if validations.validate_annotation_type(annotation_type):
doc.annotations[-1].annotation_type = annotation_type
return True
else:
raise SPDXValueError('Annotation::AnnotationType')
else:
raise CardinalityError('Annotation::AnnotationType')
else:
raise OrderError('Annotation::AnnotationType')


class PackageBuilder(object):
VERIF_CODE_REGEX = re.compile(r"([0-9a-f]+)\s*(\(\s*(.+)\))?", re.UNICODE)
Expand Down
8 changes: 8 additions & 0 deletions spdx/parsers/validations.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ def validate_annotation_comment(value, optional=False):
return validate_is_free_form_text(value, optional)


def validate_annotation_type(value, optional=False):
value = value.strip()
if value == 'REVIEW' or value == 'OTHER':
return True
else:
return False


def validate_pkg_src_info(value, optional=False):
return validate_is_free_form_text(value, optional)

Expand Down
3 changes: 3 additions & 0 deletions spdx/writers/rdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,9 @@ def create_annotation_node(self, annotation):
comment_node = Literal(annotation.comment)
comment_triple = (annotation_node, RDFS.comment, comment_node)
self.graph.add(comment_triple)
annotation_type_node = Literal(annotation.annotation_type)
annotation_type_triple = (annotation_node, self.spdx_namespace.annotationType, annotation_type_node)
self.graph.add(annotation_type_triple)

return annotation_node

Expand Down
1 change: 1 addition & 0 deletions spdx/writers/tagvalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def write_annotation(annotation, out):
write_value('AnnotationDate', annotation.annotation_date_iso_format, out)
if annotation.has_comment:
write_text_value('AnnotationComment', annotation.comment, out)
write_value('AnnotationType', annotation.annotation_type, out)


def write_file_type(ftype, out):
Expand Down
23 changes: 23 additions & 0 deletions tests/test_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ def test_comment_without_annotator(self):
comment = '<text>Comment without annotator</text>'
self.builder.add_annotation_comment(self.document, comment)

@testing_utils.raises(builders.OrderError)
def test_type_without_annotator(self):
annotation_type = 'REVIEW'
self.builder.add_annotation_type(self.document, annotation_type)

@testing_utils.raises(builders.CardinalityError)
def test_annotation_comment_cardinality(self):
comment = '<text>Annotation Comment</text>'
Expand Down Expand Up @@ -311,6 +316,24 @@ def test_annotation_comment_value(self):
self.add_annotator()
self.builder.add_annotation_comment(self.document, comment)

@testing_utils.raises(builders.SPDXValueError)
def test_incorrect_annotation_type_value(self):
annotation_type = 'Some random value instead of REVIEW or OTHER'
self.add_annotator()
self.builder.add_annotation_type(self.document, annotation_type)

def test_correct_annotation_type(self):
annotation_type = 'REVIEW'
self.add_annotator()
assert self.builder.add_annotation_type(self.document, annotation_type)

@testing_utils.raises(builders.CardinalityError)
def test_annotation_type_cardinality(self):
annotation_type = 'REVIEW'
self.add_annotator()
assert self.builder.add_annotation_type(self.document, annotation_type)
self.builder.add_annotation_type(self.document, annotation_type)

def add_annotator(self):
per_str = 'Person: Jim (jim@example.com)'
per = self.entity_builder.build_person(self.document, per_str)
Expand Down
2 changes: 2 additions & 0 deletions tests/test_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ def test_rdf_tagvalue(self):
assert doc.validate([])
filename = get_temp_file('.tag')
self.write_tagvalue_file(doc, filename)
###############################################
doc, error = self.parse_tagvalue_file(filename)
# print(doc.annotations[-1].annotation_type)
assert not error
assert doc.validate([])

Expand Down

0 comments on commit c049034

Please sign in to comment.