Code Monkey home page Code Monkey logo

tools-python's Introduction

Python library to parse, validate and create SPDX documents

CI status (Linux, macOS and Windows): Install and Test

Breaking changes v0.7 -> v0.8

Please be aware that the upcoming 0.8 release has undergone a significant refactoring in preparation for the upcoming SPDX v3.0 release, leading to breaking changes in the API. Please refer to the migration guide to update your existing code.

The main features of v0.8 are:

  • full validation of SPDX documents against the v2.2 and v2.3 specification
  • support for SPDX's RDF format with all v2.3 features
  • experimental support for the upcoming SPDX v3 specification. Note, however, that support is neither complete nor stable at this point, as the spec is still evolving. SPDX3-related code is contained in a separate subpackage "spdx3" and its use is optional. We do not recommend using it in production code yet.

Information

This library implements SPDX parsers, convertors, validators and handlers in Python.

Important updates regarding this library are shared via the SPDX tech mailing list: https://lists.spdx.org/g/Spdx-tech.

License

Apache-2.0

Features

  • API to create and manipulate SPDX v2.2 and v2.3 documents
  • Parse, convert, create and validate SPDX files
  • supported formats: Tag/Value, RDF, JSON, YAML, XML
  • visualize the structure of a SPDX document by creating an AGraph. Note: This is an optional feature and requires additional installation of optional dependencies

Experimental support for SPDX 3.0

  • Create v3.0 elements and payloads
  • Convert v2.2/v2.3 documents to v3.0
  • Serialize to JSON-LD

See Quickstart to SPDX 3.0 below.
The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: a5372a3c145dbdfc1381fc1f791c68889aafc7ff).

Installation

As always you should work in a virtualenv (venv). You can install a local clone of this repo with yourenv/bin/pip install . or install it from PyPI (check for the newest release and install it like yourenv/bin/pip install spdx-tools==0.8.0a2). Note that on Windows it would be Scripts instead of bin.

How to use

Command-line usage

  1. PARSING/VALIDATING (for parsing any format):
  • Use pyspdxtools -i <filename> where <filename> is the location of the file. The input format is inferred automatically from the file ending.

  • If you are using a source distribution, try running:
    pyspdxtools -i tests/data/SPDXJSONExample-v2.3.spdx.json

  1. CONVERTING (for converting one format to another):
  • Use pyspdxtools -i <input_file> -o <output_file> where <input_file> is the location of the file to be converted and <output_file> is the location of the output file. The input and output formats are inferred automatically from the file endings.

  • If you are using a source distribution, try running:
    pyspdxtools -i tests/data/SPDXJSONExample-v2.3.spdx.json -o output.tag

  • If you want to skip the validation process, provide the --novalidation flag, like so:
    pyspdxtools -i tests/data/SPDXJSONExample-v2.3.spdx.json -o output.tag --novalidation
    (use this with caution: note that undetected invalid documents may lead to unexpected behavior of the tool)

  • For help use pyspdxtools --help

  1. GRAPH GENERATION (optional feature)
  • This feature generates a graph representing all elements in the SPDX document and their connections based on the provided relationships. The graph can be rendered to a picture. Below is an example for the file tests/data/SPDXJSONExample-v2.3.spdx.json: SPDXJSONExample-v2.3.spdx.png
  • Make sure you install the optional dependencies networkx and pygraphviz. To do so run pip install ".[graph_generation]".
  • Use pyspdxtools -i <input_file> --graph -o <output_file> where <output_file> is an output file name with valid format for pygraphviz (check the documentation here).
  • If you are using a source distribution, try running pyspdxtools -i tests/data/SPDXJSONExample-v2.3.spdx.json --graph -o SPDXJSONExample-v2.3.spdx.png to generate a png with an overview of the structure of the example file.

