Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion data/SPDXRdfExample.rdf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
xmlns:j.0="http://usefulinc.com/ns/doap#"
xmlns="http://spdx.org/rdf/terms#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<SpdxDocument rdf:about="http://www.spdx.org/tools#SPDXANALYSIS">
<SpdxDocument rdf:about="https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-DOCUMENT">
<creationInfo>
<CreationInfo>
<created>2010-02-03T00:00:00Z</created>
Expand Down
1 change: 1 addition & 0 deletions data/SPDXSimpleTag.tag
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Document info
SPDXVersion: SPDX-2.1
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentComment: <text>Sample Comment</text>

# Creation info
Expand Down
1 change: 1 addition & 0 deletions data/SPDXTagExample.tag
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
SPDXVersion: SPDX-2.1
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentComment: <text>This is a sample spreadsheet</text>

## Creation Information
Expand Down
21 changes: 20 additions & 1 deletion spdx/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ class Document(object):
Represent an SPDX document with these fields:
- version: Spec version. Mandatory, one - Type: Version.
- data_license: SPDX-Metadata license. Mandatory, one. Type: License.
- spdx_id: SPDX Identifier for the document to refer to itself in
relationship to other elements. Mandatory, one. Type: str.
- comment: Comments on the SPDX file, optional one. Type: str
- creation_info: SPDX file creation info. Mandatory, one. Type: CreationInfo
- package: Package described by this document. Mandatory, one. Type: Package
Expand All @@ -198,11 +200,13 @@ class Document(object):
Type: Review.
"""

def __init__(self, version=None, data_license=None, comment=None, package=None):
def __init__(self, version=None, data_license=None, spdx_id=None,
comment=None, package=None):
# avoid recursive impor
from spdx.creationinfo import CreationInfo
self.version = version
self.data_license = data_license
self.spdx_id = spdx_id
self.comment = comment
self.creation_info = CreationInfo()
self.package = package
Expand Down Expand Up @@ -237,6 +241,7 @@ def validate(self, messages=None):

return (self.validate_version(messages)
and self.validate_data_lics(messages)
and self.validate_spdx_id(messages)
and self.validate_creation_info(messages)
and self.validate_package(messages)
and self.validate_extracted_licenses(messages)
Expand Down Expand Up @@ -268,6 +273,20 @@ def validate_data_lics(self, messages=None):
messages.append('Document data license must be CC0-1.0.')
return False

def validate_spdx_id(self, messages=None):
# FIXME: messages should be returned
messages = messages if messages is not None else []

if self.spdx_id is None:
messages.append('Document has no SPDX Identifier.')
return False

if self.spdx_id.endswith('SPDXRef-DOCUMENT'):
return True
else:
messages.append('Invalid Document SPDX Identifier value.')
return False

def validate_reviews(self, messages=None):
# FIXME: messages should be returned
messages = messages if messages is not None else []
Expand Down
1 change: 1 addition & 0 deletions spdx/parsers/lexers/tagvalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Lexer(object):
# Top level fields
'SPDXVersion': 'DOC_VERSION',
'DataLicense': 'DOC_LICENSE',
'SPDXID': 'DOC_SPDX_ID',
'DocumentComment': 'DOC_COMMENT',
# Creation info
'Creator': 'CREATOR',
Expand Down
8 changes: 7 additions & 1 deletion spdx/parsers/rdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
ERROR_MESSAGES = {
'DOC_VERS_VALUE': 'Invalid specVersion \'{0}\' must be SPDX-M.N where M and N are numbers.',
'DOC_D_LICS': 'Invalid dataLicense \'{0}\' must be http://spdx.org/licenses/CC0-1.0.',
'DOC_SPDX_ID_VALUE': 'Invalid SPDXID value, SPDXID must be the document namespace appended '
'by "#SPDXRef-DOCUMENT", line: {0}',
'LL_VALUE': 'Invalid licenseListVersion \'{0}\' must be of the format N.N where N is a number',
'CREATED_VALUE': 'Invalid created value \'{0}\' must be date in ISO 8601 format.',
'CREATOR_VALUE': 'Invalid creator value \'{0}\' must be Organization, Tool or Person.',
Expand Down Expand Up @@ -799,7 +801,11 @@ def parse_creation_info(self, ci_term):
self.value_error('LL_VALUE', o)

def parse_doc_fields(self, doc_term):
"""Parses the version, data license and comment."""
"""Parses the version, data license, SPDX Identifier and comment."""
try:
self.builder.set_doc_spdx_id(self.doc, doc_term)
except SPDXValueError:
self.value_error('DOC_SPDX_ID_VALUE', doc_term)
for _s, _p, o in self.graph.triples((doc_term, self.spdx_namespace['specVersion'], None)):
try:
self.builder.set_doc_version(self.doc, six.text_type(o))
Expand Down
17 changes: 17 additions & 0 deletions spdx/parsers/rdfbuilders.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from spdx.parsers.builderexceptions import OrderError
from spdx.parsers.builderexceptions import SPDXValueError
from spdx.parsers import tagvaluebuilders
from spdx.parsers import validations


class DocBuilder(object):
Expand Down Expand Up @@ -70,6 +71,21 @@ def set_doc_data_lic(self, doc, res):
else:
raise CardinalityError('Document::License')

def set_doc_spdx_id(self, doc, doc_spdx_id_line):
"""Sets the document SPDX Identifier.
Raises value error if malformed value, CardinalityError
if already defined.
"""
if not self.doc_spdx_id_set:
if validations.validate_doc_spdx_id(doc_spdx_id_line):
doc.spdx_id = doc_spdx_id_line
self.doc_spdx_id_set = True
return True
else:
raise SPDXValueError('Document::SPDX Identifier')
else:
raise CardinalityError('Document::SPDX Identifier')

def set_doc_comment(self, doc, comment):
"""Sets document comment, Raises CardinalityError if
comment already set.
Expand All @@ -88,6 +104,7 @@ def reset_document(self):
self.doc_version_set = False
self.doc_comment_set = False
self.doc_data_lics_set = False
self.doc_spdx_id_set = False