Library usage

  1. DATA MODEL
  • The spdx_tools.spdx.model package constitutes the internal SPDX v2.3 data model (v2.2 is simply a subset of this). All relevant classes for SPDX document creation are exposed in the __init__.py found here.
  • SPDX objects are implemented via @dataclass_with_properties, a custom extension of @dataclass.
    • Each class starts with a list of its properties and their possible types. When no default value is provided, the property is mandatory and must be set during initialization.
    • Using the type hints, type checking is enforced when initializing a new instance or setting/getting a property on an instance (wrong types will raise ConstructorTypeError or TypeError, respectively). This makes it easy to catch invalid properties early and only construct valid documents.
    • Note: in-place manipulations like list.append(item) will circumvent the type checking (a TypeError will still be raised when reading list again). We recommend using list = list + [item] instead.
  • The main entry point of an SPDX document is the Document class from the document.py module, which links to all other classes.
  • For license handling, the license_expression library is used.
  • Note on documentDescribes and hasFiles: These fields will be converted to relationships in the internal data model. As they are deprecated, these fields will not be written in the output.
  1. PARSING
  • Use parse_file(file_name) from the parse_anything.py module to parse an arbitrary file with one of the supported file endings.
  • Successful parsing will return a Document instance. Unsuccessful parsing will raise SPDXParsingError with a list of all encountered problems.
  1. VALIDATING
  • Use validate_full_spdx_document(document) to validate an instance of the Document class.
  • This will return a list of ValidationMessage objects, each consisting of a String describing the invalidity and a ValidationContext to pinpoint the source of the validation error.
  • Validation depends on the SPDX version of the document. Note that only versions SPDX-2.2 and SPDX-2.3 are supported by this tool.
  1. WRITING
  • Use write_file(document, file_name) from the write_anything.py module to write a Document instance to the specified file. The serialization format is determined from the filename ending.
  • Validation is performed per default prior to the writing process, which is cancelled if the document is invalid. You can skip the validation via write_file(document, file_name, validate=False). Caution: Only valid documents can be serialized reliably; serialization of invalid documents is not supported.

Example

Here are some examples of possible use cases to quickly get you started with the spdx-tools. If you want more examples, like how to create an SPDX document from scratch, have a look at the examples folder.

import logging

from license_expression import get_spdx_licensing

from spdx_tools.spdx.model import (Checksum, ChecksumAlgorithm, File, 
                                   FileType, Relationship, RelationshipType)
from spdx_tools.spdx.parser.parse_anything import parse_file
from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document
from spdx_tools.spdx.writer.write_anything import write_file

# read in an SPDX document from a file
document = parse_file("spdx_document.json")

# change the document's name
document.creation_info.name = "new document name"