class EntityBuilder(tagvaluebuilders.EntityBuilder):
Expand Down
23 changes: 23 additions & 0 deletions spdx/parsers/tagvalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
'DOC_LICENSE_VALUE_TYPE': 'DataLicense must be CC0-1.0, line: {0}',
'DOC_VERSION_VALUE': 'Invalid SPDXVersion \'{0}\' must be SPDX-M.N where M and N are numbers. Line: {1}',
'DOC_VERSION_VALUE_TYPE': 'Invalid SPDXVersion value, must be SPDX-M.N where M and N are numbers. Line: {0}',
'DOC_SPDX_ID_VALUE': 'Invalid SPDXID value, SPDXID must be SPDXRef-DOCUMENT, line: {0}',
'DOC_COMMENT_VALUE_TYPE': 'DocumentComment value must be free form text between <text></text> tags, line:{0}',
'REVIEWER_VALUE_TYPE': 'Invalid Reviewer value must be a Person, Organization or Tool. Line: {0}',
'CREATOR_VALUE_TYPE': 'Invalid Reviewer value must be a Person, Organization or Tool. Line: {0}',
Expand Down Expand Up @@ -106,6 +107,7 @@ def p_start_2(self, p):
def p_attrib(self, p):
"""attrib : spdx_version
| data_lics
| doc_spdx_id
| doc_comment
| creator
| created
Expand Down Expand Up @@ -1098,6 +1100,27 @@ def p_data_license_2(self, p):
msg = ERROR_MESSAGES['DOC_LICENSE_VALUE_TYPE'].format(p.lineno(1))
self.logger.log(msg)

def p_doc_spdx_id_1(self, p):
"""doc_spdx_id : DOC_SPDX_ID LINE"""
try:
if six.PY2:
value = p[2].decode(encoding='utf-8')
else:
value = p[2]
self.builder.set_doc_spdx_id(self.document, value)
except SPDXValueError:
self.error = True
msg = ERROR_MESSAGES['DOC_SPDX_ID_VALUE'].format(p.lineno(2))
self.logger.log(msg)
except CardinalityError:
self.more_than_one_error('SPDXID', p.lineno(1))

def p_doc_spdx_id_2(self, p):
"""doc_spdx_id : DOC_SPDX_ID error"""
self.error = True
msg = ERROR_MESSAGES['DOC_SPDX_ID_VALUE'].format(p.lineno(1))
self.logger.log(msg)

def p_spdx_version_1(self, p):
"""spdx_version : DOC_VERSION LINE"""
try:
Expand Down
16 changes: 16 additions & 0 deletions spdx/parsers/tagvaluebuilders.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,21 @@ def set_doc_data_lics(self, doc, lics):
else:
raise CardinalityError('Document::DataLicense')

def set_doc_spdx_id(self, doc, doc_spdx_id_line):
"""Sets the document SPDX Identifier.
Raises value error if malformed value, CardinalityError
if already defined.
"""
if not self.doc_spdx_id_set:
if doc_spdx_id_line == 'SPDXRef-DOCUMENT':
doc.spdx_id = doc_spdx_id_line
self.doc_spdx_id_set = True
return True
else:
raise SPDXValueError('Document::SPDX Identifier')
else:
raise CardinalityError('Document::SPDX Identifier')

def set_doc_comment(self, doc, comment):
"""Sets document comment, Raises CardinalityError if
comment already set.
Expand All @@ -123,6 +138,7 @@ def reset_document(self):
self.doc_version_set = False
self.doc_comment_set = False
self.doc_data_lics_set = False
self.doc_spdx_id_set = False


class EntityBuilder(object):
Expand Down
9 changes: 9 additions & 0 deletions spdx/parsers/validations.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ def validate_doc_comment(value, optional=False):
return validate_is_free_form_text(value, optional)


def validate_doc_spdx_id(value, optional=False):
if value is None:
return optional
elif value.endswith('#SPDXRef-DOCUMENT'):
return True
else:
return False


def validate_creator(value, optional=False):
if value is None:
return optional
Expand Down
2 changes: 1 addition & 1 deletion spdx/writers/rdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ def create_doc(self):
"""
Add and return the root document node to graph.
"""
doc_node = URIRef('http://www.spdx.org/tools#SPDXANALYSIS')
doc_node = URIRef('http://www.spdx.org/tools#SPDXRef-DOCUMENT')
# Doc type
self.graph.add((doc_node, RDF.type, self.spdx_namespace.SpdxDocument))
# Version
Expand Down
1 change: 1 addition & 0 deletions spdx/writers/tagvalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ def write_document(document, out, validate=True):
out.write('# Document Information\n\n')
write_value('SPDXVersion', str(document.version), out)
write_value('DataLicense', document.data_license.identifier, out)
write_value('SPDXID', 'SPDXRef-DOCUMENT', out)
if document.has_comment:
write_text_value('DocumentComment', document.comment, out)
write_separators(out)
Expand Down
2 changes: 1 addition & 1 deletion tests/data/doc_write/rdf-simple-plus.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
}
}
},
"@rdf:about": "http://www.spdx.org/tools#SPDXANALYSIS"
"@rdf:about": "http://www.spdx.org/tools#SPDXRef-DOCUMENT"
}
}
}
2 changes: 1 addition & 1 deletion tests/data/doc_write/rdf-simple.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"ns1:fileName": "./some/path/tofile"
}
},
"@rdf:about": "http://www.spdx.org/tools#SPDXANALYSIS"
"@rdf:about": "http://www.spdx.org/tools#SPDXRef-DOCUMENT"
}
}
}
1 change: 1 addition & 0 deletions tests/data/doc_write/tv-simple-plus.tv
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Document Information
SPDXVersion: SPDX-2.1
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
# Creation Info
# Package
PackageName: some/path
Expand Down
1 change: 1 addition & 0 deletions tests/data/doc_write/tv-simple.tv
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Document Information
SPDXVersion: SPDX-2.1
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
# Creation Info
# Package
PackageName: some/path
Expand Down
9 changes: 6 additions & 3 deletions tests/test_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ def test_creation(self):
assert document.data_license.identifier == 'AFL-1.1'