# define a file and a DESCRIBES relationship between the file and the document
checksum = Checksum(ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c")

file = File(name="./fileName.py", spdx_id="SPDXRef-File", checksums=[checksum], 
            file_types=[FileType.TEXT], 
            license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"),
            license_comment="licenseComment", copyright_text="copyrightText")

relationship = Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-File")

# add the file and the relationship to the document 
# (note that we do not use "document.files.append(file)" as that would circumvent the type checking)
document.files = document.files + [file]
document.relationships = document.relationships + [relationship]

# validate the edited document and log the validation messages
# (depending on your use case, you might also want to utilize the validation_message.context)
validation_messages = validate_full_spdx_document(document)
for validation_message in validation_messages:
    logging.warning(validation_message.validation_message)

# if there are no validation messages, the document is valid 
# and we can safely serialize it without validating again
if not validation_messages:
    write_file(document, "new_spdx_document.rdf", validate=False)

Quickstart to SPDX 3.0

In contrast to SPDX v2, all elements are now subclasses of the central Element class. This includes packages, files, snippets, relationships, annotations, but also SBOMs, SpdxDocuments, and more.
For serialization purposes, all Elements that are to be serialized into the same file are collected in a Payload. This is just a dictionary that maps each Element's SpdxId to itself. Use the write_payload() functions to serialize a payload. There currently are two options:

  • The spdx_tools.spdx3.writer.json_ld.json_ld_writer module generates a JSON-LD file of the payload.
  • The spdx_tools.spdx3.writer.console.payload_writer module prints a debug output to console. Note that this is not an official part of the SPDX specification and will probably be dropped as soon as a better standard emerges.

You can convert an SPDX v2 document to v3 via the spdx_tools.spdx3.bump_from_spdx2.spdx_document module. The bump_spdx_document() function will return a payload containing an SpdxDocument Element and one Element for each package, file, snippet, relationship, or annotation contained in the v2 document.

Dependencies

Support

Contributing

Contributions are very welcome! See CONTRIBUTING.md for instructions on how to contribute to the codebase.

History

This is the result of an initial GSoC contribution by @ah450 (or https://github.com/a-h-i) and is maintained by a community of SPDX adopters and enthusiasts. In order to prepare for the release of SPDX v3.0, the repository has undergone a major refactoring during the time from 11/2022 to 07/2023.

tools-python's People

Contributors

a-h-i avatar alpianon avatar altendky avatar armintaenzertng avatar carmenbianca avatar chrisdecker1201 avatar fholger avatar goneall avatar harshvmahawar avatar jayvdb avatar jotterson avatar kolanich avatar lhh avatar lumjjb avatar macrovve avatar maxhbr avatar meretp avatar nicoweidner avatar njv299 avatar pombredanne avatar quaresmajose avatar rodneyrichardson avatar skalt avatar sschuberth avatar tardyp avatar techytushar avatar vargenau avatar xavierfigueroav avatar yash-nisar avatar yash-varshney avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tools-python's Issues

Add support for parsing more than one package

The current implementation only supports parsing a single package in the SPDX document. There can be one or more packages as mentioned here. We should add support for parsing more than one package.

has_optional_field implementation may lead to unexpected results

has_optional_field(field) verifies whether the value of field is not None. But, some attributes are sometimes initialized as some default/empty object, like an empty list. In that example, has_optional_field(field) will always return True, even if the list is empty (when I think it should return False because there is actually no information).

I suggest: return bool(field)

Add a utility to map originator defined license strings to SPDX license format

Package managers or text files may declare a license string that may not be an SPDX license format. For example, many projects declare their license as BSD but it is unclear which BSD.
oss-review-toolkit has an implementation that comes reasonably close.

https://github.com/heremaps/oss-review-toolkit/blob/490c2da69435182db19c6dbdebad863de41a7108/spdx-utils/src/main/kotlin/SpdxLicenseAliasMapping.kt

https://github.com/heremaps/oss-review-toolkit/blob/518e17c0b1385cc403960cfdfdff69e76240cb27/spdx-utils/src/main/kotlin/SpdxDeclaredLicenseMapping.kt

This is written in kotlin but it looks reasonably straightforward to convert it to python2/3

This would be useful for tools that are reading user-declared licenses.

cc @tsteenbe @goneall @kestewart

Update .gitignore

The .gitignore file does not have entries for the virtualenv and IDEs file.

Incorrect line numbers reported when errors are emitted

Steps to reproduce:

  1. Edit line FileCopyrightText: Copyright 2014 Acme Inc in SPDXSimpleTag.tag
  2. Navigate to the examples directory.
  3. Run the command python parse_tv.py '../data/SPDXSimpleTag.tag'
  4. Get output as :
Generating LALR tables
FileCopyrightText must be one of NOASSERTION, NONE or free form text, line: 34
Errors encountered while parsing

Remove hard depo on nose for tests

Instead the tests should only depend on the plain unittest so that anyone can use any test runner they like (and I love py.test for this)

Searching the SPDX Database for a License Name

Is it possible to get a license in Json or XML format form SPDX database by searching through the license names using a string (or a regular expression)? The result can also be a best effort result if the given search string is not exact.

Version model fields must be integers but sometimes they aren't

BACKGROUND INFORMATION
major and minor fields of Version model are supposed to be integers and the class method Version.from_str() is responsible for assuring that.

def from_str(cls, value):
"""Constructs a Version from a string.
Returns None if string not in N.N form where N represents a
number.
"""
m = cls.VERS_STR_REGEX.match(value)
if m is not None:
return cls(int(m.group(1)), int(m.group(2)))
else:
return None

If license_list_version field is absent when initializing a CreationInfo object, a default value is taken from the config.py file.
def __init__(self, created=None, comment=None,
license_list_version=config.LICENSE_LIST_VERSION):
self.creators = []
self.created = created
self.comment = comment
self.license_list_version = license_list_version

THE ISSUE
The default Version object described above is created assigning major and minor fields directly as string values.
(_major, _minor), LICENSE_MAP = load_license_list(_licenses)
LICENSE_LIST_VERSION = Version(major=_major, minor=_minor)

__lt__ method and parsers tests (expect integer values) may fail.

Add AUTHORS file

An authors file is needed to list and thank people who have contributed to the project.

PEP8 violations at a few places

While going through the codebase, I've noticed a few PEP8 violations which can be fixed by a static code analysis tool like coala.

Add SPDX Document Merge

This would be a merge to combine two SPDX documents without losing any of the license information. An example use case: A SPDX document including human input is already created, but a new document is automatically generated with a scanner and we wish to merge the two without losing the modifications made by a human.

Make validation optional by introducing a `validate` flag

On the validation side, the validation will be an option. Fields will not be mandatory by default. They will be checked only when the user asks to validate and not at the time of creation. This will enforce the user to be able to create and dump eventually partial documents that may not yet be fully valid.

This can be established by introducing a validate flag in both the parsers (tagvalue and rdf) and validating only when the flag is set.

@pombredanne Should I create a PR for this one ?

Report an error when an `UNKNOWN_TAG` is found

Steps to reproduce:

  • When I modify any tag, e.g SPDXVersion: SPDX-1.2 to SPDXVersio: SPDX-1.2, the tool should report an error like Found unknown tag : SPDXVersio at line: 2 but instead it continues to parse.

The tokenizing works fine, the problem is with the parsing method.

Section 'artifactOf' of 'File' is not completely supported by RDF parsers/writers

  • RDF parsers do not handle 'projectURI' field of 'artifactOf' section.

    def p_file_project(self, project):
    """Helper function for parsing doap:project name and homepage.
    and setting them using the file builder.
    """
    for _, _, name in self.graph.triples((project, self.doap_namespace['name'], None)):
    self.builder.set_file_atrificat_of_project(self.doc, 'name', six.text_type(name))
    for _, _, homepage in self.graph.triples(
    (project, self.doap_namespace['homepage'], None)):
    self.builder.set_file_atrificat_of_project(self.doc, 'home', six.text_type(homepage))

  • RDF writers do not handle anything in 'artifactOf' section. That section is not being written in RDF files. A way to try it is running python tv_to_rdf.py ../data/SPDXTagExample.tag result.rdf

Output file attached:
result.rdf.txt

there are some extra quotes which may confuse people

In the README, How to use section.

parse_tv.py is an example tag/value parsing usage. Try running python parse_tv.py '../data/SPDXSimpleTag.tag'

args '../data/SPDXSimpleTag.tag' should remove single quotes cause they are not valid path in Windows

Link CI status badges in README

As a follow up to #4 it would be nice to get status badges in the README.
I tend to prefer ReST to markdown and we could use the examples of the (sophisticated or complex depending on which way you look at it) status badges used in scancode

spdx is not compatible with python 3

Description- I am using this spdx as deps in scancode-toolkit .When i running the api calc_verif_code is not working properly on Python 3. Its saying TypeError: Unicode-objects must be encoded before hashing
My source code - https://github.com/nexB/scancode-toolkit/blob/develop/src/formattedcode/output_spdx.py#L319

Output - https://dev.azure.com/nexB/scancode-toolkit/_build/results?buildId=954&view=logs&jobId=0b478794-5af2-5128-0bfd-478dc215772f&taskId=9d724a14-ad4d-5378-78fc-204e55328930&lineStart=4409&lineEnd=4410&colStart=1&colEnd=1

OS- macOS Mojave(10.14.6)
Python version - 3.6.8

Even your latest version that supports py3 is also not available on Pypi.
Please update setup also https://github.com/spdx/tools-python/blob/master/setup.py#L51

Please fix this API(https://github.com/spdx/tools-python/blob/master/spdx/package.py#L246) ASAP , i need Py 2/3 compatible .Thanks

SPDX IDs format inconsistencies between file formats

RDF and TAG/VALUE file formats have two different ways to write SPDX IDs throughout a SPDX Document (document ID, file ID, annotation ID, package ID, etc).

For RDF files: [DocumentNamespace|DocumentURI]#[SPDX Identifier]
For TAG/VALUE files: [SPDX Identifier]

A problem comes up when a TAG/VALUE file is written from reading an RDF file: SPDX IDs will have the format for RDF files. Moreover, if this behavior is ignored while developing JSON/YAML/XML support, it will spread.

Data from parsers should be stored in spdx models only as python types and spdx models

When parsing documents from RDF files, some fields are being stored as rdflib objects and it can be problematic.

All data stored in SPDX models (document.Document, file.File, document.ExtractedLicense, etc) should be stored as python and spdx types so that they are independent of the format to be written or read.

I had problems trying to write YAML files from a document instance created by reading an RDF file because pyyaml was not able to represent some rdflib objects (and it does not have to be able to). As expected, pyyaml is able to deal with python objects.

Of course, almost every spdx type has overwritten the __str__ and __repr__ methods and some others have methods that return the 'str' representation of their single fields, but they sometimes assume (correctly) that fields such as full_name, text or comment (from document.ExtractedLicense) are strings (but they are rdflib.terms.Literal objects when parsed from RDF files), so those functions just return the field (rdflib type).

Again, spdx types should be independent of the format to be written or read.

Build fails

The build fails for this project. The build fails for Python 3.4 and 3.5.I am working on to correct this.Any feedback would be appreciated.

Release on Pypi

The spdx name is taken by @bbqsrc which is OK, we can pick spdx-tools instead.
But to avoid namespace issues, either we should find a way to share the namespace (see bbqsrc/spdx-python#1 ) or refactor the namespace used here.

virtualenv error on OSX build (CircleCI)

The error that I get is :

bash: line 2: virtualenv: command not found

((if (directory? "/Users/distiller/virtualenvs/venv-system") (echo "Using cached venv") (do ("virtualenv" "/Users/distiller/virtualenvs/venv-system" || exit 1) (source "/Users/distiller/virtualenvs/venv-system/bin/activate" || exit 2) (pip install nose || exit 3))) "true" (echo "source /Users/distiller/virtualenvs/venv-system/bin/activate" >> "~/.circlerc")) returned exit code 1

Action failed: virtualenv

Update to full SPDX v2.1

Update the SPDX Python libraries to the SPDX 2.1 specification. The SPDX 2.1 specification is a major upgrade from SPDX 1.2 supporting relationships between SPDX documents and SPDX elements.

Do not require the SPDX version to be 1.2

@sschuberth @pombredanne
According to 2ecb365, we do not require the version to be 1.2, but we have a bug. (still require the version to be 1.2)

Steps to reproduce:

  1. Modify SPDXSimpleTag.tag and replace this line -> SPDXVersion: SPDX-1.2 with SPDXVersion: SPDX-1.1.
  2. Run python parse_tv.py '../data/SPDXSimpleTag.tag' from the examples directory.

Output that we receive:

examples git:(master) โœ— python parse_tv.py '../data/SPDXSimpleTag.tag'
Generating LALR tables
SPDXVersion must be SPDX-1.2 found SPDX-1.1.
Errors encountered while parsing

The cause of this behaviour is the given snippet inside tagvaluebuilders.py:

if vers == version.Version(major=1, minor=2):
    doc.version = vers
    return True

Change print to python3 style in example

There are still some codes called the print function the Python 2-way without the parentheses, which may raise SyntaxError in Python 3
here are some examples

except InvalidDocumentError:
       print 'Document is Invalid' 
       messages = []
       doc.validate(messages)
       print '\n'.join(messages)

Document Compare functionality

I would like to implement this functionality as a small project for understanding my targetted GSoC project a little better. I am planning of making comparision between two rdf format documents at first, then I will go on to expand for tv format as well.Let me know your thoughts on this @pombredanne , so that I can proceed.

Duplicate extracted licenses when parsing from RDF

The field Document.extracted_licenses contains duplicate ExtractedLicense objects when they are parsed from RDF files.

It can be noticed by running parse_rdf.py.
Input: SPDXRdfExample.rdf
Output:

doc comment: This is a sample spreadsheet
Creators:
        Person: Gary O'Neall
        Tool: SourceAuditor-V1.2
        Organization: Source Auditor Inc.
Document review information:
        Reviewer: Person: Suzanne Reviewer
        Date: 2011-03-13 00:00:00
        Comment: Another example reviewer.
        Reviewer: Person: Joe Reviewer
        Date: 2010-02-10 00:00:00
        Comment: This is just an example.  Some of the non-standard licenses look like they are actually BSD 3 clause licenses
Creation comment: This is an example of an SPDX spreadsheet format
Package Name: SPDX Translator
Package Version: Version 0.9.2
Package Download Location: http://www.spdx.org/tools
Package Homepage: None
Package Checksum: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
Package verification code: 4e3211c67a2d28fced849ee1bb76e7391b93feba
Package excluded from verif: SpdxTranslatorSpdx.txt,SpdxTranslatorSpdx.rdf
Package license concluded: LicenseRef-4 AND LicenseRef-2 AND Apache-1.0 AND LicenseRef-3 AND LicenseRef-1 AND Apache-2.0 AND MPL-1.1
Package license declared: MPL-1.1 AND Apache-2.0 AND LicenseRef-3 AND LicenseRef-2 AND LicenseRef-4 AND LicenseRef-1
Package licenses from files:
        LicenseRef-1
        LicenseRef-3
        Apache-1.0
        MPL-1.1
        LicenseRef-4
        LicenseRef-2
        Apache-2.0
Package Copyright text:  Copyright 2010, 2011 Source Auditor Inc.
Package summary: SPDX Translator utility
Package description: This utility translates and SPDX RDF XML document to a spreadsheet, translates a spreadsheet to an SPDX RDF XML document and translates an SPDX RDFa document to an SPDX RDF XML document.
Package Files:
        File name: Jenna-2.6.3/jena-2.6.3-sources.jar
        File type: ARCHIVE
        File Checksum: 3ab4e1c67a2d28fced849ee1bb76e7391b93f125
        File license concluded: LicenseRef-1
        File license info in file: LicenseRef-1
        File artifact of project name: Jena
        File name: src/org/spdx/parser/DOAPProject.java
        File type: SOURCE
        File Checksum: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
        File license concluded: Apache-2.0
        File license info in file: Apache-2.0
        File artifact of project name:
Document Extracted licenses:
        Identifier: LicenseRef-4
        Name: None
        Identifier: LicenseRef-2
        Name: None
        Identifier: LicenseRef-3
        Name: CyberNeko License
        Identifier: LicenseRef-1
        Name: None
        Identifier: LicenseRef-3
        Name: CyberNeko License
        Identifier: LicenseRef-2
        Name: None
        Identifier: LicenseRef-4
        Name: None
        Identifier: LicenseRef-1
        Name: None
Annotations:
        Annotator: Person: Jim Reviewer
        Annotation Date: 2012-06-13 00:00:00
        Annotation Comment: This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses
        Annotation Type: REVIEW
        Annotation SPDX Identifier: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#SPDXRef-45

Parsing the .tag file gives error

When parsing the sample.tag file using python parse_tv.py sample.tag, it throws an error TypeError: expected string or buffer. The sample.tag is generated after running python write_tv.py sample.tag. IMHO this happens because when write_tv.py is executed it creates a key value pair PackageCopyrightText: NOASSERTION, here type of NOASSERTION is <class 'spdx.utils.NoAssert'> which is not supported.

Whole error log can be found in the screenshot below.
screenshot from 2018-03-06 18-07-05

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.