def test_document_validate_failures_returns_informative_messages(self):
doc = Document(Version(2, 1), License.from_identifier('CC0-1.0'))
doc = Document(Version(2, 1), License.from_identifier('CC0-1.0'),
spdx_id='SPDXRef-DOCUMENT')
pack = doc.package = Package('some/path', NoAssert())
file1 = File('./some/path/tofile')
file1.name = './some/path/tofile'
Expand All @@ -83,7 +84,8 @@ def test_document_validate_failures_returns_informative_messages(self):
assert expected == messages

def test_document_is_valid_when_using_or_later_licenses(self):
doc = Document(Version(2, 1), License.from_identifier('CC0-1.0'))
doc = Document(Version(2, 1), License.from_identifier('CC0-1.0'),
spdx_id='SPDXRef-DOCUMENT')
doc.creation_info.add_creator(Tool('ScanCode'))
doc.creation_info.set_created_now()

Expand Down Expand Up @@ -113,7 +115,8 @@ def test_document_is_valid_when_using_or_later_licenses(self):
class TestWriters(TestCase):

def _get_lgpl_doc(self, or_later=False):
doc = Document(Version(2, 1), License.from_identifier('CC0-1.0'))
doc = Document(Version(2, 1), License.from_identifier('CC0-1.0'),
spdx_id='SPDXRef-DOCUMENT')
doc.creation_info.add_creator(Tool('ScanCode'))
doc.creation_info.set_created_now()

Expand Down
9 changes: 7 additions & 2 deletions tests/test_tag_value_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,18 @@ def test_document(self):
SPDXVersion: SPDX-2.1
# Comment.
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentComment: <text>This is a sample spreadsheet</text>
'''
self.l.input(data)
self.token_assert_helper(self.l.token(), 'DOC_VERSION', 'SPDXVersion', 2)
self.token_assert_helper(self.l.token(), 'LINE', 'SPDX-2.1', 2)
self.token_assert_helper(self.l.token(), 'DOC_LICENSE', 'DataLicense', 4)
self.token_assert_helper(self.l.token(), 'LINE', 'CC0-1.0', 4)
self.token_assert_helper(self.l.token(), 'DOC_COMMENT', 'DocumentComment', 5)
self.token_assert_helper(self.l.token(), 'TEXT', '<text>This is a sample spreadsheet</text>', 5)
self.token_assert_helper(self.l.token(), 'DOC_SPDX_ID', 'SPDXID', 5)
self.token_assert_helper(self.l.token(), 'LINE', 'SPDXRef-DOCUMENT', 5)
self.token_assert_helper(self.l.token(), 'DOC_COMMENT', 'DocumentComment', 6)
self.token_assert_helper(self.l.token(), 'TEXT', '<text>This is a sample spreadsheet</text>', 6)

def test_creation_info(self):
data = '''
Expand Down Expand Up @@ -105,6 +108,7 @@ class TestParser(TestCase):
document_str = '\n'.join([
'SPDXVersion: SPDX-2.1',
'DataLicense: CC0-1.0',
'SPDXID: SPDXRef-DOCUMENT',
'DocumentComment: <text>Sample Comment</text>'
])

Expand Down Expand Up @@ -169,6 +173,7 @@ def test_doc(self):
assert not error
assert document.version == Version(major=2, minor=1)
assert document.data_license.identifier == 'CC0-1.0'
assert document.spdx_id == 'SPDXRef-DOCUMENT'
assert document.comment == 'Sample Comment'

def test_creation_info(self):
Expand Down