├── .editorconfig
├── .flake8
├── .github
├── dependabot.yml
└── workflows
│ ├── check_codestyle.yml
│ ├── docs.yml
│ ├── install_and_test.yml
│ ├── integration_test.yml
│ └── prepare_release.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── DOCUMENTATION.md
├── LICENSE
├── MANIFEST.in
├── README.md
├── appveyor.yml
├── assets
└── SPDXJSONExample-v2.3.spdx.png
├── dev
└── publish_from_tag.sh
├── examples
├── spdx2_convert_format.py
├── spdx2_convert_to_spdx3.py
├── spdx2_document_from_scratch.py
├── spdx2_generate_graph.py
└── spdx2_parse_file.py
├── pyproject.toml
├── setup.py
├── src
└── spdx_tools
│ ├── common
│ ├── __init__.py
│ ├── spdx_licensing.py
│ └── typing
│ │ ├── __init__.py
│ │ ├── constructor_type_errors.py
│ │ ├── dataclass_with_properties.py
│ │ └── type_checks.py
│ ├── spdx
│ ├── __init__.py
│ ├── casing_tools.py
│ ├── clitools
│ │ ├── __init__.py
│ │ └── pyspdxtools.py
│ ├── constants.py
│ ├── datetime_conversions.py
│ ├── document_utils.py
│ ├── formats.py
│ ├── graph_generation.py
│ ├── jsonschema
│ │ ├── __init__.py
│ │ ├── annotation_converter.py
│ │ ├── annotation_properties.py
│ │ ├── checksum_converter.py
│ │ ├── checksum_properties.py
│ │ ├── converter.py
│ │ ├── creation_info_converter.py
│ │ ├── creation_info_properties.py
│ │ ├── document_converter.py
│ │ ├── document_properties.py
│ │ ├── external_document_ref_converter.py
│ │ ├── external_document_ref_properties.py
│ │ ├── external_package_ref_converter.py
│ │ ├── external_package_ref_properties.py
│ │ ├── extracted_licensing_info_converter.py
│ │ ├── extracted_licensing_info_properties.py
│ │ ├── file_converter.py
│ │ ├── file_properties.py
│ │ ├── json_property.py
│ │ ├── optional_utils.py
│ │ ├── package_converter.py
│ │ ├── package_properties.py
│ │ ├── package_verification_code_converter.py
│ │ ├── package_verification_code_properties.py
│ │ ├── relationship_converter.py
│ │ ├── relationship_properties.py
│ │ ├── snippet_converter.py
│ │ └── snippet_properties.py
│ ├── model
│ │ ├── __init__.py
│ │ ├── actor.py
│ │ ├── annotation.py
│ │ ├── checksum.py
│ │ ├── document.py
│ │ ├── external_document_ref.py
│ │ ├── extracted_licensing_info.py
│ │ ├── file.py
│ │ ├── package.py
│ │ ├── relationship.py
│ │ ├── relationship_filters.py
│ │ ├── snippet.py
│ │ ├── spdx_no_assertion.py
│ │ ├── spdx_none.py
│ │ └── version.py
│ ├── parser
│ │ ├── __init__.py
│ │ ├── actor_parser.py
│ │ ├── error.py
│ │ ├── json
│ │ │ ├── __init__.py
│ │ │ └── json_parser.py
│ │ ├── jsonlikedict
│ │ │ ├── __init__.py
│ │ │ ├── annotation_parser.py
│ │ │ ├── checksum_parser.py
│ │ │ ├── creation_info_parser.py
│ │ │ ├── dict_parsing_functions.py
│ │ │ ├── extracted_licensing_info_parser.py
│ │ │ ├── file_parser.py
│ │ │ ├── json_like_dict_parser.py
│ │ │ ├── license_expression_parser.py
│ │ │ ├── package_parser.py
│ │ │ ├── relationship_parser.py
│ │ │ └── snippet_parser.py
│ │ ├── logger.py
│ │ ├── parse_anything.py
│ │ ├── parsing_functions.py
│ │ ├── rdf
│ │ │ ├── __init__.py
│ │ │ ├── annotation_parser.py
│ │ │ ├── checksum_parser.py
│ │ │ ├── creation_info_parser.py
│ │ │ ├── extracted_licensing_info_parser.py
│ │ │ ├── file_parser.py
│ │ │ ├── graph_parsing_functions.py
│ │ │ ├── license_expression_parser.py
│ │ │ ├── package_parser.py
│ │ │ ├── rdf_parser.py
│ │ │ ├── relationship_parser.py
│ │ │ └── snippet_parser.py
│ │ ├── tagvalue
│ │ │ ├── __init__.py
│ │ │ ├── helper_methods.py
│ │ │ ├── lexer.py
│ │ │ ├── parser.py
│ │ │ └── tagvalue_parser.py
│ │ ├── xml
│ │ │ ├── __init__.py
│ │ │ └── xml_parser.py
│ │ └── yaml
│ │ │ ├── __init__.py
│ │ │ └── yaml_parser.py
│ ├── py.typed
│ ├── rdfschema
│ │ ├── __init__.py
│ │ └── namespace.py
│ ├── spdx_element_utils.py
│ ├── validation
│ │ ├── __init__.py
│ │ ├── actor_validator.py
│ │ ├── annotation_validator.py
│ │ ├── checksum_validator.py
│ │ ├── creation_info_validator.py
│ │ ├── document_validator.py
│ │ ├── external_document_ref_validator.py
│ │ ├── external_package_ref_validator.py
│ │ ├── extracted_licensing_info_validator.py
│ │ ├── file_validator.py
│ │ ├── license_expression_validator.py
│ │ ├── package_validator.py
│ │ ├── package_verification_code_validator.py
│ │ ├── relationship_validator.py
│ │ ├── snippet_validator.py
│ │ ├── spdx_id_validators.py
│ │ ├── uri_validators.py
│ │ └── validation_message.py
│ └── writer
│ │ ├── __init__.py
│ │ ├── json
│ │ ├── __init__.py
│ │ └── json_writer.py
│ │ ├── rdf
│ │ ├── __init__.py
│ │ ├── annotation_writer.py
│ │ ├── checksum_writer.py
│ │ ├── creation_info_writer.py
│ │ ├── external_document_ref_writer.py
│ │ ├── extracted_licensing_info_writer.py
│ │ ├── file_writer.py
│ │ ├── license_expression_writer.py
│ │ ├── package_writer.py
│ │ ├── rdf_writer.py
│ │ ├── relationship_writer.py
│ │ ├── snippet_writer.py
│ │ └── writer_utils.py
│ │ ├── tagvalue
│ │ ├── __init__.py
│ │ ├── annotation_writer.py
│ │ ├── checksum_writer.py
│ │ ├── creation_info_writer.py
│ │ ├── extracted_licensing_info_writer.py
│ │ ├── file_writer.py
│ │ ├── package_writer.py
│ │ ├── relationship_writer.py
│ │ ├── snippet_writer.py
│ │ ├── tagvalue_writer.py
│ │ └── tagvalue_writer_helper_functions.py
│ │ ├── write_anything.py
│ │ ├── write_utils.py
│ │ ├── xml
│ │ ├── __init__.py
│ │ └── xml_writer.py
│ │ └── yaml
│ │ ├── __init__.py
│ │ └── yaml_writer.py
│ └── spdx3
│ ├── __init__.py
│ ├── bump_from_spdx2
│ ├── __init__.py
│ ├── actor.py
│ ├── annotation.py
│ ├── bump_utils.py
│ ├── checksum.py
│ ├── creation_info.py
│ ├── external_document_ref.py
│ ├── file.py
│ ├── license_expression.py
│ ├── message.py
│ ├── package.py
│ ├── relationship.py
│ ├── snippet.py
│ └── spdx_document.py
│ ├── clitools
│ ├── __init__.py
│ └── pyspdxtools3.py
│ ├── model
│ ├── __init__.py
│ ├── agent.py
│ ├── ai
│ │ ├── __init__.py
│ │ └── ai_package.py
│ ├── annotation.py
│ ├── artifact.py
│ ├── bom.py
│ ├── build
│ │ ├── __init__.py
│ │ └── build.py
│ ├── bundle.py
│ ├── creation_info.py
│ ├── dataset
│ │ ├── __init__.py
│ │ └── dataset.py
│ ├── element.py
│ ├── external_identifier.py
│ ├── external_map.py
│ ├── external_reference.py
│ ├── hash.py
│ ├── integrity_method.py
│ ├── licensing
│ │ ├── __init__.py
│ │ ├── any_license_info.py
│ │ ├── conjunctive_license_set.py
│ │ ├── custom_license.py
│ │ ├── custom_license_addition.py
│ │ ├── disjunctive_license_set.py
│ │ ├── license.py
│ │ ├── license_addition.py
│ │ ├── license_field.py
│ │ ├── listed_license.py
│ │ ├── listed_license_exception.py
│ │ ├── no_assertion_license.py
│ │ ├── none_license.py
│ │ ├── or_later_operator.py
│ │ └── with_addition_operator.py
│ ├── lifecycle_scoped_relationship.py
│ ├── namespace_map.py
│ ├── organization.py
│ ├── person.py
│ ├── positive_integer_range.py
│ ├── profile_identifier.py
│ ├── relationship.py
│ ├── security
│ │ ├── __init__.py
│ │ ├── cvss_v2_vuln_assessment_relationship.py
│ │ ├── cvss_v3_vuln_assessment_relationship.py
│ │ ├── epss_vuln_assessment_relationship.py
│ │ ├── exploit_catalog_vuln_assessment_relationship.py
│ │ ├── ssvc_vuln_assessment_relationship.py
│ │ ├── vex_affected_vuln_assessment_relationship.py
│ │ ├── vex_fixed_vuln_assessment_relationship.py
│ │ ├── vex_not_affected_vuln_assessment_relationship.py
│ │ ├── vex_under_investigation_vuln_assessment_relationship.py
│ │ ├── vex_vuln_assessment_relationship.py
│ │ ├── vuln_assessment_relationship.py
│ │ └── vulnerability.py
│ ├── software
│ │ ├── __init__.py
│ │ ├── file.py
│ │ ├── package.py
│ │ ├── sbom.py
│ │ ├── snippet.py
│ │ ├── software_artifact.py
│ │ ├── software_dependency_relationship.py
│ │ └── software_purpose.py
│ ├── software_agent.py
│ ├── spdx_collection.py
│ ├── spdx_document.py
│ └── tool.py
│ ├── payload.py
│ ├── validation
│ ├── __init__.py
│ └── json_ld
│ │ ├── __init__.py
│ │ └── shacl_validation.py
│ └── writer
│ ├── __init__.py
│ ├── console
│ ├── __init__.py
│ ├── agent_writer.py
│ ├── ai
│ │ ├── __init__.py
│ │ └── ai_package_writer.py
│ ├── annotation_writer.py
│ ├── artifact_writer.py
│ ├── bom_writer.py
│ ├── build
│ │ ├── __init__.py
│ │ └── build_writer.py
│ ├── bundle_writer.py
│ ├── console.py
│ ├── creation_info_writer.py
│ ├── dataset
│ │ ├── __init__.py
│ │ └── dataset_writer.py
│ ├── element_writer.py
│ ├── external_identifier_writer.py
│ ├── external_map_writer.py
│ ├── external_reference_writer.py
│ ├── hash_writer.py
│ ├── integrity_method_writer.py
│ ├── lifecycle_scoped_relationship_writer.py
│ ├── namespace_map_writer.py
│ ├── payload_writer.py
│ ├── relationship_writer.py
│ ├── software
│ │ ├── __init__.py
│ │ ├── file_writer.py
│ │ ├── package_writer.py
│ │ ├── sbom_writer.py
│ │ ├── snippet_writer.py
│ │ └── software_dependency_relationship_writer.py
│ ├── spdx_collection_writer.py
│ ├── spdx_document_writer.py
│ └── tool_writer.py
│ └── json_ld
│ ├── SPDX_OWL.json
│ ├── __init__.py
│ ├── context.json
│ ├── json_ld_converter.py
│ ├── json_ld_writer.py
│ ├── model.ttl
│ ├── owl_to_context.py
│ └── process.md
├── stdeb.cfg
└── tests
├── __init__.py
├── spdx
├── __init__.py
├── data
│ ├── SPDXJSONExample-UTF-16.spdx.json
│ ├── SPDXJSONExample-v2.2.spdx.json
│ ├── SPDXJSONExample-v2.3.spdx.json
│ ├── SPDXLite.spdx
│ ├── SPDXRdfExample-UTF-16.spdx.rdf.xml
│ ├── SPDXRdfExample-v2.2.spdx.rdf.xml
│ ├── SPDXRdfExample-v2.3.spdx.rdf.xml
│ ├── SPDXTagExample-UTF-16.spdx
│ ├── SPDXTagExample-v2.2.spdx
│ ├── SPDXTagExample-v2.3.spdx
│ ├── SPDXXMLExample-UTF-16.spdx.xml
│ ├── SPDXXMLExample-v2.2.spdx.xml
│ ├── SPDXXMLExample-v2.3.spdx.xml
│ ├── SPDXYAMLExample-UTF-16.spdx.yaml
│ ├── SPDXYAMLExample-v2.2.spdx.yaml
│ ├── SPDXYAMLExample-v2.3.spdx.yaml
│ ├── circleConversionTestInitialDocument.json
│ └── invalid
│ │ └── spdx-trivy-vmware_log-intelligence-fluentd-sha256_086af034f561f343f633be9d9f9e95f65ae6c61b8ddb2c6755ef5bb25b40f53a.json
├── examples
│ ├── __init__.py
│ ├── test_examples.py
│ └── test_spdx2_document_from_scratch.py
├── fixtures.py
├── jsonschema
│ ├── __init__.py
│ ├── test_annotation_converter.py
│ ├── test_checksum_converter.py
│ ├── test_converter.py
│ ├── test_creation_info_converter.py
│ ├── test_document_converter.py
│ ├── test_external_document_ref_converter.py
│ ├── test_external_package_ref_converter.py
│ ├── test_extracted_licensing_info_converter.py
│ ├── test_file_converter.py
│ ├── test_package_converter.py
│ ├── test_package_verification_code_converter.py
│ ├── test_relationship_converter.py
│ └── test_snippet_converter.py
├── mock_utils.py
├── model
│ ├── __init__.py
│ ├── test_actor.py
│ ├── test_annotation.py
│ ├── test_checksum.py
│ ├── test_creation_info.py
│ ├── test_document.py
│ ├── test_external_document_ref.py
│ ├── test_external_package_reference.py
│ ├── test_extracted_licensing_info.py
│ ├── test_file.py
│ ├── test_package.py
│ ├── test_package_verification_code.py
│ ├── test_relationship.py
│ ├── test_snippet.py
│ └── test_version.py
├── parser
│ ├── __init__.py
│ ├── all_formats
│ │ ├── __init__.py
│ │ └── test_parse_from_file.py
│ ├── jsonlikedict
│ │ ├── __init__.py
│ │ ├── test_annotation_parser.py
│ │ ├── test_checksum_parser.py
│ │ ├── test_creation_info_parser.py
│ │ ├── test_dict_parsing_functions.py
│ │ ├── test_extracted_licensing_info_parser.py
│ │ ├── test_file_parser.py
│ │ ├── test_license_expression_parser.py
│ │ ├── test_package_parser.py
│ │ ├── test_relationship_parser.py
│ │ └── test_snippet_parser.py
│ ├── rdf
│ │ ├── __init__.py
│ │ ├── data
│ │ │ ├── file_to_test_rdf_parser.rdf.xml
│ │ │ └── invalid_documents
│ │ │ │ ├── file_without_spdx_ids.xml
│ │ │ │ ├── invalid_creation_info.rdf.xml
│ │ │ │ └── invalid_creation_info_with_snippet.rdf.xml
│ │ ├── test_annotation_parser.py
│ │ ├── test_checksum_parser.py
│ │ ├── test_creation_info_parser.py
│ │ ├── test_extracted_licensing_info_parser.py
│ │ ├── test_file_parser.py
│ │ ├── test_graph_parsing_function.py
│ │ ├── test_license_expression_parser.py
│ │ ├── test_package_parser.py
│ │ ├── test_relationship_parser.py
│ │ └── test_snippet_parser.py
│ └── tagvalue
│ │ ├── __init__.py
│ │ ├── test_annotation_parser.py
│ │ ├── test_creation_info_parser.py
│ │ ├── test_extracted_licensing_info_parser.py
│ │ ├── test_file_parser.py
│ │ ├── test_helper_methods.py
│ │ ├── test_package_parser.py
│ │ ├── test_relationship_parser.py
│ │ ├── test_snippet_parser.py
│ │ ├── test_tag_value_lexer.py
│ │ └── test_tag_value_parser.py
├── test_actor_parser.py
├── test_casing_tools.py
├── test_checksum_calculation.py
├── test_cli.py
├── test_datetime_conversions.py
├── test_document_utils.py
├── test_graph_generation.py
├── validation
│ ├── __init__.py
│ ├── test_actor_validator.py
│ ├── test_annotation_validator.py
│ ├── test_checksum_validator.py
│ ├── test_creation_info_validator.py
│ ├── test_document_validator.py
│ ├── test_external_document_ref_validator.py
│ ├── test_external_package_ref_validator.py
│ ├── test_extracted_licensing_info_validator.py
│ ├── test_file_validator.py
│ ├── test_license_expression_validator.py
│ ├── test_package_validator.py
│ ├── test_package_verification_code_validator.py
│ ├── test_relationship_validator.py
│ ├── test_snippet_validator.py
│ ├── test_spdx_id_validators.py
│ └── test_uri_validators.py
└── writer
│ ├── __init__.py
│ ├── json
│ ├── __init__.py
│ ├── expected_results
│ │ ├── __init__.py
│ │ └── expected.json
│ └── test_json_writer.py
│ ├── rdf
│ ├── __init__.py
│ ├── test_annotation_writer.py
│ ├── test_checksum_writer.py
│ ├── test_creation_info_writer.py
│ ├── test_external_document_ref_writer.py
│ ├── test_extracted_licensing_info_writer.py
│ ├── test_file_writer.py
│ ├── test_license_expression_writer.py
│ ├── test_package_writer.py
│ ├── test_rdf_writer.py
│ ├── test_relationship_writer.py
│ ├── test_snippet_writer.py
│ └── test_writer_utils.py
│ └── tagvalue
│ ├── __init__.py
│ ├── expected_results
│ └── expected_tag_value.spdx
│ ├── test_annotation_writer.py
│ ├── test_checksum_writer.py
│ ├── test_creation_info_writer.py
│ ├── test_extracted_licensing_info_writer.py
│ ├── test_file_writer.py
│ ├── test_package_writer.py
│ ├── test_relationship_writer.py
│ ├── test_snippet_writer.py
│ ├── test_tagvalue_writer.py
│ └── test_tagvalue_writer_helper_functions.py
└── spdx3
├── __init__.py
├── bump
├── __init__.py
├── test_actor_bump.py
├── test_bump_utils.py
├── test_checksum_bump.py
├── test_external_document_ref_bump.py
├── test_external_element_bump.py
├── test_file_bump.py
├── test_license_expression_bump.py
├── test_package_bump.py
├── test_relationship_bump.py
├── test_snippet_bump.py
└── test_spdx_document_bump.py
├── fixtures.py
├── model
├── __init__.py
├── licensing
│ ├── __init__.py
│ ├── test_conjunctive_license_set.py
│ ├── test_disjunctive_license_set.py
│ ├── test_or_later_operator.py
│ └── test_with_addition_operator.py
├── model_test_utils.py
├── test_abstract_classes.py
├── test_creation_info.py
├── test_element_and_licensing_subclasses.py
├── test_external_identifier.py
├── test_external_map.py
├── test_external_reference.py
├── test_hash.py
└── test_namespace_map.py
├── validation
├── __init__.py
└── json_ld
│ ├── __init__.py
│ └── test_shacl_validation.py
└── writer
├── __init__.py
├── json_ld
├── __init__.py
└── test_json_ld_writer.py
└── tag_value
└── test_write_document.py
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 4
7 | insert_final_newline = true
8 | end_of_line = lf
9 |
10 | [*.{yml,yaml}]
11 | indent_size = 2
12 |
--------------------------------------------------------------------------------
/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | max-line-length = 119
3 | exclude = src/spdx_tools/spdx/parser/tagvalue/parsetab.py, __init__.py
4 | extend-ignore = E203
5 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "pip" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "weekly"
12 |
--------------------------------------------------------------------------------
/.github/workflows/check_codestyle.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | name: Run Linter
6 |
7 | on:
8 | push:
9 | branches:
10 | - main
11 | pull_request:
12 | workflow_dispatch:
13 |
14 | jobs:
15 | check_code_style:
16 | runs-on: ${{ matrix.os }}
17 | defaults:
18 | run:
19 | shell: bash
20 | strategy:
21 | matrix:
22 | os: [ ubuntu-latest, macos-latest, windows-latest ]
23 | python-version: [ "3.8", "3.9", "3.10", "3.11" ]
24 |
25 | steps:
26 | - uses: actions/checkout@v3
27 | - name: Set up Python ${{ matrix.python-version }}
28 | uses: actions/setup-python@v4
29 | with:
30 | python-version: ${{ matrix.python-version }}
31 | - name: Installation
32 | run: pip install ".[code_style]"
33 | - name: Check code with isort
34 | run: |
35 | isort src tests --check
36 | black src tests --check
37 | flake8 src tests
38 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | name: Generate API docs
5 |
6 | on:
7 | push:
8 | branches:
9 | - main
10 |
11 | permissions:
12 | contents: read
13 |
14 | jobs:
15 | build:
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: actions/checkout@v3
19 | - name: Setup Python
20 | uses: actions/setup-python@v4
21 | with:
22 | python-version: '3.11'
23 | - name: Install dependencies
24 | run: |
25 | sudo apt-get install graphviz-dev
26 | pip install -e ".[test,graph_generation]"
27 | pip install pdoc
28 | - name: Generate docs
29 | run: pdoc spdx_tools -o docs/
30 | - name: Upload docs as artifact
31 | uses: actions/upload-pages-artifact@v1
32 | with:
33 | path: docs/
34 |
35 | deploy:
36 | needs: build
37 | runs-on: ubuntu-latest
38 | permissions:
39 | pages: write
40 | id-token: write
41 | environment:
42 | name: github-pages
43 | url: ${{ steps.deployment.outputs.page_url }}
44 | steps:
45 | - id: deployment
46 | name: Deploy docs to GitHub pages
47 | uses: actions/deploy-pages@v2
48 |
--------------------------------------------------------------------------------
/.github/workflows/install_and_test.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | name: Install and Test
6 |
7 | on:
8 | push:
9 | branches:
10 | - main
11 | pull_request:
12 | workflow_dispatch:
13 |
14 | jobs:
15 | install_and_test:
16 | runs-on: ${{ matrix.os }}
17 | strategy:
18 | matrix:
19 | os: [ ubuntu-latest, macos-latest, windows-latest ]
20 | python-version: [ "3.8", "3.9", "3.10", "3.11" ]
21 |
22 | steps:
23 | - uses: actions/checkout@v3
24 | - name: Set up Python ${{ matrix.python-version }}
25 | uses: actions/setup-python@v4
26 | with:
27 | python-version: ${{ matrix.python-version }}
28 | - name: Installation
29 | run: |
30 | python -m pip install --upgrade pip
31 | python -m pip install --upgrade setuptools wheel setuptools_scm build
32 | python -m build -nwx .
33 | python -m pip install --upgrade ./dist/*.whl
34 | python -m pip install pytest
35 | python -m pip install pyshacl
36 | python -m pip install tzdata
37 | python -m pip install networkx
38 | shell: bash
39 | - name: Run tests
40 | run: pytest
41 | - name: Run CLI
42 | run: pyspdxtools -i ./tests/spdx/data/SPDXJSONExample-v2.3.spdx.json
43 |
--------------------------------------------------------------------------------
/.github/workflows/integration_test.yml:
--------------------------------------------------------------------------------
1 | name: Circle conversion test
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | workflow_dispatch:
9 |
10 | jobs:
11 | install_and_test:
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v3
16 | - name: Set up Python 3.11
17 | uses: actions/setup-python@v4
18 | with:
19 | python-version: 3.11
20 | - name: Installation
21 | run: |
22 | python -m pip install --upgrade pip
23 | python -m pip install --upgrade setuptools wheel setuptools_scm build
24 | python -m build -nwx .
25 | python -m pip install --upgrade ./dist/*.whl
26 | shell: bash
27 | - name: Install jd
28 | uses: jaxxstorm/action-install-gh-release@v1.10.0
29 | with: # Grab the latest version
30 | repo: josephburnett/jd
31 | platform: linux
32 | extension-matching: disable
33 | rename-to: jd
34 | chmod: 0755
35 | - name: Run CLI
36 | run: |
37 | pyspdxtools -i ./tests/spdx/data/circleConversionTestInitialDocument.json -o circleTest.yaml
38 | pyspdxtools -i circleTest.yaml -o circleTest.xml
39 | pyspdxtools -i circleTest.xml -o circleTest.rdf
40 | pyspdxtools -i circleTest.rdf -o circleTest.spdx
41 | pyspdxtools -i circleTest.spdx -o circleTest.json
42 | - name: Compare initial and final json document of the circle conversion test
43 | run: jd -set ./tests/spdx/data/circleConversionTestInitialDocument.json circleTest.json
44 |
--------------------------------------------------------------------------------
/.github/workflows/prepare_release.yml:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | name: Prepare release
6 |
7 | on:
8 | push:
9 | tags: [ 'v*.*.*']
10 |
11 | jobs:
12 | release:
13 | runs-on: ubuntu-latest
14 | permissions:
15 | contents: write
16 |
17 | steps:
18 | - uses: actions/checkout@v3
19 | - name: Set up Python
20 | uses: actions/setup-python@v4
21 | with:
22 | python-version: '3.8'
23 | - name: Set up dependencies
24 | run: |
25 | python -m pip install --upgrade pip
26 | python -m pip install --upgrade setuptools wheel setuptools_scm build twine
27 | python -m pip install -e .
28 | shell: bash
29 | - name: Build wheel
30 | run: python -m build
31 | - name: Verify build
32 | run: twine check dist/*
33 | - name: Create build archive
34 | uses: a7ul/tar-action@v1.1.0
35 | with:
36 | command: c
37 | files: dist
38 | outPath: spdx_tools_dist.tar.gz
39 | - name: Create GitHub release
40 | uses: softprops/action-gh-release@v1
41 | with:
42 | files: spdx_tools_dist.tar.gz
43 | generate_release_notes: true
44 | draft: true
45 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__/
2 | *.py[cod]
3 | *.out
4 | /build/
5 | /dist*/
6 | /tmp/
7 | src/spdx_tools/spdx/parser/tagvalue/parsetab.py
8 | /.cache/
9 |
10 | .tox
11 | venv*
12 |
13 | # virtualenv
14 | /bin
15 | /lib
16 | /Lib
17 | /local
18 | /local/
19 | /.eggs/
20 | *.egg-info/
21 | /Include
22 | /include
23 | /pip-selfcheck.json
24 | .Python
25 | /share/
26 |
27 | # IDEs
28 | .project
29 | .pydevproject
30 | .idea
31 | org.eclipse.core.resources.prefs
32 | .vscode
33 | .pytest_cache
34 |
35 | # Installer logs
36 | pip-log.txt
37 |
38 | # Unit test / coverage reports
39 | .cache
40 | .coverage
41 | .coverage.*
42 | nosetests.xml
43 | htmlcov
44 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | graft data
2 | graft examples
3 | graft spdx
4 | graft tests
5 |
6 | prune src/spdx_tools.egg-info
7 |
8 | include spdx/licenses.json
9 | include README.md
10 | include CHANGELOG.rst
11 | include LICENSE
12 | include MANIFEST.in
13 | include setup.py
14 | include setup.cfg
15 | include .gitignore
16 | include MANIFEST.in
17 | include .travis.yml
18 | include circle.yml
19 | include appveyor.yml
20 |
21 | global-exclude *.py[co] __pycache__ *.*~
22 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: "{build}"
2 | image:
3 | - Visual Studio 2019
4 | environment:
5 | matrix:
6 | - PYTHON_EXE: "C:\\Python37-x64\\python.exe"
7 | - PYTHON_EXE: "C:\\Python38-x64\\python.exe"
8 | - PYTHON_EXE: "C:\\Python39-x64\\python.exe"
9 | - PYTHON_EXE: "C:\\Python310-x64\\python.exe"
10 |
11 | install:
12 | - "%PYTHON_EXE% --version"
13 | - "%PYTHON_EXE% -m pip install --upgrade pip"
14 | - "%PYTHON_EXE% -m pip install --upgrade setuptools setuptools_scm wheel build pytest"
15 | - "%PYTHON_EXE% -m pip install --upgrade -e ."
16 |
17 | build: off
18 |
19 | test_script:
20 | - "%PYTHON_EXE% -m pytest"
21 |
--------------------------------------------------------------------------------
/assets/SPDXJSONExample-v2.3.spdx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/assets/SPDXJSONExample-v2.3.spdx.png
--------------------------------------------------------------------------------
/examples/spdx2_convert_format.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from os import path
5 |
6 | from spdx_tools.spdx.model import Document
7 | from spdx_tools.spdx.writer.write_anything import write_file
8 | from spdx_tools.spdx.parser.parse_anything import parse_file
9 |
10 | # This example demonstrates how to load an existing SPDX2 file and convert it to a different SPDX2 format
11 |
12 | # Provide a path to the input file in the originating format
13 | input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx")
14 | # Parse the original input file (format is deduced automatically from the file extension)
15 | document: Document = parse_file(input_path)
16 | # Write to a different file format (e.g. XML, format is deduced automatically from the file extension)
17 | write_file(document, "converted_format.xml")
18 |
--------------------------------------------------------------------------------
/examples/spdx2_convert_to_spdx3.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from os import path
5 |
6 | from spdx_tools.spdx.model import Document
7 | from spdx_tools.spdx3.payload import Payload
8 | from spdx_tools.spdx3.writer.json_ld.json_ld_writer import write_payload
9 | from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document
10 | from spdx_tools.spdx.parser.parse_anything import parse_file
11 |
12 | # This example demonstrates how to load an existing SPDX2 file and convert it to the SPDX3 format
13 |
14 | # Provide a path to the input file
15 | input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx")
16 | # Parse the original SPDX2 input file
17 | spdx2_document: Document = parse_file(input_path)
18 | # Convert original document to an SPDX3 payload
19 | spdx3_payload: Payload = bump_spdx_document(spdx2_document)
20 | # Write SPDX3 payload in json-ld format
21 | write_payload(spdx3_payload, "spdx2_to_3")
22 |
--------------------------------------------------------------------------------
/examples/spdx2_generate_graph.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from os import path
5 |
6 | from spdx_tools.spdx.graph_generation import export_graph_from_document
7 | from spdx_tools.spdx.model import Document
8 | from spdx_tools.spdx.parser.parse_anything import parse_file
9 |
10 | # This example demonstrates how to generate a relationship graph for an SPDX2 document
11 |
12 | # Provide a path to the input file
13 | input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXJSONExample-v2.3.spdx.json")
14 | # Parse the file
15 | document: Document = parse_file(input_path)
16 | # Generate the graph (note: you need to have installed the optional dependencies networkx and pygraphviz)
17 | export_graph_from_document(document, "graph.png")
18 |
--------------------------------------------------------------------------------
/examples/spdx2_parse_file.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import logging
5 | from os import path
6 |
7 | from spdx_tools.spdx.model.document import Document
8 | from spdx_tools.spdx.parser.error import SPDXParsingError
9 | from spdx_tools.spdx.parser.parse_anything import parse_file
10 |
11 | # This example demonstrates how to parse an existing spdx file.
12 |
13 | # Provide a path to the input file
14 | input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx")
15 | try:
16 | # Try to parse the input file. If successful, returns a Document, otherwise raises an SPDXParsingError
17 | document: Document = parse_file(input_path)
18 | except SPDXParsingError:
19 | logging.exception("Failed to parse spdx file")
20 |
21 | # We can now access attributes from the parsed document
22 | print(f"Parsed document name: {document.creation_info.name}")
23 | creators_as_str = ", ".join([creator.to_serialized_string() for creator in document.creation_info.creators])
24 | print(f"Created on {document.creation_info.created} by {creators_as_str}")
25 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | from setuptools import setup
4 |
5 | if __name__ == "__main__":
6 | setup()
7 |
--------------------------------------------------------------------------------
/src/spdx_tools/common/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/common/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/common/spdx_licensing.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from license_expression import get_spdx_licensing
5 |
6 | # this getter takes quite long so we only call it once in this singleton module
7 | spdx_licensing = get_spdx_licensing()
8 |
--------------------------------------------------------------------------------
/src/spdx_tools/common/typing/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/common/typing/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/common/typing/constructor_type_errors.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List
5 |
6 |
7 | class ConstructorTypeErrors(TypeError):
8 | """
9 | Helper class that holds a list of error messages. Intended to capture all TypeErrors encountered during a
10 | constructor call, instead of raising only the first one.
11 | """
12 |
13 | messages: List[str]
14 |
15 | def __init__(self, messages: List[str]):
16 | self.messages = messages
17 |
18 | def get_messages(self):
19 | return list(self.messages)
20 |
--------------------------------------------------------------------------------
/src/spdx_tools/common/typing/type_checks.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from dataclasses import fields
5 |
6 | from beartype.typing import Any, Dict
7 |
8 | from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors
9 |
10 |
11 | def check_types_and_set_values(instance_under_construction: Any, local_variables: Dict) -> None:
12 | """
13 | Helper method to accumulate all type errors encountered during a constructor call and return them in a
14 | ConstructorTypeErrors instance.
15 | Background: Our setters are enhanced with runtime typechecks using beartype. However, this means that by
16 | default, a TypeError is raised on the first type violation that is encountered. We consider it more helpful to
17 | return all type violations in one go.
18 | As an aside, defining constructors "manually" using this utility method helps avoid a nasty PyCharm bug:
19 | https://youtrack.jetbrains.com/issue/PY-34569
20 | """
21 | errors = []
22 | for field in fields(instance_under_construction):
23 | key = field.name
24 | value = local_variables.get(key)
25 | try:
26 | setattr(instance_under_construction, key, value)
27 | except TypeError as err:
28 | error_message: str = err.args[0]
29 | errors.append(error_message)
30 | if errors:
31 | raise ConstructorTypeErrors(errors)
32 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/casing_tools.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from re import sub
5 |
6 |
7 | def snake_case_to_camel_case(snake_case_string: str) -> str:
8 | each_word_capitalized = sub(r"[_\-]+", " ", snake_case_string).title().replace(" ", "")
9 | return each_word_capitalized[0].lower() + each_word_capitalized[1:]
10 |
11 |
12 | def camel_case_to_snake_case(camel_case_string: str) -> str:
13 | snake_case_string = sub("(?!^)([A-Z]+)", r"_\1", camel_case_string).lower()
14 | return snake_case_string
15 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/clitools/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/clitools/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/constants.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | DOCUMENT_SPDX_ID = "SPDXRef-DOCUMENT"
5 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/datetime_conversions.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from datetime import datetime, timezone
5 |
6 |
7 | def datetime_from_str(date_str: str) -> datetime:
8 | if not isinstance(date_str, str):
9 | raise TypeError(f"Could not convert str to datetime, invalid type: {type(date_str).__name__}")
10 |
11 | date = datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%SZ") # raises ValueError if format does not match
12 | return date
13 |
14 |
15 | def datetime_to_iso_string(date: datetime) -> str:
16 | """
17 | Return an ISO-8601 representation of a datetime object.
18 | """
19 | if date.tzinfo is not None:
20 | date = date.astimezone(timezone.utc) # Convert aware datetimes to UTC
21 | date = date.replace(tzinfo=None) # Convert to naive datetime
22 |
23 | if date.microsecond != 0:
24 | date = date.replace(microsecond=0) # SPDX does not support microseconds
25 |
26 | return date.isoformat() + "Z"
27 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/formats.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import Enum, auto
5 |
6 | from spdx_tools.spdx.parser.error import SPDXParsingError
7 |
8 |
9 | class FileFormat(Enum):
10 | JSON = auto()
11 | YAML = auto()
12 | XML = auto()
13 | TAG_VALUE = auto()
14 | RDF_XML = auto()
15 |
16 |
17 | def file_name_to_format(file_name: str) -> FileFormat:
18 | if file_name.endswith(".rdf") or file_name.endswith(".rdf.xml"):
19 | return FileFormat.RDF_XML
20 | elif file_name.endswith(".tag") or file_name.endswith(".spdx"):
21 | return FileFormat.TAG_VALUE
22 | elif file_name.endswith(".json"):
23 | return FileFormat.JSON
24 | elif file_name.endswith(".xml"):
25 | return FileFormat.XML
26 | elif file_name.endswith(".yaml") or file_name.endswith(".yml"):
27 | return FileFormat.YAML
28 | else:
29 | raise SPDXParsingError(["Unsupported SPDX file type: " + str(file_name)])
30 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/jsonschema/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/annotation_converter.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import Any, Type
5 |
6 | from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string
7 | from spdx_tools.spdx.jsonschema.annotation_properties import AnnotationProperty
8 | from spdx_tools.spdx.jsonschema.converter import TypedConverter
9 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
10 | from spdx_tools.spdx.model import Annotation, Document
11 |
12 |
13 | class AnnotationConverter(TypedConverter[Annotation]):
14 | def _get_property_value(
15 | self, annotation: Annotation, annotation_property: AnnotationProperty, document: Document = None
16 | ) -> Any:
17 | if annotation_property == AnnotationProperty.ANNOTATION_DATE:
18 | return datetime_to_iso_string(annotation.annotation_date)
19 | elif annotation_property == AnnotationProperty.ANNOTATION_TYPE:
20 | return annotation.annotation_type.name
21 | elif annotation_property == AnnotationProperty.ANNOTATOR:
22 | return annotation.annotator.to_serialized_string()
23 | elif annotation_property == AnnotationProperty.COMMENT:
24 | return annotation.annotation_comment
25 |
26 | def get_json_type(self) -> Type[JsonProperty]:
27 | return AnnotationProperty
28 |
29 | def get_data_model_type(self) -> Type[Annotation]:
30 | return Annotation
31 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/annotation_properties.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import auto
5 |
6 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
7 |
8 |
9 | class AnnotationProperty(JsonProperty):
10 | ANNOTATION_DATE = auto()
11 | ANNOTATION_TYPE = auto()
12 | ANNOTATOR = auto()
13 | COMMENT = auto()
14 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/checksum_converter.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import Type
5 |
6 | from spdx_tools.spdx.jsonschema.checksum_properties import ChecksumProperty
7 | from spdx_tools.spdx.jsonschema.converter import TypedConverter
8 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
9 | from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, Document
10 |
11 |
12 | class ChecksumConverter(TypedConverter[Checksum]):
13 | def get_data_model_type(self) -> Type[Checksum]:
14 | return Checksum
15 |
16 | def get_json_type(self) -> Type[JsonProperty]:
17 | return ChecksumProperty
18 |
19 | def _get_property_value(
20 | self, checksum: Checksum, checksum_property: ChecksumProperty, _document: Document = None
21 | ) -> str:
22 | if checksum_property == ChecksumProperty.ALGORITHM:
23 | return algorithm_to_json_string(checksum.algorithm)
24 | elif checksum_property == ChecksumProperty.CHECKSUM_VALUE:
25 | return checksum.value
26 |
27 |
28 | def algorithm_to_json_string(algorithm: ChecksumAlgorithm) -> str:
29 | name_with_dash: str = algorithm.name.replace("_", "-")
30 | if "BLAKE2B" in name_with_dash:
31 | return name_with_dash.replace("BLAKE2B", "BLAKE2b")
32 | return name_with_dash
33 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/checksum_properties.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import auto
5 |
6 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
7 |
8 |
9 | class ChecksumProperty(JsonProperty):
10 | ALGORITHM = auto()
11 | CHECKSUM_VALUE = auto()
12 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/creation_info_properties.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import auto
5 |
6 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
7 |
8 |
9 | class CreationInfoProperty(JsonProperty):
10 | CREATED = auto()
11 | CREATORS = auto()
12 | LICENSE_LIST_VERSION = auto()
13 | COMMENT = auto()
14 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/document_properties.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import auto
5 |
6 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
7 |
8 |
9 | class DocumentProperty(JsonProperty):
10 | SPDX_ID = auto()
11 | ANNOTATIONS = auto()
12 | COMMENT = auto()
13 | CREATION_INFO = auto()
14 | DATA_LICENSE = auto()
15 | EXTERNAL_DOCUMENT_REFS = auto()
16 | HAS_EXTRACTED_LICENSING_INFOS = auto()
17 | NAME = auto()
18 | SPDX_VERSION = auto()
19 | DOCUMENT_NAMESPACE = auto()
20 | PACKAGES = auto()
21 | FILES = auto()
22 | SNIPPETS = auto()
23 | RELATIONSHIPS = auto()
24 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/external_document_ref_properties.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import auto
5 |
6 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
7 |
8 |
9 | class ExternalDocumentRefProperty(JsonProperty):
10 | EXTERNAL_DOCUMENT_ID = auto()
11 | SPDX_DOCUMENT = auto()
12 | CHECKSUM = auto()
13 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import Any, Type
5 |
6 | from spdx_tools.spdx.jsonschema.converter import TypedConverter
7 | from spdx_tools.spdx.jsonschema.external_package_ref_properties import ExternalPackageRefProperty
8 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
9 | from spdx_tools.spdx.model import Document, ExternalPackageRef
10 |
11 |
12 | class ExternalPackageRefConverter(TypedConverter[ExternalPackageRef]):
13 | def _get_property_value(
14 | self,
15 | external_ref: ExternalPackageRef,
16 | external_ref_property: ExternalPackageRefProperty,
17 | document: Document = None,
18 | ) -> Any:
19 | if external_ref_property == ExternalPackageRefProperty.COMMENT:
20 | return external_ref.comment
21 | elif external_ref_property == ExternalPackageRefProperty.REFERENCE_CATEGORY:
22 | return external_ref.category.name
23 | elif external_ref_property == ExternalPackageRefProperty.REFERENCE_LOCATOR:
24 | return external_ref.locator
25 | elif external_ref_property == ExternalPackageRefProperty.REFERENCE_TYPE:
26 | return external_ref.reference_type
27 |
28 | def get_json_type(self) -> Type[JsonProperty]:
29 | return ExternalPackageRefProperty
30 |
31 | def get_data_model_type(self) -> Type[ExternalPackageRef]:
32 | return ExternalPackageRef
33 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/external_package_ref_properties.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import auto
5 |
6 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
7 |
8 |
9 | class ExternalPackageRefProperty(JsonProperty):
10 | COMMENT = auto()
11 | REFERENCE_CATEGORY = auto()
12 | REFERENCE_LOCATOR = auto()
13 | REFERENCE_TYPE = auto()
14 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_properties.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import auto
5 |
6 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
7 |
8 |
9 | class ExtractedLicensingInfoProperty(JsonProperty):
10 | COMMENT = auto()
11 | EXTRACTED_TEXT = auto()
12 | LICENSE_ID = auto()
13 | NAME = auto()
14 | SEE_ALSOS = auto()
15 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/file_properties.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import auto
5 |
6 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
7 |
8 |
9 | class FileProperty(JsonProperty):
10 | SPDX_ID = auto()
11 | ANNOTATIONS = auto()
12 | ARTIFACT_OFS = auto()
13 | ATTRIBUTION_TEXTS = auto()
14 | CHECKSUMS = auto()
15 | COMMENT = auto()
16 | COPYRIGHT_TEXT = auto()
17 | FILE_CONTRIBUTORS = auto()
18 | FILE_DEPENDENCIES = auto()
19 | FILE_NAME = auto()
20 | FILE_TYPES = auto()
21 | LICENSE_COMMENTS = auto()
22 | LICENSE_CONCLUDED = auto()
23 | LICENSE_INFO_IN_FILES = auto()
24 | NOTICE_TEXT = auto()
25 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/json_property.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import Enum
5 |
6 |
7 | class JsonProperty(Enum):
8 | """
9 | Parent class for all json property classes. Not meant to be instantiated directly, only to have a common parent
10 | type that can be used in type hints.
11 | In general, all the child enums list the properties of the corresponding objects from the json schema.
12 | """
13 |
14 | pass
15 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/optional_utils.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import Callable, Optional, TypeVar
5 |
6 | T = TypeVar("T")
7 | S = TypeVar("S")
8 |
9 |
10 | def apply_if_present(function: Callable[[T], S], optional_value: Optional[T]) -> Optional[S]:
11 | """
12 | Apply the passed function to the optional value if it is not None. Else returns None.
13 | """
14 | return function(optional_value) if optional_value is not None else None
15 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/package_properties.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import auto
5 |
6 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
7 |
8 |
9 | class PackageProperty(JsonProperty):
10 | SPDX_ID = auto()
11 | ANNOTATIONS = auto()
12 | ATTRIBUTION_TEXTS = auto()
13 | BUILT_DATE = auto()
14 | CHECKSUMS = auto()
15 | COMMENT = auto()
16 | COPYRIGHT_TEXT = auto()
17 | DESCRIPTION = auto()
18 | DOWNLOAD_LOCATION = auto()
19 | EXTERNAL_REFS = auto()
20 | FILES_ANALYZED = auto()
21 | HOMEPAGE = auto()
22 | LICENSE_COMMENTS = auto()
23 | LICENSE_CONCLUDED = auto()
24 | LICENSE_DECLARED = auto()
25 | LICENSE_INFO_FROM_FILES = auto()
26 | NAME = auto()
27 | ORIGINATOR = auto()
28 | PACKAGE_FILE_NAME = auto()
29 | PACKAGE_VERIFICATION_CODE = auto()
30 | PRIMARY_PACKAGE_PURPOSE = auto()
31 | RELEASE_DATE = auto()
32 | SOURCE_INFO = auto()
33 | SUMMARY = auto()
34 | SUPPLIER = auto()
35 | VALID_UNTIL_DATE = auto()
36 | VERSION_INFO = auto()
37 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import Any, Type
5 |
6 | from spdx_tools.spdx.jsonschema.converter import TypedConverter
7 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
8 | from spdx_tools.spdx.jsonschema.package_verification_code_properties import PackageVerificationCodeProperty
9 | from spdx_tools.spdx.model import Document, PackageVerificationCode
10 |
11 |
12 | class PackageVerificationCodeConverter(TypedConverter[PackageVerificationCode]):
13 | def _get_property_value(
14 | self,
15 | verification_code: PackageVerificationCode,
16 | verification_code_property: PackageVerificationCodeProperty,
17 | document: Document = None,
18 | ) -> Any:
19 | if verification_code_property == PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_EXCLUDED_FILES:
20 | return verification_code.excluded_files or None
21 | elif verification_code_property == PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_VALUE:
22 | return verification_code.value
23 |
24 | def get_json_type(self) -> Type[JsonProperty]:
25 | return PackageVerificationCodeProperty
26 |
27 | def get_data_model_type(self) -> Type[PackageVerificationCode]:
28 | return PackageVerificationCode
29 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/package_verification_code_properties.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import auto
5 |
6 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
7 |
8 |
9 | class PackageVerificationCodeProperty(JsonProperty):
10 | PACKAGE_VERIFICATION_CODE_EXCLUDED_FILES = auto()
11 | PACKAGE_VERIFICATION_CODE_VALUE = auto()
12 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/relationship_converter.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import Any, Type
5 |
6 | from spdx_tools.spdx.jsonschema.converter import TypedConverter
7 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
8 | from spdx_tools.spdx.jsonschema.relationship_properties import RelationshipProperty
9 | from spdx_tools.spdx.model import Document, Relationship
10 |
11 |
12 | class RelationshipConverter(TypedConverter[Relationship]):
13 | def _get_property_value(
14 | self, relationship: Relationship, relationship_property: RelationshipProperty, document: Document = None
15 | ) -> Any:
16 | if relationship_property == RelationshipProperty.SPDX_ELEMENT_ID:
17 | return relationship.spdx_element_id
18 | elif relationship_property == RelationshipProperty.COMMENT:
19 | return relationship.comment
20 | elif relationship_property == RelationshipProperty.RELATED_SPDX_ELEMENT:
21 | return str(relationship.related_spdx_element_id)
22 | elif relationship_property == RelationshipProperty.RELATIONSHIP_TYPE:
23 | return relationship.relationship_type.name
24 |
25 | def get_json_type(self) -> Type[JsonProperty]:
26 | return RelationshipProperty
27 |
28 | def get_data_model_type(self) -> Type[Relationship]:
29 | return Relationship
30 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/relationship_properties.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import auto
5 |
6 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
7 |
8 |
9 | class RelationshipProperty(JsonProperty):
10 | SPDX_ELEMENT_ID = auto()
11 | COMMENT = auto()
12 | RELATED_SPDX_ELEMENT = auto()
13 | RELATIONSHIP_TYPE = auto()
14 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/jsonschema/snippet_properties.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import auto
5 |
6 | from spdx_tools.spdx.jsonschema.json_property import JsonProperty
7 |
8 |
9 | class SnippetProperty(JsonProperty):
10 | SPDX_ID = auto()
11 | ANNOTATIONS = auto()
12 | ATTRIBUTION_TEXTS = auto()
13 | COMMENT = auto()
14 | COPYRIGHT_TEXT = auto()
15 | LICENSE_COMMENTS = auto()
16 | LICENSE_CONCLUDED = auto()
17 | LICENSE_INFO_IN_SNIPPETS = auto()
18 | NAME = auto()
19 | RANGES = auto()
20 | SNIPPET_FROM_FILE = auto()
21 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/model/__init__.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion
5 | from spdx_tools.spdx.model.spdx_none import SpdxNone
6 | from spdx_tools.spdx.model.version import Version
7 | from spdx_tools.spdx.model.actor import Actor, ActorType
8 | from spdx_tools.spdx.model.annotation import Annotation, AnnotationType
9 | from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm
10 | from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef
11 | from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo
12 | from spdx_tools.spdx.model.file import File, FileType
13 | from spdx_tools.spdx.model.package import (
14 | ExternalPackageRef,
15 | ExternalPackageRefCategory,
16 | Package,
17 | PackagePurpose,
18 | PackageVerificationCode,
19 | )
20 | from spdx_tools.spdx.model.relationship import Relationship, RelationshipType
21 | from spdx_tools.spdx.model.snippet import Snippet
22 | from spdx_tools.spdx.model.document import CreationInfo, Document
23 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/model/actor.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import Enum, auto
5 |
6 | from beartype.typing import Optional
7 |
8 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
9 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
10 |
11 |
12 | class ActorType(Enum):
13 | PERSON = auto()
14 | ORGANIZATION = auto()
15 | TOOL = auto()
16 |
17 |
18 | @dataclass_with_properties
19 | class Actor:
20 | actor_type: ActorType
21 | name: str
22 | email: Optional[str] = None
23 |
24 | def __init__(self, actor_type: ActorType, name: str, email: Optional[str] = None):
25 | check_types_and_set_values(self, locals())
26 |
27 | def to_serialized_string(self) -> str:
28 | """
29 | All serialization formats use the same representation of an actor, so this method is included in the data model
30 | """
31 | optional_email = f" ({self.email})" if self.email else ""
32 | return "".join([f"{self.actor_type.name.title()}:", f" {self.name}", optional_email])
33 |
34 | def __str__(self):
35 | return self.to_serialized_string()
36 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/model/annotation.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from datetime import datetime
5 | from enum import Enum, auto
6 |
7 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
8 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
9 | from spdx_tools.spdx.model import Actor
10 |
11 |
12 | class AnnotationType(Enum):
13 | REVIEW = auto()
14 | OTHER = auto()
15 |
16 |
17 | @dataclass_with_properties
18 | class Annotation:
19 | spdx_id: str
20 | annotation_type: AnnotationType
21 | annotator: Actor
22 | annotation_date: datetime
23 | annotation_comment: str
24 |
25 | def __init__(
26 | self,
27 | spdx_id: str,
28 | annotation_type: AnnotationType,
29 | annotator: Actor,
30 | annotation_date: datetime,
31 | annotation_comment: str,
32 | ):
33 | check_types_and_set_values(self, locals())
34 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/model/checksum.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import Enum, auto
5 |
6 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
7 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
8 |
9 |
10 | class ChecksumAlgorithm(Enum):
11 | SHA1 = auto()
12 | SHA224 = auto()
13 | SHA256 = auto()
14 | SHA384 = auto()
15 | SHA512 = auto()
16 | SHA3_256 = auto()
17 | SHA3_384 = auto()
18 | SHA3_512 = auto()
19 | BLAKE2B_256 = auto()
20 | BLAKE2B_384 = auto()
21 | BLAKE2B_512 = auto()
22 | BLAKE3 = auto()
23 | MD2 = auto()
24 | MD4 = auto()
25 | MD5 = auto()
26 | MD6 = auto()
27 | ADLER32 = auto()
28 |
29 |
30 | @dataclass_with_properties
31 | class Checksum:
32 | algorithm: ChecksumAlgorithm
33 | value: str
34 |
35 | def __init__(self, algorithm: ChecksumAlgorithm, value: str):
36 | check_types_and_set_values(self, locals())
37 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/model/external_document_ref.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
6 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
7 | from spdx_tools.spdx.model import Checksum
8 |
9 |
10 | @dataclass_with_properties
11 | class ExternalDocumentRef:
12 | document_ref_id: str # of the form "DocumentRef-[idstring]"
13 | document_uri: str
14 | checksum: Checksum
15 |
16 | def __init__(self, document_ref_id: str, document_uri: str, checksum: Checksum):
17 | check_types_and_set_values(self, locals())
18 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/model/extracted_licensing_info.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from dataclasses import field
5 |
6 | from beartype.typing import List, Optional, Union
7 |
8 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
9 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
10 | from spdx_tools.spdx.model import SpdxNoAssertion
11 |
12 |
13 | @dataclass_with_properties
14 | class ExtractedLicensingInfo:
15 | license_id: Optional[str] = None
16 | extracted_text: Optional[str] = None
17 | license_name: Optional[Union[str, SpdxNoAssertion]] = None
18 | cross_references: List[str] = field(default_factory=list)
19 | comment: Optional[str] = None
20 |
21 | def __init__(
22 | self,
23 | license_id: Optional[str] = None,
24 | extracted_text: Optional[str] = None,
25 | license_name: Optional[Union[str, SpdxNoAssertion]] = None,
26 | cross_references: List[str] = None,
27 | comment: Optional[str] = None,
28 | ):
29 | cross_references = [] if cross_references is None else cross_references
30 | check_types_and_set_values(self, locals())
31 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/model/spdx_no_assertion.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | SPDX_NO_ASSERTION_STRING = "NOASSERTION"
6 |
7 |
8 | class SpdxNoAssertion:
9 | """
10 | Represents the SPDX NOASSERTION value.
11 | """
12 |
13 | def __str__(self):
14 | return SPDX_NO_ASSERTION_STRING
15 |
16 | def __repr__(self):
17 | return SPDX_NO_ASSERTION_STRING
18 |
19 | def __eq__(self, other):
20 | return isinstance(other, SpdxNoAssertion)
21 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/model/spdx_none.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | SPDX_NONE_STRING = "NONE"
6 |
7 |
8 | class SpdxNone:
9 | """
10 | Represents the SPDX NONE value.
11 | """
12 |
13 | def __str__(self):
14 | return SPDX_NONE_STRING
15 |
16 | def __repr__(self):
17 | return SPDX_NONE_STRING
18 |
19 | def __eq__(self, other):
20 | return isinstance(other, SpdxNone)
21 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/model/version.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 |
6 | import re
7 | from re import Pattern
8 |
9 |
10 | class Version:
11 | VERSION_REGEX: Pattern = re.compile(r"^(\d+)\.(\d+)$")
12 |
13 | major: int
14 | minor: int
15 |
16 | @classmethod
17 | def is_valid_version_string(cls, value: str) -> bool:
18 | return cls.VERSION_REGEX.match(value) is not None
19 |
20 | # No type hint for Python reasons.
21 | # See https://stackoverflow.com/questions/33533148/how-do-i-type-hint-a-method-with-the-type-of-the-enclosing-class
22 | @classmethod
23 | def from_string(cls, value: str):
24 | if not Version.is_valid_version_string(value):
25 | raise ValueError(f"{value} is not a valid version string")
26 |
27 | match = cls.VERSION_REGEX.match(value)
28 | return cls(int(match.group(1)), int(match.group(2)))
29 |
30 | def __init__(self, major: int, minor: int):
31 | self.major = major
32 | self.minor = minor
33 |
34 | def __str__(self):
35 | return f"{self.major}.{self.minor}"
36 |
37 | def __eq__(self, other):
38 | if not isinstance(other, Version):
39 | return False
40 | return self.major == other.major and self.minor == other.minor
41 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/parser/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/error.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List
5 |
6 |
7 | class SPDXParsingError(Exception):
8 | messages: List[str]
9 |
10 | def __init__(self, messages: List[str]):
11 | self.messages = messages
12 |
13 | def get_messages(self):
14 | return list(self.messages)
15 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/json/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/parser/json/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/json/json_parser.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import json
5 |
6 | from beartype.typing import Dict
7 |
8 | from spdx_tools.spdx.model import Document
9 | from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser
10 |
11 |
12 | def parse_from_file(file_name: str, encoding: str = "utf-8") -> Document:
13 | with open(file_name, encoding=encoding) as file:
14 | input_doc_as_dict: Dict = json.load(file)
15 |
16 | return JsonLikeDictParser().parse(input_doc_as_dict)
17 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/jsonlikedict/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/parser/jsonlikedict/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import Dict, Optional
5 |
6 | from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm
7 | from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import json_str_to_enum_name
8 | from spdx_tools.spdx.parser.logger import Logger
9 | from spdx_tools.spdx.parser.parsing_functions import (
10 | construct_or_raise_parsing_error,
11 | raise_parsing_error_if_logger_has_messages,
12 | )
13 |
14 |
15 | class ChecksumParser:
16 | logger: Logger
17 |
18 | def __init__(self):
19 | self.logger = Logger()
20 |
21 | @staticmethod
22 | def parse_checksum(checksum_dict: Dict) -> Checksum:
23 | logger = Logger()
24 | algorithm: str = json_str_to_enum_name(checksum_dict.get("algorithm", ""))
25 | try:
26 | checksum_algorithm = ChecksumAlgorithm[algorithm]
27 | except KeyError:
28 | logger.append(f"Invalid ChecksumAlgorithm: {algorithm}")
29 | checksum_algorithm = None
30 | checksum_value: Optional[str] = checksum_dict.get("checksumValue")
31 | raise_parsing_error_if_logger_has_messages(logger, "Checksum")
32 | checksum = construct_or_raise_parsing_error(Checksum, dict(algorithm=checksum_algorithm, value=checksum_value))
33 | return checksum
34 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import Union
5 | from license_expression import ExpressionError, LicenseExpression
6 |
7 | from spdx_tools.common.spdx_licensing import spdx_licensing
8 | from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone
9 | from spdx_tools.spdx.parser.error import SPDXParsingError
10 |
11 |
12 | class LicenseExpressionParser:
13 | @staticmethod
14 | def parse_license_expression(license_expression_str: str) -> Union[LicenseExpression, SpdxNone, SpdxNoAssertion]:
15 | if isinstance(license_expression_str, str):
16 | if license_expression_str.upper() == "NOASSERTION":
17 | return SpdxNoAssertion()
18 | if license_expression_str.upper() == "NONE":
19 | return SpdxNone()
20 |
21 | try:
22 | license_expression = spdx_licensing.parse(license_expression_str)
23 | except ExpressionError as err:
24 | err_msg = f'Error parsing LicenseExpression: "{license_expression_str}"'
25 | if err.args:
26 | err_msg += f": {err.args[0]}"
27 | raise SPDXParsingError([err_msg])
28 |
29 | return license_expression
30 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/logger.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List
5 |
6 |
7 | class Logger:
8 | messages: List[str]
9 |
10 | def __init__(self):
11 | self.messages = []
12 |
13 | def append(self, message: str):
14 | self.messages.append(message)
15 |
16 | def extend(self, messages_to_append: List[str]):
17 | self.messages.extend(messages_to_append)
18 |
19 | def has_messages(self):
20 | return bool(self.messages)
21 |
22 | def get_messages(self):
23 | return list(self.messages)
24 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/parsing_functions.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import Any, Dict
5 |
6 | from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors
7 | from spdx_tools.spdx.parser.error import SPDXParsingError
8 | from spdx_tools.spdx.parser.logger import Logger
9 |
10 |
11 | def construct_or_raise_parsing_error(object_to_construct: Any, args_for_construction: Dict) -> Any:
12 | try:
13 | constructed_object = object_to_construct(**args_for_construction)
14 | except ConstructorTypeErrors as err:
15 | raise SPDXParsingError([f"Error while constructing {object_to_construct.__name__}: {err.get_messages()}"])
16 | except TypeError as err:
17 | raise SPDXParsingError([f"Error while constructing {object_to_construct.__name__}: {err.args[0]}"])
18 | return constructed_object
19 |
20 |
21 | def raise_parsing_error_if_logger_has_messages(logger: Logger, parsed_object_name: str = None):
22 | if logger.has_messages():
23 | if parsed_object_name:
24 | raise SPDXParsingError([f"Error while parsing {parsed_object_name}: {logger.get_messages()}"])
25 | else:
26 | raise SPDXParsingError(logger.get_messages())
27 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/rdf/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/parser/rdf/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/tagvalue/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/parser/tagvalue/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.spdx.model import Document
5 | from spdx_tools.spdx.parser.tagvalue.parser import Parser
6 |
7 |
8 | def parse_from_file(file_name: str, encoding: str = "utf-8") -> Document:
9 | parser = Parser()
10 | with open(file_name, encoding=encoding) as file:
11 | data = file.read()
12 | document: Document = parser.parse(data)
13 | return document
14 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/xml/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/parser/xml/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/yaml/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/parser/yaml/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/parser/yaml/yaml_parser.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import yaml
5 | from beartype.typing import Dict
6 |
7 | from spdx_tools.spdx.model import Document
8 | from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser
9 |
10 |
11 | def parse_from_file(file_name: str, encoding: str = "utf-8") -> Document:
12 | with open(file_name, encoding=encoding) as file:
13 | input_doc_as_dict: Dict = yaml.safe_load(file)
14 |
15 | return JsonLikeDictParser().parse(input_doc_as_dict)
16 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/py.typed
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/rdfschema/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/rdfschema/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/rdfschema/namespace.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from rdflib import Namespace
5 |
6 | SPDX_NAMESPACE = Namespace("http://spdx.org/rdf/terms#")
7 | POINTER_NAMESPACE = Namespace("http://www.w3.org/2009/pointers#")
8 | REFERENCE_NAMESPACE = Namespace("http://spdx.org/rdf/references/")
9 | LICENSE_NAMESPACE = Namespace("http://spdx.org/licenses/")
10 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/validation/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/validation/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/validation/actor_validator.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | from beartype.typing import List
6 |
7 | from spdx_tools.spdx.model import Actor, ActorType
8 | from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage
9 |
10 |
11 | def validate_actors(actors: List[Actor], parent_id: str) -> List[ValidationMessage]:
12 | validation_messages = []
13 | for actor in actors:
14 | validation_messages.extend(validate_actor(actor, parent_id))
15 |
16 | return validation_messages
17 |
18 |
19 | def validate_actor(actor: Actor, parent_id: str) -> List[ValidationMessage]:
20 | validation_messages = []
21 |
22 | if actor.actor_type == ActorType.TOOL and actor.email is not None:
23 | validation_messages.append(
24 | ValidationMessage(
25 | f"email must be None if actor_type is TOOL, but is: {actor.email}",
26 | ValidationContext(parent_id=parent_id, element_type=SpdxElementType.ACTOR, full_element=actor),
27 | )
28 | )
29 |
30 | return validation_messages
31 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/validation/annotation_validator.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | from beartype.typing import List
6 |
7 | from spdx_tools.spdx.model import Annotation, Document
8 | from spdx_tools.spdx.validation.actor_validator import validate_actor
9 | from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id
10 | from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage
11 |
12 |
13 | def validate_annotations(annotations: List[Annotation], document: Document) -> List[ValidationMessage]:
14 | validation_messages = []
15 | for annotation in annotations:
16 | validation_messages.extend(validate_annotation(annotation, document))
17 |
18 | return validation_messages
19 |
20 |
21 | def validate_annotation(annotation: Annotation, document: Document) -> List[ValidationMessage]:
22 | validation_messages = []
23 | context = ValidationContext(element_type=SpdxElementType.ANNOTATION, full_element=annotation)
24 |
25 | validation_messages.extend(validate_actor(annotation.annotator, "annotation"))
26 |
27 | messages: List[str] = validate_spdx_id(annotation.spdx_id, document, check_document=True)
28 | for message in messages:
29 | validation_messages.append(ValidationMessage(message, context))
30 |
31 | return validation_messages
32 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/validation/package_verification_code_validator.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | import re
6 |
7 | from beartype.typing import List
8 |
9 | from spdx_tools.spdx.model import PackageVerificationCode
10 | from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage
11 |
12 |
13 | def validate_verification_code(verification_code: PackageVerificationCode, parent_id: str) -> List[ValidationMessage]:
14 | validation_messages: List[ValidationMessage] = []
15 | context = ValidationContext(
16 | parent_id=parent_id, element_type=SpdxElementType.PACKAGE_VERIFICATION_CODE, full_element=verification_code
17 | )
18 |
19 | for file in verification_code.excluded_files:
20 | if file.startswith("/"):
21 | validation_messages.append(
22 | ValidationMessage(f'file name must not be an absolute path starting with "/", but is: {file}', context)
23 | )
24 |
25 | value: str = verification_code.value
26 | if not re.match("^[0-9a-f]{40}$", value):
27 | validation_messages.append(
28 | ValidationMessage(
29 | f"value of verification_code must consist of 40 lowercase hexadecimal digits, but is: {value} "
30 | f"(length: {len(value)} digits)",
31 | context,
32 | )
33 | )
34 |
35 | return validation_messages
36 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/validation/validation_message.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | from dataclasses import dataclass
6 | from enum import Enum, auto
7 |
8 | from beartype.typing import Any, Optional
9 |
10 |
11 | class SpdxElementType(Enum):
12 | LICENSE_EXPRESSION = auto()
13 | PACKAGE_VERIFICATION_CODE = auto()
14 | EXTERNAL_DOCUMENT_REF = auto()
15 | CHECKSUM = auto()
16 | EXTERNAL_PACKAGE_REF = auto()
17 | ACTOR = auto()
18 | DOCUMENT = auto()
19 | CREATION_INFO = auto()
20 | PACKAGE = auto()
21 | FILE = auto()
22 | SNIPPET = auto()
23 | ANNOTATION = auto()
24 | RELATIONSHIP = auto()
25 | EXTRACTED_LICENSING_INFO = auto()
26 |
27 |
28 | @dataclass(frozen=True)
29 | class ValidationContext:
30 | spdx_id: Optional[str] = None # not every type has an id, or it might be missing
31 | parent_id: Optional[str] = None # if a parent is known and has a valid id
32 | element_type: Optional[SpdxElementType] = None
33 | full_element: Any = None # can be any class of the data model
34 |
35 |
36 | @dataclass(frozen=True)
37 | class ValidationMessage:
38 | validation_message: str
39 | context: ValidationContext
40 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/writer/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/json/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/writer/json/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/json/json_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import json
5 |
6 | from beartype.typing import IO
7 |
8 | from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter
9 | from spdx_tools.spdx.model import Document
10 | from spdx_tools.spdx.writer.write_utils import convert, validate_and_deduplicate
11 |
12 |
13 | def write_document_to_stream(
14 | document: Document,
15 | stream: IO[str],
16 | validate: bool = True,
17 | converter: DocumentConverter = None,
18 | drop_duplicates: bool = True,
19 | ):
20 | """
21 | Serializes the provided document to json and writes it to a file with the provided name. Unless validate is set
22 | to False, validates the document before serialization. Unless a DocumentConverter instance is provided,
23 | a new one is created.
24 | """
25 | document = validate_and_deduplicate(document, validate, drop_duplicates)
26 | document_dict = convert(document, converter)
27 | json.dump(document_dict, stream, indent=4)
28 |
29 |
30 | def write_document_to_file(
31 | document: Document,
32 | file_name: str,
33 | validate: bool = True,
34 | converter: DocumentConverter = None,
35 | drop_duplicates: bool = True,
36 | ):
37 | with open(file_name, "w", encoding="utf-8") as out:
38 | write_document_to_stream(document, out, validate, converter, drop_duplicates)
39 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/rdf/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/writer/rdf/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/rdf/checksum_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from rdflib import RDF, BNode, Graph, Literal, URIRef
5 |
6 | from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm
7 | from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE
8 |
9 |
10 | def add_checksum_to_graph(checksum: Checksum, graph: Graph, parent: URIRef):
11 | checksum_node = BNode()
12 | graph.add((checksum_node, RDF.type, SPDX_NAMESPACE.Checksum))
13 | graph.add((checksum_node, SPDX_NAMESPACE.algorithm, algorithm_to_rdf_string(checksum.algorithm)))
14 | graph.add((checksum_node, SPDX_NAMESPACE.checksumValue, Literal(checksum.value)))
15 |
16 | graph.add((parent, SPDX_NAMESPACE.checksum, checksum_node))
17 |
18 |
19 | def algorithm_to_rdf_string(algorithm: ChecksumAlgorithm) -> URIRef:
20 | if "BLAKE2B" in algorithm.name:
21 | algorithm_rdf_string = algorithm.name.replace("_", "").lower()
22 | else:
23 | algorithm_rdf_string = algorithm.name.lower()
24 |
25 | return SPDX_NAMESPACE[f"checksumAlgorithm_{algorithm_rdf_string}"]
26 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/rdf/external_document_ref_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from rdflib import RDF, Graph, URIRef
5 |
6 | from spdx_tools.spdx.model import ExternalDocumentRef
7 | from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE
8 | from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph
9 |
10 |
11 | def add_external_document_ref_to_graph(
12 | external_document_ref: ExternalDocumentRef, graph: Graph, doc_node: URIRef, doc_namespace: str
13 | ):
14 | external_document_ref_resource = URIRef(f"{doc_namespace}#{external_document_ref.document_ref_id}")
15 | graph.add((external_document_ref_resource, RDF.type, SPDX_NAMESPACE.ExternalDocumentRef))
16 | graph.add(
17 | (external_document_ref_resource, SPDX_NAMESPACE.spdxDocument, URIRef(external_document_ref.document_uri))
18 | )
19 | add_checksum_to_graph(external_document_ref.checksum, graph, external_document_ref_resource)
20 |
21 | graph.add((doc_node, SPDX_NAMESPACE.externalDocumentRef, external_document_ref_resource))
22 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/tagvalue/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/writer/tagvalue/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: Apache-2.0
2 | # Copyright (c) 2022 spdx contributors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | from beartype.typing import TextIO
13 |
14 | from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string
15 | from spdx_tools.spdx.model import Annotation
16 | from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value
17 |
18 |
19 | def write_annotation(annotation: Annotation, text_output: TextIO):
20 | write_value("Annotator", annotation.annotator.to_serialized_string(), text_output)
21 | write_value("AnnotationDate", datetime_to_iso_string(annotation.annotation_date), text_output)
22 | write_value("AnnotationType", annotation.annotation_type.name, text_output)
23 | write_value("SPDXREF", annotation.spdx_id, text_output)
24 | write_text_value("AnnotationComment", annotation.annotation_comment, text_output)
25 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: Apache-2.0
2 | # Copyright (c) 2022 spdx contributors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | from beartype.typing import TextIO
13 |
14 | from spdx_tools.spdx.model import ExtractedLicensingInfo
15 | from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value
16 |
17 |
18 | def write_extracted_licensing_info(extracted_licensing_info: ExtractedLicensingInfo, text_output: TextIO):
19 | write_value("LicenseID", extracted_licensing_info.license_id, text_output)
20 | write_text_value("ExtractedText", extracted_licensing_info.extracted_text, text_output)
21 | write_value("LicenseName", extracted_licensing_info.license_name, text_output)
22 |
23 | for cross_reference in sorted(extracted_licensing_info.cross_references):
24 | write_value("LicenseCrossReference", cross_reference, text_output)
25 |
26 | write_text_value("LicenseComment", extracted_licensing_info.comment, text_output)
27 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: Apache-2.0
2 | # Copyright (c) 2022 spdx contributors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | from beartype.typing import TextIO
13 |
14 | from spdx_tools.spdx.model import Relationship
15 | from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value
16 |
17 |
18 | def write_relationship(relationship: Relationship, text_output: TextIO):
19 | write_value(
20 | "Relationship",
21 | " ".join(
22 | [
23 | relationship.spdx_element_id,
24 | relationship.relationship_type.name,
25 | str(relationship.related_spdx_element_id),
26 | ]
27 | ),
28 | text_output,
29 | )
30 | write_text_value("RelationshipComment", relationship.comment, text_output)
31 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/write_anything.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.spdx.formats import FileFormat, file_name_to_format
5 | from spdx_tools.spdx.model import Document
6 | from spdx_tools.spdx.writer.json import json_writer
7 | from spdx_tools.spdx.writer.rdf import rdf_writer
8 | from spdx_tools.spdx.writer.tagvalue import tagvalue_writer
9 | from spdx_tools.spdx.writer.xml import xml_writer
10 | from spdx_tools.spdx.writer.yaml import yaml_writer
11 |
12 |
13 | def write_file(document: Document, file_name: str, validate: bool = True):
14 | output_format = file_name_to_format(file_name)
15 | if output_format == FileFormat.JSON:
16 | json_writer.write_document_to_file(document, file_name, validate)
17 | elif output_format == FileFormat.YAML:
18 | yaml_writer.write_document_to_file(document, file_name, validate)
19 | elif output_format == FileFormat.XML:
20 | xml_writer.write_document_to_file(document, file_name, validate)
21 | elif output_format == FileFormat.TAG_VALUE:
22 | tagvalue_writer.write_document_to_file(document, file_name, validate)
23 | elif output_format == FileFormat.RDF_XML:
24 | rdf_writer.write_document_to_file(document, file_name, validate)
25 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/write_utils.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List
5 |
6 | from spdx_tools.spdx.document_utils import create_document_without_duplicates
7 | from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter
8 | from spdx_tools.spdx.model import Document
9 | from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document
10 | from spdx_tools.spdx.validation.validation_message import ValidationMessage
11 |
12 |
13 | def validate_and_deduplicate(document: Document, validate: bool = True, drop_duplicates: bool = True) -> Document:
14 | if validate:
15 | validation_messages: List[ValidationMessage] = validate_full_spdx_document(document)
16 | if validation_messages:
17 | raise ValueError(f"Document is not valid. The following errors were detected: {validation_messages}")
18 | if drop_duplicates:
19 | document = create_document_without_duplicates(document)
20 | return document
21 |
22 |
23 | def convert(document: Document, converter: DocumentConverter) -> dict:
24 | if converter is None:
25 | converter = DocumentConverter()
26 | return converter.convert(document)
27 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/xml/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/writer/xml/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/xml/xml_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import xmltodict
5 | from beartype.typing import IO
6 |
7 | from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter
8 | from spdx_tools.spdx.model import Document
9 | from spdx_tools.spdx.writer.write_utils import convert, validate_and_deduplicate
10 |
11 |
12 | def write_document_to_stream(
13 | document: Document,
14 | stream: IO[str],
15 | validate: bool = True,
16 | converter: DocumentConverter = None,
17 | drop_duplicates: bool = True,
18 | ):
19 | """
20 | Serializes the provided document to XML and writes it to a file with the provided name. Unless validate is set
21 | to False, validates the document before serialization. Unless a DocumentConverter instance is provided,
22 | a new one is created.
23 | """
24 | document = validate_and_deduplicate(document, validate, drop_duplicates)
25 | document_dict = {"Document": convert(document, converter)}
26 | xmltodict.unparse(document_dict, stream, encoding="utf-8", pretty=True)
27 |
28 |
29 | def write_document_to_file(
30 | document: Document,
31 | file_name: str,
32 | validate: bool = True,
33 | converter: DocumentConverter = None,
34 | drop_duplicates: bool = True,
35 | ):
36 | with open(file_name, "w", encoding="utf-8") as out:
37 | write_document_to_stream(document, out, validate, converter, drop_duplicates)
38 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/yaml/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx/writer/yaml/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx/writer/yaml/yaml_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import yaml
5 | from beartype.typing import IO
6 |
7 | from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter
8 | from spdx_tools.spdx.model import Document
9 | from spdx_tools.spdx.writer.write_utils import convert, validate_and_deduplicate
10 |
11 |
12 | def write_document_to_stream(
13 | document: Document,
14 | stream: IO[str],
15 | validate: bool = True,
16 | converter: DocumentConverter = None,
17 | drop_duplicates: bool = True,
18 | ):
19 | """
20 | Serializes the provided document to yaml and writes it to a file with the provided name. Unless validate is set
21 | to False, validates the document before serialization. Unless a DocumentConverter instance is provided,
22 | a new one is created.
23 | """
24 | document = validate_and_deduplicate(document, validate, drop_duplicates)
25 | document_dict = convert(document, converter)
26 | yaml.safe_dump(document_dict, stream, indent=2)
27 |
28 |
29 | def write_document_to_file(
30 | document: Document,
31 | file_name: str,
32 | validate: bool = True,
33 | converter: DocumentConverter = None,
34 | drop_duplicates: bool = True,
35 | ):
36 | with open(file_name, "w", encoding="utf-8") as out:
37 | write_document_to_stream(document, out, validate, converter, drop_duplicates)
38 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx3/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/bump_from_spdx2/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx3/bump_from_spdx2/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/bump_from_spdx2/bump_utils.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import Optional, Union
5 |
6 | from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion
7 | from spdx_tools.spdx.model.spdx_none import SpdxNone
8 |
9 |
10 | def handle_no_assertion_or_none(field: Union[SpdxNone, SpdxNoAssertion, str], field_name: str) -> Optional[str]:
11 | if isinstance(field, SpdxNone):
12 | print(f"{field_name}: Missing conversion for SpdxNone.")
13 | return None
14 | if isinstance(field, SpdxNoAssertion):
15 | return None
16 | if isinstance(field, str):
17 | return field
18 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/bump_from_spdx2/checksum.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.spdx3.model import Hash, HashAlgorithm
5 | from spdx_tools.spdx.model.checksum import Checksum as Spdx2_Checksum
6 | from spdx_tools.spdx.model.checksum import ChecksumAlgorithm
7 |
8 |
9 | def bump_checksum(spdx2_checksum: Spdx2_Checksum) -> Hash:
10 | algorithm: HashAlgorithm = convert_checksum_algorithm_to_hash_algorithm(spdx2_checksum.algorithm)
11 | value: str = spdx2_checksum.value
12 |
13 | return Hash(algorithm, value)
14 |
15 |
16 | def convert_checksum_algorithm_to_hash_algorithm(checksum_algorithm: ChecksumAlgorithm) -> HashAlgorithm:
17 | if checksum_algorithm.name.startswith("BLAKE"):
18 | return HashAlgorithm[checksum_algorithm.name.replace("_", "")]
19 | if checksum_algorithm == ChecksumAlgorithm.ADLER32:
20 | return HashAlgorithm.OTHER
21 | return HashAlgorithm[checksum_algorithm.name]
22 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List, Tuple
5 |
6 | from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum
7 | from spdx_tools.spdx3.model import ExternalMap, Hash, NamespaceMap
8 | from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef
9 |
10 |
11 | def bump_external_document_ref(external_document_ref: ExternalDocumentRef) -> Tuple[NamespaceMap, ExternalMap]:
12 | verified_using: List[Hash] = [bump_checksum(external_document_ref.checksum)]
13 |
14 | return NamespaceMap(external_document_ref.document_ref_id, external_document_ref.document_uri + "#"), ExternalMap(
15 | external_id=f"{external_document_ref.document_ref_id}:SPDXRef-DOCUMENT",
16 | verified_using=verified_using,
17 | )
18 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/bump_from_spdx2/message.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | import sys
6 |
7 | MISSING_CONVERSION_REASONS = {0: "missing conversion rule", 1: "missing implementation"}
8 |
9 |
10 | def print_missing_conversion(field: str, reason, additional_information: str = ""):
11 | print(f"{field} not converted: {MISSING_CONVERSION_REASONS[reason]} {additional_information}", file=sys.stderr)
12 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/clitools/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx3/clitools/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/__init__.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.spdx3.model.profile_identifier import ProfileIdentifierType
5 | from spdx_tools.spdx3.model.creation_info import CreationInfo
6 | from spdx_tools.spdx3.model.integrity_method import IntegrityMethod
7 | from spdx_tools.spdx3.model.hash import Hash, HashAlgorithm
8 | from spdx_tools.spdx3.model.external_reference import ExternalReference, ExternalReferenceType
9 | from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType
10 | from spdx_tools.spdx3.model.external_map import ExternalMap
11 | from spdx_tools.spdx3.model.namespace_map import NamespaceMap
12 | from spdx_tools.spdx3.model.element import Element
13 | from spdx_tools.spdx3.model.agent import Agent
14 | from spdx_tools.spdx3.model.person import Person
15 | from spdx_tools.spdx3.model.organization import Organization
16 | from spdx_tools.spdx3.model.software_agent import SoftwareAgent
17 | from spdx_tools.spdx3.model.tool import Tool
18 | from spdx_tools.spdx3.model.spdx_collection import ElementCollection
19 | from spdx_tools.spdx3.model.bundle import Bundle
20 | from spdx_tools.spdx3.model.bom import Bom
21 | from spdx_tools.spdx3.model.spdx_document import SpdxDocument
22 | from spdx_tools.spdx3.model.annotation import Annotation, AnnotationType
23 | from spdx_tools.spdx3.model.relationship import Relationship, RelationshipType, RelationshipCompleteness
24 | from spdx_tools.spdx3.model.lifecycle_scoped_relationship import LifecycleScopedRelationship, LifecycleScopeType
25 | from spdx_tools.spdx3.model.artifact import Artifact
26 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/agent.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List, Optional
5 |
6 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
7 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
8 | from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, IntegrityMethod
9 |
10 |
11 | @dataclass_with_properties
12 | class Agent(Element):
13 | def __init__(
14 | self,
15 | spdx_id: str,
16 | creation_info: Optional[CreationInfo] = None,
17 | name: Optional[str] = None,
18 | summary: Optional[str] = None,
19 | description: Optional[str] = None,
20 | comment: Optional[str] = None,
21 | verified_using: List[IntegrityMethod] = None,
22 | external_reference: List[ExternalReference] = None,
23 | external_identifier: List[ExternalIdentifier] = None,
24 | extension: Optional[str] = None,
25 | ):
26 | verified_using = [] if verified_using is None else verified_using
27 | external_reference = [] if external_reference is None else external_reference
28 | external_identifier = [] if external_identifier is None else external_identifier
29 | check_types_and_set_values(self, locals())
30 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/ai/__init__.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.spdx3.model.ai.ai_package import AIPackage
5 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/artifact.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from abc import abstractmethod
5 | from dataclasses import field
6 | from datetime import datetime
7 |
8 | from beartype.typing import List, Optional
9 |
10 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
11 | from spdx_tools.spdx3.model import Element
12 |
13 |
14 | @dataclass_with_properties
15 | class Artifact(Element):
16 | originated_by: List[str] = field(default_factory=list) # SPDXID of the Agent/Tool
17 | supplied_by: List[str] = field(default_factory=list) # SPDXID of the Agent/Tool
18 | built_time: Optional[datetime] = None
19 | release_time: Optional[datetime] = None
20 | valid_until_time: Optional[datetime] = None
21 | standard: List[str] = field(default_factory=list)
22 |
23 | @abstractmethod
24 | def __init__(self):
25 | pass
26 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/build/__init__.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.spdx3.model.build.build import Build
5 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/creation_info.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from dataclasses import field
5 | from datetime import datetime
6 |
7 | from beartype.typing import List, Optional
8 | from semantic_version import Version
9 |
10 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
11 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
12 | from spdx_tools.spdx3.model import ProfileIdentifierType
13 |
14 |
15 | @dataclass_with_properties
16 | class CreationInfo:
17 | spec_version: Version
18 | created: datetime
19 | created_by: List[str] # SPDXID of Agents
20 | profile: List[ProfileIdentifierType]
21 | data_license: Optional[str] = "CC0-1.0"
22 | created_using: List[str] = field(default_factory=list) # SPDXID of Tools
23 | comment: Optional[str] = None
24 |
25 | def __init__(
26 | self,
27 | spec_version: Version,
28 | created: datetime,
29 | created_by: List[str],
30 | profile: List[ProfileIdentifierType],
31 | data_license: Optional[str] = "CC0-1.0",
32 | created_using: List[str] = None,
33 | comment: Optional[str] = None,
34 | ):
35 | created_using = [] if created_using is None else created_using
36 | check_types_and_set_values(self, locals())
37 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/dataset/__init__.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.spdx3.model.dataset.dataset import Dataset, DatasetAvailabilityType, ConfidentialityLevelType
5 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/element.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from abc import ABC, abstractmethod
5 | from dataclasses import field
6 |
7 | from beartype.typing import List, Optional
8 |
9 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
10 | from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod
11 |
12 |
13 | @dataclass_with_properties
14 | class Element(ABC):
15 | spdx_id: str # IRI
16 | creation_info: Optional[CreationInfo] = None
17 | name: Optional[str] = None
18 | summary: Optional[str] = None
19 | description: Optional[str] = None
20 | comment: Optional[str] = None
21 | verified_using: List[IntegrityMethod] = field(default_factory=list)
22 | external_reference: List[ExternalReference] = field(default_factory=list)
23 | external_identifier: List[ExternalIdentifier] = field(default_factory=list)
24 | extension: Optional[str] = None # placeholder for extension
25 |
26 | @abstractmethod
27 | def __init__(self):
28 | pass
29 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/external_identifier.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from dataclasses import field
5 | from enum import Enum, auto
6 |
7 | from beartype.typing import List, Optional
8 |
9 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
10 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
11 |
12 |
13 | class ExternalIdentifierType(Enum):
14 | CPE22 = auto()
15 | CPE23 = auto()
16 | CVE = auto()
17 | EMAIL = auto()
18 | GITOID = auto()
19 | PURL = auto()
20 | SECURITY_OTHER = auto()
21 | SWHID = auto()
22 | SWID = auto()
23 | URL_SCHEME = auto()
24 | OTHER = auto()
25 |
26 |
27 | @dataclass_with_properties
28 | class ExternalIdentifier:
29 | external_identifier_type: ExternalIdentifierType
30 | identifier: str
31 | comment: Optional[str] = None
32 | identifier_locator: List[str] = field(default_factory=list)
33 | issuing_authority: Optional[str] = None
34 |
35 | def __init__(
36 | self,
37 | external_identifier_type: ExternalIdentifierType,
38 | identifier: str,
39 | comment: Optional[str] = None,
40 | identifier_locator: List[str] = None,
41 | issuing_authority: Optional[str] = None,
42 | ):
43 | identifier_locator = [] if identifier_locator is None else identifier_locator
44 | check_types_and_set_values(self, locals())
45 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/external_map.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from dataclasses import field
5 |
6 | from beartype.typing import List, Optional
7 |
8 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
9 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
10 | from spdx_tools.spdx3.model import IntegrityMethod
11 |
12 |
13 | @dataclass_with_properties
14 | class ExternalMap:
15 | external_id: str # anyURI
16 | verified_using: List[IntegrityMethod] = field(default_factory=list)
17 | location_hint: Optional[str] = None # anyURI
18 | defining_document: Optional[str] = None
19 |
20 | def __init__(
21 | self,
22 | external_id: str,
23 | verified_using: List[IntegrityMethod] = None,
24 | location_hint: Optional[str] = None,
25 | defining_document: Optional[str] = None,
26 | ):
27 | verified_using = [] if verified_using is None else verified_using
28 | check_types_and_set_values(self, locals())
29 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/hash.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import Enum, auto
5 |
6 | from beartype.typing import Optional
7 |
8 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
9 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
10 | from spdx_tools.spdx3.model import IntegrityMethod
11 |
12 |
13 | class HashAlgorithm(Enum):
14 | BLAKE2B256 = auto()
15 | BLAKE2B384 = auto()
16 | BLAKE2B512 = auto()
17 | BLAKE3 = auto()
18 | CRYSTALS_KYBER = auto()
19 | CRYSTALS_DILITHIUM = auto()
20 | FALCON = auto()
21 | MD2 = auto()
22 | MD4 = auto()
23 | MD5 = auto()
24 | MD6 = auto()
25 | OTHER = auto()
26 | SHA1 = auto()
27 | SHA224 = auto()
28 | SHA256 = auto()
29 | SHA3_224 = auto()
30 | SHA3_256 = auto()
31 | SHA3_384 = auto()
32 | SHA3_512 = auto()
33 | SHA384 = auto()
34 | SHA512 = auto()
35 | SPDXPVCSHA1 = auto()
36 | SPDXPVCSHA256 = auto()
37 | SPHINCS_PLUS = auto()
38 |
39 |
40 | @dataclass_with_properties
41 | class Hash(IntegrityMethod):
42 | algorithm: HashAlgorithm = None
43 | hash_value: str = None
44 |
45 | def __init__(self, algorithm: HashAlgorithm, hash_value: str, comment: Optional[str] = None):
46 | check_types_and_set_values(self, locals())
47 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/integrity_method.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from abc import ABC, abstractmethod
5 |
6 | from beartype.typing import Optional
7 |
8 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
9 |
10 |
11 | @dataclass_with_properties
12 | class IntegrityMethod(ABC):
13 | comment: Optional[str] = None
14 |
15 | @abstractmethod
16 | def __init__(self):
17 | pass
18 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/__init__.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from .any_license_info import AnyLicenseInfo
5 | from .conjunctive_license_set import ConjunctiveLicenseSet
6 | from .custom_license import CustomLicense
7 | from .custom_license_addition import CustomLicenseAddition
8 | from .disjunctive_license_set import DisjunctiveLicenseSet
9 | from .license import License
10 | from .license_addition import LicenseAddition
11 | from .license_field import LicenseField
12 | from .listed_license import ListedLicense
13 | from .listed_license_exception import ListedLicenseException
14 | from .no_assertion_license import NoAssertionLicense
15 | from .none_license import NoneLicense
16 | from .or_later_operator import OrLaterOperator
17 | from .with_addition_operator import WithAdditionOperator
18 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/any_license_info.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from abc import abstractmethod
5 |
6 | from spdx_tools.spdx3.model.licensing.license_field import LicenseField
7 |
8 |
9 | class AnyLicenseInfo(LicenseField):
10 | @abstractmethod
11 | def __init__(self):
12 | pass
13 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/conjunctive_license_set.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List
5 |
6 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
7 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
8 | from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo
9 |
10 |
11 | @dataclass_with_properties
12 | class ConjunctiveLicenseSet(AnyLicenseInfo):
13 | member: List[AnyLicenseInfo]
14 |
15 | def __init__(self, member: List[AnyLicenseInfo]):
16 | check_types_and_set_values(self, locals())
17 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/custom_license.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List, Optional
5 |
6 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
7 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
8 | from spdx_tools.spdx3.model.licensing.license import License
9 |
10 |
11 | @dataclass_with_properties
12 | class CustomLicense(License):
13 | def __init__(
14 | self,
15 | license_id: str,
16 | license_name: str,
17 | license_text: str,
18 | license_comment: Optional[str] = None,
19 | see_also: List[str] = None,
20 | is_osi_approved: Optional[bool] = None,
21 | is_fsf_libre: Optional[bool] = None,
22 | standard_license_header: Optional[str] = None,
23 | standard_license_template: Optional[str] = None,
24 | is_deprecated_license_id: Optional[bool] = None,
25 | obsoleted_by: Optional[str] = None,
26 | ):
27 | see_also = [] if see_also is None else see_also
28 | check_types_and_set_values(self, locals())
29 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/custom_license_addition.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List, Optional
5 |
6 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
7 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
8 | from spdx_tools.spdx3.model.licensing.license_addition import LicenseAddition
9 |
10 |
11 | @dataclass_with_properties
12 | class CustomLicenseAddition(LicenseAddition):
13 | def __init__(
14 | self,
15 | addition_id: str,
16 | addition_name: str,
17 | addition_text: str,
18 | addition_comment: Optional[str] = None,
19 | see_also: List[str] = None,
20 | standard_addition_template: Optional[str] = None,
21 | is_deprecated_addition_id: Optional[bool] = None,
22 | obsoleted_by: Optional[str] = None,
23 | ):
24 | see_also = [] if see_also is None else see_also
25 | check_types_and_set_values(self, locals())
26 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/disjunctive_license_set.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List
5 |
6 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
7 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
8 | from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo
9 |
10 |
11 | @dataclass_with_properties
12 | class DisjunctiveLicenseSet(AnyLicenseInfo):
13 | member: List[AnyLicenseInfo]
14 |
15 | def __init__(self, member: List[AnyLicenseInfo]):
16 | check_types_and_set_values(self, locals())
17 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/license.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from abc import abstractmethod
5 | from dataclasses import field
6 |
7 | from beartype.typing import List, Optional
8 |
9 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
10 | from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo
11 |
12 |
13 | @dataclass_with_properties
14 | class License(AnyLicenseInfo):
15 | license_id: str
16 | license_name: str
17 | license_text: str
18 | license_comment: Optional[str] = None
19 | see_also: List[str] = field(default_factory=list)
20 | is_osi_approved: Optional[bool] = None
21 | is_fsf_libre: Optional[bool] = None
22 | standard_license_header: Optional[str] = None
23 | standard_license_template: Optional[str] = None
24 | is_deprecated_license_id: Optional[bool] = None
25 | obsoleted_by: Optional[str] = None
26 |
27 | @abstractmethod
28 | def __init__(self):
29 | pass
30 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/license_addition.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from abc import ABC, abstractmethod
5 | from dataclasses import field
6 |
7 | from beartype.typing import List, Optional
8 |
9 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
10 |
11 |
12 | @dataclass_with_properties
13 | class LicenseAddition(ABC):
14 | addition_id: str
15 | addition_name: str
16 | addition_text: str
17 | addition_comment: Optional[str] = None
18 | see_also: List[str] = field(default_factory=list)
19 | standard_addition_template: Optional[str] = None
20 | is_deprecated_addition_id: Optional[bool] = None
21 | obsoleted_by: Optional[str] = None
22 |
23 | @abstractmethod
24 | def __init__(self):
25 | pass
26 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/license_field.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from abc import ABC, abstractmethod
5 |
6 |
7 | class LicenseField(ABC):
8 | @abstractmethod
9 | def __init__(self):
10 | pass
11 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/listed_license.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List, Optional
5 |
6 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
7 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
8 | from spdx_tools.spdx3.model.licensing.license import License
9 |
10 |
11 | @dataclass_with_properties
12 | class ListedLicense(License):
13 | list_version_added: Optional[str] = None
14 | deprecated_version: Optional[str] = None
15 |
16 | def __init__(
17 | self,
18 | license_id: str,
19 | license_name: str,
20 | license_text: str,
21 | license_comment: Optional[str] = None,
22 | see_also: List[str] = None,
23 | is_osi_approved: Optional[bool] = None,
24 | is_fsf_libre: Optional[bool] = None,
25 | standard_license_header: Optional[str] = None,
26 | standard_license_template: Optional[str] = None,
27 | is_deprecated_license_id: Optional[bool] = None,
28 | obsoleted_by: Optional[str] = None,
29 | list_version_added: Optional[str] = None,
30 | deprecated_version: Optional[str] = None,
31 | ):
32 | see_also = [] if see_also is None else see_also
33 | check_types_and_set_values(self, locals())
34 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/listed_license_exception.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List, Optional
5 |
6 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
7 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
8 | from spdx_tools.spdx3.model.licensing.license_addition import LicenseAddition
9 |
10 |
11 | @dataclass_with_properties
12 | class ListedLicenseException(LicenseAddition):
13 | list_version_added: Optional[str] = None
14 | deprecated_version: Optional[str] = None
15 |
16 | def __init__(
17 | self,
18 | addition_id: str,
19 | addition_name: str,
20 | addition_text: str,
21 | addition_comment: Optional[str] = None,
22 | see_also: List[str] = None,
23 | standard_addition_template: Optional[str] = None,
24 | is_deprecated_addition_id: Optional[bool] = None,
25 | obsoleted_by: Optional[str] = None,
26 | list_version_added: Optional[str] = None,
27 | deprecated_version: Optional[str] = None,
28 | ):
29 | see_also = [] if see_also is None else see_also
30 | check_types_and_set_values(self, locals())
31 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/no_assertion_license.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.spdx3.model.licensing.license_field import LicenseField
5 |
6 |
7 | class NoAssertionLicense(LicenseField):
8 | def __init__(self):
9 | pass
10 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/none_license.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.spdx3.model.licensing.license_field import LicenseField
5 |
6 |
7 | class NoneLicense(LicenseField):
8 | def __init__(self):
9 | pass
10 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/or_later_operator.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
5 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
6 | from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo
7 | from spdx_tools.spdx3.model.licensing.license import License
8 |
9 |
10 | @dataclass_with_properties
11 | class OrLaterOperator(AnyLicenseInfo):
12 | subject_license: License
13 |
14 | def __init__(self, subject_license: License):
15 | check_types_and_set_values(self, locals())
16 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/licensing/with_addition_operator.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
5 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
6 | from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo
7 | from spdx_tools.spdx3.model.licensing.license import License
8 | from spdx_tools.spdx3.model.licensing.license_addition import LicenseAddition
9 |
10 |
11 | @dataclass_with_properties
12 | class WithAdditionOperator(AnyLicenseInfo):
13 | subject_license: License
14 | subject_addition: LicenseAddition
15 |
16 | def __init__(self, subject_license: License, subject_addition: LicenseAddition):
17 | check_types_and_set_values(self, locals())
18 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/namespace_map.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
5 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
6 |
7 |
8 | @dataclass_with_properties
9 | class NamespaceMap:
10 | prefix: str
11 | namespace: str # anyURI
12 |
13 | def __init__(self, prefix: str, namespace: str):
14 | check_types_and_set_values(self, locals())
15 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/organization.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List, Optional
5 |
6 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
7 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
8 | from spdx_tools.spdx3.model import Agent, CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod
9 |
10 |
11 | @dataclass_with_properties
12 | class Organization(Agent):
13 | def __init__(
14 | self,
15 | spdx_id: str,
16 | creation_info: Optional[CreationInfo] = None,
17 | name: Optional[str] = None,
18 | summary: Optional[str] = None,
19 | description: Optional[str] = None,
20 | comment: Optional[str] = None,
21 | verified_using: List[IntegrityMethod] = None,
22 | external_reference: List[ExternalReference] = None,
23 | external_identifier: List[ExternalIdentifier] = None,
24 | extension: Optional[str] = None,
25 | ):
26 | verified_using = [] if verified_using is None else verified_using
27 | external_reference = [] if external_reference is None else external_reference
28 | external_identifier = [] if external_identifier is None else external_identifier
29 | check_types_and_set_values(self, locals())
30 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/person.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List, Optional
5 |
6 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
7 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
8 | from spdx_tools.spdx3.model import Agent, CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod
9 |
10 |
11 | @dataclass_with_properties
12 | class Person(Agent):
13 | def __init__(
14 | self,
15 | spdx_id: str,
16 | creation_info: Optional[CreationInfo] = None,
17 | name: Optional[str] = None,
18 | summary: Optional[str] = None,
19 | description: Optional[str] = None,
20 | comment: Optional[str] = None,
21 | verified_using: List[IntegrityMethod] = None,
22 | external_reference: List[ExternalReference] = None,
23 | external_identifier: List[ExternalIdentifier] = None,
24 | extension: Optional[str] = None,
25 | ):
26 | verified_using = [] if verified_using is None else verified_using
27 | external_reference = [] if external_reference is None else external_reference
28 | external_identifier = [] if external_identifier is None else external_identifier
29 | check_types_and_set_values(self, locals())
30 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/positive_integer_range.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
5 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
6 |
7 |
8 | @dataclass_with_properties
9 | class PositiveIntegerRange:
10 | begin: int
11 | end: int
12 |
13 | def __init__(
14 | self,
15 | begin: int,
16 | end: int,
17 | ):
18 | check_types_and_set_values(self, locals())
19 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/profile_identifier.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import Enum, auto
5 |
6 |
7 | class ProfileIdentifierType(Enum):
8 | CORE = auto()
9 | SOFTWARE = auto()
10 | LICENSING = auto()
11 | SECURITY = auto()
12 | BUILD = auto()
13 | AI = auto()
14 | DATASET = auto()
15 | USAGE = auto()
16 | EXTENSION = auto()
17 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/security/__init__.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from .cvss_v2_vuln_assessment_relationship import CvssV2VulnAssessmentRelationship
5 | from .cvss_v3_vuln_assessment_relationship import CvssV3VulnAssessmentRelationship
6 | from .epss_vuln_assessment_relationship import EpssVulnAssessmentRelationship
7 | from .exploit_catalog_vuln_assessment_relationship import ExploitCatalogVulnAssessmentRelationship, ExploitCatalogType
8 | from .ssvc_vuln_assessment_relationship import SsvcVulnAssessmentRelationship, SsvcDecisionType
9 | from .vex_affected_vuln_assessment_relationship import VexAffectedVulnAssessmentRelationship
10 | from .vex_fixed_vuln_assessment_relationship import VexFixedVulnAssessmentRelationship
11 | from .vex_not_affected_vuln_assessment_relationship import (
12 | VexNotAffectedVulnAssessmentRelationship,
13 | VexJustificationType,
14 | )
15 | from .vex_under_investigation_vuln_assessment_relationship import VexUnderInvestigationVulnAssessmentRelationship
16 | from .vex_vuln_assessment_relationship import VexVulnAssessmentRelationship
17 | from .vuln_assessment_relationship import VulnAssessmentRelationship
18 | from .vulnerability import Vulnerability
19 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from abc import abstractmethod
5 |
6 | from beartype.typing import Optional
7 |
8 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
9 | from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship
10 |
11 |
12 | @dataclass_with_properties
13 | class VexVulnAssessmentRelationship(VulnAssessmentRelationship):
14 | vex_version: Optional[str] = None
15 | status_notes: Optional[str] = None
16 |
17 | @abstractmethod
18 | def __init__(self):
19 | pass
20 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from abc import abstractmethod
5 | from datetime import datetime
6 |
7 | from beartype.typing import Optional
8 |
9 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
10 | from spdx_tools.spdx3.model import Relationship
11 |
12 |
13 | @dataclass_with_properties
14 | class VulnAssessmentRelationship(Relationship):
15 | assessed_element: Optional[str] = None # id of the element
16 | published_time: Optional[datetime] = None
17 | supplied_by: Optional[str] = None
18 | modified_time: Optional[datetime] = None
19 | withdrawn_time: Optional[datetime] = None
20 |
21 | @abstractmethod
22 | def __init__(self):
23 | pass
24 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/software/__init__.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose
5 | from spdx_tools.spdx3.model.software.file import File
6 | from spdx_tools.spdx3.model.software.package import Package
7 | from spdx_tools.spdx3.model.software.snippet import Snippet
8 | from spdx_tools.spdx3.model.software.sbom import Sbom, SBOMType
9 | from spdx_tools.spdx3.model.software.software_dependency_relationship import (
10 | SoftwareDependencyRelationship,
11 | SoftwareDependencyLinkType,
12 | DependencyConditionalityType,
13 | )
14 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/software/software_artifact.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from abc import abstractmethod
5 | from dataclasses import field
6 |
7 | from beartype.typing import List, Optional
8 |
9 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
10 | from spdx_tools.spdx3.model import Artifact
11 | from spdx_tools.spdx3.model.licensing import LicenseField
12 | from spdx_tools.spdx3.model.software import SoftwarePurpose
13 |
14 |
15 | @dataclass_with_properties
16 | class SoftwareArtifact(Artifact):
17 | content_identifier: Optional[str] = None
18 | primary_purpose: Optional[SoftwarePurpose] = None
19 | additional_purpose: List[SoftwarePurpose] = field(default_factory=list)
20 | concluded_license: Optional[LicenseField] = None
21 | declared_license: Optional[LicenseField] = None
22 | copyright_text: Optional[str] = None
23 | attribution_text: Optional[str] = None
24 |
25 | @abstractmethod
26 | def __init__(self):
27 | pass
28 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/software/software_purpose.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import Enum, auto
5 |
6 |
7 | class SoftwarePurpose(Enum):
8 | APPLICATION = auto()
9 | ARCHIVE = auto()
10 | BOM = auto()
11 | CONFIGURATION = auto()
12 | CONTAINER = auto()
13 | DATA = auto()
14 | DEVICE = auto()
15 | DOCUMENTATION = auto()
16 | EXECUTABLE = auto()
17 | FILE = auto()
18 | FIRMWARE = auto()
19 | FRAMEWORK = auto()
20 | INSTALL = auto()
21 | LIBRARY = auto()
22 | MODEL = auto()
23 | MODULE = auto()
24 | OPERATING_SYSTEM = auto()
25 | OTHER = auto()
26 | PATCH = auto()
27 | REQUIREMENT = auto()
28 | SOURCE = auto()
29 | TEST = auto()
30 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/software_agent.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List, Optional
5 |
6 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
7 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
8 | from spdx_tools.spdx3.model import Agent, CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod
9 |
10 |
11 | @dataclass_with_properties
12 | class SoftwareAgent(Agent):
13 | def __init__(
14 | self,
15 | spdx_id: str,
16 | creation_info: Optional[CreationInfo] = None,
17 | name: Optional[str] = None,
18 | summary: Optional[str] = None,
19 | description: Optional[str] = None,
20 | comment: Optional[str] = None,
21 | verified_using: List[IntegrityMethod] = None,
22 | external_reference: List[ExternalReference] = None,
23 | external_identifier: List[ExternalIdentifier] = None,
24 | extension: Optional[str] = None,
25 | ):
26 | verified_using = [] if verified_using is None else verified_using
27 | external_reference = [] if external_reference is None else external_reference
28 | external_identifier = [] if external_identifier is None else external_identifier
29 | check_types_and_set_values(self, locals())
30 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/spdx_collection.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from abc import abstractmethod
5 | from dataclasses import field
6 |
7 | from beartype.typing import List
8 |
9 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
10 | from spdx_tools.spdx3.model import Element, ExternalMap, NamespaceMap
11 |
12 |
13 | @dataclass_with_properties
14 | class ElementCollection(Element):
15 | # due to the inheritance we need to make all fields non-default in the __annotation__,
16 | # the __init__ method still raises an error if required fields are not set
17 | element: List[str] = field(default_factory=list)
18 | root_element: List[str] = field(default_factory=list)
19 | namespaces: List[NamespaceMap] = field(default_factory=list)
20 | imports: List[ExternalMap] = field(default_factory=list)
21 |
22 | @abstractmethod
23 | def __init__(self):
24 | pass
25 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/model/tool.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import List, Optional
5 |
6 | from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties
7 | from spdx_tools.common.typing.type_checks import check_types_and_set_values
8 | from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, IntegrityMethod
9 |
10 |
11 | @dataclass_with_properties
12 | class Tool(Element):
13 | def __init__(
14 | self,
15 | spdx_id: str,
16 | creation_info: Optional[CreationInfo] = None,
17 | name: Optional[str] = None,
18 | summary: Optional[str] = None,
19 | description: Optional[str] = None,
20 | comment: Optional[str] = None,
21 | verified_using: List[IntegrityMethod] = None,
22 | external_reference: List[ExternalReference] = None,
23 | external_identifier: List[ExternalIdentifier] = None,
24 | extension: Optional[str] = None,
25 | ):
26 | verified_using = [] if verified_using is None else verified_using
27 | external_reference = [] if external_reference is None else external_reference
28 | external_identifier = [] if external_identifier is None else external_identifier
29 | check_types_and_set_values(self, locals())
30 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/payload.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import Dict
5 |
6 | from spdx_tools.spdx3.model import Element
7 |
8 |
9 | class Payload:
10 | _spdx_id_map: Dict[str, Element]
11 |
12 | def __init__(self, spdx_id_map: Dict[str, Element] = None):
13 | self._spdx_id_map = spdx_id_map if spdx_id_map else {}
14 |
15 | def add_element(self, element: Element):
16 | self._spdx_id_map[element.spdx_id] = element
17 |
18 | def get_element(self, spdx_id: str) -> Element:
19 | return self._spdx_id_map[spdx_id]
20 |
21 | def get_full_map(self) -> Dict[str, Element]:
22 | return self._spdx_id_map
23 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/validation/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx3/validation/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/validation/json_ld/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx3/validation/json_ld/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import Optional
5 | from pyshacl import validate
6 | from rdflib import Graph
7 |
8 |
9 | def validate_against_shacl_from_file(
10 | data_file: str, shacl_file: str, data_format: Optional[str] = "json-ld", shacl_format: Optional[str] = "ttl"
11 | ):
12 | data_graph = Graph()
13 | with open(data_file) as file:
14 | data_graph.parse(file, format=data_format)
15 |
16 | shacl_graph = Graph()
17 | with open(shacl_file) as file:
18 | shacl_graph.parse(file, format=shacl_format)
19 |
20 | return validate(data_graph=data_graph, shacl_graph=shacl_graph, ont_graph=shacl_graph)
21 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx3/writer/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/__init__.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | """This is a temporary package to write the implemented model of spdx_tools.spdx3.0 to console. As soon as
5 | serialization formats are properly defined this package can be deleted."""
6 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/agent_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import Agent, Organization, Person, SoftwareAgent
7 | from spdx_tools.spdx3.writer.console.element_writer import write_element_properties
8 |
9 |
10 | def write_agent(agent: Agent, text_output: TextIO, heading: bool = True):
11 | if heading:
12 | if isinstance(agent, Person):
13 | text_output.write("## Person\n")
14 | if isinstance(agent, Organization):
15 | text_output.write("## Organization\n")
16 | if isinstance(agent, SoftwareAgent):
17 | text_output.write("## SoftwareAgent\n")
18 | write_element_properties(agent, text_output)
19 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/ai/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx3/writer/console/ai/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model.ai import AIPackage
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 | from spdx_tools.spdx3.writer.console.software.package_writer import write_package
9 |
10 |
11 | def write_ai_package(ai_package: AIPackage, text_output: TextIO):
12 | text_output.write("## AI Package\n")
13 | write_package(ai_package, text_output, False)
14 |
15 | for property_name in AIPackage.__annotations__.keys():
16 | write_value(property_name, getattr(ai_package, property_name), text_output)
17 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/annotation_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import Annotation
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 | from spdx_tools.spdx3.writer.console.element_writer import write_element_properties
9 |
10 |
11 | def write_annotation(annotation: Annotation, text_output: TextIO):
12 | text_output.write("## Annotation\n")
13 | write_element_properties(annotation, text_output)
14 |
15 | for property_name in Annotation.__annotations__.keys():
16 | write_value(property_name, getattr(annotation, property_name), text_output)
17 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/artifact_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import Artifact
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 | from spdx_tools.spdx3.writer.console.element_writer import write_element_properties
9 |
10 |
11 | def write_artifact_properties(artifact: Artifact, text_output: TextIO):
12 | write_element_properties(artifact, text_output)
13 |
14 | for property_name in Artifact.__annotations__.keys():
15 | write_value(property_name, getattr(artifact, property_name), text_output)
16 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/bom_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import Bom
7 | from spdx_tools.spdx3.writer.console.bundle_writer import write_bundle
8 |
9 |
10 | def write_bom(bom: Bom, text_output: TextIO, heading: bool = True):
11 | if heading:
12 | text_output.write("## Bom\n")
13 | write_bundle(bom, text_output, False)
14 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/build/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx3/writer/console/build/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/build/build_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model.build import Build
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 | from spdx_tools.spdx3.writer.console.element_writer import write_element_properties
9 | from spdx_tools.spdx3.writer.console.hash_writer import write_hash
10 | from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading
11 |
12 |
13 | def write_build(build: Build, text_output: TextIO):
14 | text_output.write("## Build\n")
15 | write_element_properties(build, text_output)
16 |
17 | for property_name in Build.__annotations__.keys():
18 | if property_name == "config_source_digest":
19 | write_optional_heading(build.config_source_digest, "config_source_digest", text_output)
20 | for digest_hash in build.config_source_digest:
21 | write_hash(digest_hash, text_output, heading=False)
22 | continue
23 |
24 | write_value(property_name, getattr(build, property_name), text_output)
25 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/bundle_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import Bundle
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 | from spdx_tools.spdx3.writer.console.spdx_collection_writer import write_collection
9 |
10 |
11 | def write_bundle(bundle: Bundle, text_output: TextIO, heading: bool = True):
12 | if heading:
13 | text_output.write("## Bundle\n")
14 | write_collection(bundle, text_output)
15 | write_value("context", bundle.context, text_output)
16 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/console.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from enum import Enum
5 |
6 | from beartype.typing import Optional, TextIO, Union
7 |
8 |
9 | def write_value(tag: str, value: Optional[Union[bool, str, dict, list, Enum]], out: TextIO, indent: bool = False):
10 | """This function is duplicated from spdx_tools.spdx.writer.tagvalue.tag_value_writer_helper_functions
11 | and slightly adapted to make indentation of output possible."""
12 | if not value:
13 | return
14 | if isinstance(value, dict):
15 | value = ", ".join([f"{tag}: ({key}: {val})" for key, val in value.items()])
16 | if isinstance(value, list):
17 | value = ", ".join([entry for entry in value])
18 | if isinstance(value, Enum):
19 | value = value.name
20 | write_and_possibly_indent(f"{tag}: {value}", indent, out)
21 |
22 |
23 | def write_and_possibly_indent(text: str, indent: bool, out: TextIO):
24 | if indent:
25 | out.write(f" {text}\n")
26 | else:
27 | out.write(f"{text}\n")
28 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/creation_info_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import CreationInfo
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 | from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string
9 |
10 |
11 | def write_creation_info(creation_info: CreationInfo, text_output: TextIO, indent: bool = True):
12 | text_output.write("# Creation Information\n")
13 | write_value("specVersion", str(creation_info.spec_version), text_output, indent)
14 | write_value("created", datetime_to_iso_string(creation_info.created), text_output, indent)
15 | for created_by in creation_info.created_by:
16 | write_value("created by", created_by, text_output, indent)
17 | for created_using in creation_info.created_using:
18 | write_value("created using", created_using, text_output, indent)
19 | write_value("profile", [profile.name for profile in creation_info.profile], text_output, indent)
20 | write_value("data license", creation_info.data_license, text_output, indent)
21 | write_value("comment", creation_info.comment, text_output, indent)
22 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/dataset/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx3/writer/console/dataset/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model.dataset import Dataset
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 | from spdx_tools.spdx3.writer.console.software.package_writer import write_package
9 |
10 |
11 | def write_dataset(dataset: Dataset, text_output: TextIO):
12 | text_output.write("## Dataset\n")
13 | write_package(dataset, text_output, False)
14 |
15 | for property_name in Dataset.__annotations__.keys():
16 | write_value(property_name, getattr(dataset, property_name), text_output)
17 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import ExternalIdentifier
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 |
9 |
10 | def write_external_identifier(external_identifier: ExternalIdentifier, text_output: TextIO):
11 | for property_name in ExternalIdentifier.__annotations__.keys():
12 | write_value(property_name, getattr(external_identifier, property_name), text_output)
13 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/external_map_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import ExternalMap
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 | from spdx_tools.spdx3.writer.console.hash_writer import write_hash
9 | from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading
10 |
11 |
12 | def write_external_map(external_map: ExternalMap, text_output: TextIO):
13 | write_value("external_id", external_map.external_id, text_output)
14 | write_optional_heading(external_map.verified_using, "verified using\n", text_output)
15 | for integrity_method in external_map.verified_using:
16 | # for now Hash is the only child class of the abstract class IntegrityMethod,
17 | # as soon as there are more inherited classes we need to implement a logic
18 | # that determines the correct write function for the "integrity_method" object
19 | write_hash(integrity_method, text_output, heading=False)
20 | write_value("location_hint", external_map.location_hint, text_output)
21 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/external_reference_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import ExternalReference
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 |
9 |
10 | def write_external_reference(external_reference: ExternalReference, text_output: TextIO):
11 | for property_name in ExternalReference.__annotations__.keys():
12 | write_value(property_name, getattr(external_reference, property_name), text_output)
13 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/hash_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import Hash
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 | from spdx_tools.spdx3.writer.console.integrity_method_writer import write_integrity_method
9 |
10 |
11 | def write_hash(hash_object: Hash, text_output: TextIO, heading: bool, indent: bool = True):
12 | if heading:
13 | text_output.write("## Hash\n")
14 | write_value("algorithm", hash_object.algorithm, text_output, indent)
15 | write_value("hash_value", hash_object.hash_value, text_output, indent)
16 | write_integrity_method(hash_object, text_output, indent)
17 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import IntegrityMethod
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 |
9 |
10 | def write_integrity_method(integrity_method: IntegrityMethod, text_output: TextIO, indent: bool = True):
11 | write_value("comment", integrity_method.comment, text_output, indent)
12 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/lifecycle_scoped_relationship_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | from beartype.typing import TextIO
6 |
7 | from spdx_tools.spdx3.model import LifecycleScopedRelationship
8 | from spdx_tools.spdx3.writer.console.console import write_value
9 | from spdx_tools.spdx3.writer.console.relationship_writer import write_relationship
10 |
11 |
12 | def write_lifecycle_scoped_relationship(
13 | relationship: LifecycleScopedRelationship, text_output: TextIO, heading: bool = True
14 | ):
15 | if heading:
16 | text_output.write("## LifecycleScopedRelationship\n")
17 | write_relationship(relationship, text_output, heading=False)
18 |
19 | for property_name in LifecycleScopedRelationship.__annotations__.keys():
20 | write_value(property_name, getattr(relationship, property_name), text_output)
21 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import NamespaceMap
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 |
9 |
10 | def write_namespace_map(namespace_map: NamespaceMap, text_output: TextIO):
11 | for property_name in NamespaceMap.__annotations__.keys():
12 | write_value(property_name, getattr(namespace_map, property_name), text_output)
13 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/relationship_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import Relationship
7 | from spdx_tools.spdx3.writer.console.console import write_value
8 | from spdx_tools.spdx3.writer.console.element_writer import write_element_properties
9 |
10 |
11 | def write_relationship(relationship: Relationship, text_output: TextIO, heading: bool = True):
12 | if heading:
13 | text_output.write("## Relationship\n")
14 | write_element_properties(relationship, text_output)
15 | for property_name in relationship.__annotations__.keys():
16 | write_value(property_name, getattr(relationship, property_name), text_output)
17 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/software/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx3/writer/console/software/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/software/file_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model.software import File
7 | from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties
8 | from spdx_tools.spdx3.writer.console.console import write_value
9 |
10 |
11 | def write_file(file: File, text_output: TextIO):
12 | text_output.write("## File\n")
13 | write_artifact_properties(file, text_output)
14 |
15 | for property_name in File.__annotations__.keys():
16 | if property_name == "file_purpose":
17 | write_value(
18 | property_name, ", ".join([purpose.name for purpose in getattr(file, property_name)]), text_output
19 | )
20 | continue
21 | write_value(property_name, getattr(file, property_name), text_output)
22 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/software/package_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model.software import Package
7 | from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties
8 | from spdx_tools.spdx3.writer.console.console import write_value
9 |
10 |
11 | def write_package(package: Package, text_output: TextIO, heading: bool = True):
12 | if heading:
13 | text_output.write("## Package\n")
14 | write_artifact_properties(package, text_output)
15 |
16 | for property_name in Package.__annotations__.keys():
17 | if property_name == "package_purpose":
18 | write_value(
19 | property_name, ", ".join([purpose.name for purpose in getattr(package, property_name)]), text_output
20 | )
21 | continue
22 | write_value(property_name, getattr(package, property_name), text_output)
23 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model.software import Sbom
7 | from spdx_tools.spdx3.writer.console.bom_writer import write_bom
8 |
9 |
10 | def write_sbom(sbom: Sbom, text_output: TextIO):
11 | text_output.write("## Sbom\n")
12 | write_bom(sbom, text_output, False)
13 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model.software import Snippet
7 | from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties
8 | from spdx_tools.spdx3.writer.console.console import write_value
9 |
10 |
11 | def write_snippet(snippet: Snippet, text_output: TextIO):
12 | text_output.write("## Snippet\n")
13 | write_artifact_properties(snippet, text_output)
14 |
15 | for property_name in Snippet.__annotations__.keys():
16 | if property_name == "snippet_purpose":
17 | write_value(
18 | property_name, ", ".join([purpose.name for purpose in getattr(snippet, property_name)]), text_output
19 | )
20 | continue
21 | write_value(property_name, getattr(snippet, property_name), text_output)
22 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/software/software_dependency_relationship_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | from beartype.typing import TextIO
6 |
7 | from spdx_tools.spdx3.model.software import SoftwareDependencyRelationship
8 | from spdx_tools.spdx3.writer.console.console import write_value
9 | from spdx_tools.spdx3.writer.console.lifecycle_scoped_relationship_writer import write_lifecycle_scoped_relationship
10 |
11 |
12 | def write_software_dependency_relationship(
13 | relationship: SoftwareDependencyRelationship, text_output: TextIO, heading: bool = True
14 | ):
15 | if heading:
16 | text_output.write("## SoftwareDependencyRelationship\n")
17 | write_lifecycle_scoped_relationship(relationship, text_output, heading=False)
18 |
19 | for property_name in SoftwareDependencyRelationship.__annotations__.keys():
20 | write_value(property_name, getattr(relationship, property_name), text_output)
21 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import ElementCollection
7 | from spdx_tools.spdx3.writer.console.element_writer import write_element_properties
8 | from spdx_tools.spdx3.writer.console.external_map_writer import write_external_map
9 | from spdx_tools.spdx3.writer.console.namespace_map_writer import write_namespace_map
10 | from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading
11 |
12 |
13 | def write_collection(collection: ElementCollection, text_output: TextIO):
14 | write_element_properties(collection, text_output)
15 | text_output.write(f"elements: {', '.join(collection.element)}\n")
16 | write_optional_heading(collection.namespaces, "# Namespaces\n", text_output)
17 | for namespace_map in collection.namespaces:
18 | write_namespace_map(namespace_map, text_output)
19 | write_optional_heading(collection.imports, "# Imports\n", text_output)
20 | for external_map in collection.imports:
21 | write_external_map(external_map, text_output)
22 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from beartype.typing import TextIO
5 |
6 | from spdx_tools.spdx3.model import SpdxDocument
7 | from spdx_tools.spdx3.writer.console.bundle_writer import write_bundle
8 |
9 |
10 | def write_spdx_document(spdx_document: SpdxDocument, text_output: TextIO):
11 | text_output.write("## SPDX Document\n")
12 | write_bundle(spdx_document, text_output, False)
13 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/console/tool_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: Apache-2.0
2 | # Copyright (c) 2023 spdx contributors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | from beartype.typing import TextIO
13 |
14 | from spdx_tools.spdx3.model import Tool
15 | from spdx_tools.spdx3.writer.console.element_writer import write_element_properties
16 |
17 |
18 | def write_tool(tool: Tool, text_output: TextIO, heading: bool = True):
19 | if heading:
20 | text_output.write("## Tool\n")
21 | write_element_properties(tool, text_output)
22 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/json_ld/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/src/spdx_tools/spdx3/writer/json_ld/__init__.py
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import json
5 | import os
6 |
7 | from spdx_tools.spdx3.payload import Payload
8 | from spdx_tools.spdx3.writer.json_ld.json_ld_converter import convert_payload_to_json_ld_list_of_elements
9 |
10 |
11 | def write_payload(payload: Payload, file_name: str):
12 | element_list = convert_payload_to_json_ld_list_of_elements(payload)
13 |
14 | # this will be obsolete as soon as the context is publicly available under some URI
15 | with open(os.path.join(os.path.dirname(__file__), "context.json"), "r") as infile:
16 | context = json.load(infile)
17 |
18 | complete_dict = {"@context": context, "@graph": element_list}
19 |
20 | with open(file_name + ".jsonld", "w") as out:
21 | json.dump(complete_dict, out, indent=2)
22 |
--------------------------------------------------------------------------------
/src/spdx_tools/spdx3/writer/json_ld/process.md:
--------------------------------------------------------------------------------
1 | ### Workflow
2 |
3 | Process to produce context file and a serialization example:
4 |
5 | 1. Run
6 | ```
7 | spec-parser --gen-md --gen-refs --gen-rdf ../spdx-3-model/model
8 | ```
9 | - spdx-3-model (commit: 6cb4316, last commit where spec-parser is able to run)
10 | - spec-parser (main with commits from PR 44, 45)
11 |
12 | 2. Convert the generated `spec-parser/md_generated/model.ttl` to a json-ld file using https://frogcat.github.io/ttl2jsonld/demo/.
13 | 3. Convert owl to context using `convert_spdx_owl_to_jsonld_context("SPDX_OWL.json")`.
14 | 4. Place the generated `context.json` in `spdx_tools/spdx3/writer/jsonld/`.
15 | 5. To generate the jsonld from the testfile run
16 | ```
17 | pyspdxtools3 -i ./tests/spdx/data/SPDXJSONExample-v2.3.spdx.json -o example_with_context
18 | ```
19 |
20 |
21 | ### Manually
22 |
23 |
24 | ### Known limitations
25 | - Validation of enums does not work
26 | - Additional keys seem to be ignored in validation
27 | - inherited properties aren't validated
28 |
--------------------------------------------------------------------------------
/stdeb.cfg:
--------------------------------------------------------------------------------
1 | [DEFAULT]
2 | Depends = python-rdflib (>= 4.1.2), python-ply (>= 3.4)
3 | Copyright-File = LICENSE
4 |
5 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/data/SPDXJSONExample-UTF-16.spdx.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/data/SPDXJSONExample-UTF-16.spdx.json
--------------------------------------------------------------------------------
/tests/spdx/data/SPDXLite.spdx:
--------------------------------------------------------------------------------
1 | # from https://github.com/OpenChain-Project/OpenChain-JWG/blob/4675d7a61ad552e8f9780419c54dddbdf87f6018/subgroups/sbom-sg/outcomes/SPDX-Lite/sample/SPDX-tools-spdxlite.txt
2 | ## 2 Document Creation Information
3 |
4 | SPDXVersion: SPDX-2.2
5 | DataLicense: CC0-1.0
6 | SPDXID: SPDXRef-DOCUMENT
7 | DocumentName: example-v1.0
8 | DocumentNamespace: https://example.com/example-v1.0
9 | Creator: Person: someone
10 | Created: 2021-04-05T01:23:45Z
11 |
12 | ## 3 Package Information
13 |
14 | PackageName: SPDX tools
15 | SPDXID: SPDXRef-spdxtools
16 | PackageVersion: 2.0.3
17 | PackageFileName: spdx-tools-2.0.2-jar-with-dependencies.jar
18 | PackageDownloadLocation: NONE
19 | FilesAnalyzed: false
20 | PackageHomePage: https://spdx.org/tools
21 | PackageLicenseConcluded: Apache-2.0
22 | PackageLicenseDeclared: Apache-2.0
23 | PackageLicenseComments:
24 | PackageCopyrightText: software copyright (c) 2000-2003, BEA Systems,
25 | PackageComment:
26 | ModificationRecord: NO
27 | CompileOptions: --some-option
28 | LinkMethodology: Dynamic
29 |
30 |
31 | ## 6 Other Licensing Information Detected
32 |
33 | LicenseID: LicenseRef-1
34 | ExtractedText: hoge
35 | LicenseName: NOASSERTION
36 | LicenseComment:
37 |
--------------------------------------------------------------------------------
/tests/spdx/data/SPDXRdfExample-UTF-16.spdx.rdf.xml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/data/SPDXRdfExample-UTF-16.spdx.rdf.xml
--------------------------------------------------------------------------------
/tests/spdx/data/SPDXTagExample-UTF-16.spdx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/data/SPDXTagExample-UTF-16.spdx
--------------------------------------------------------------------------------
/tests/spdx/data/SPDXXMLExample-UTF-16.spdx.xml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/data/SPDXXMLExample-UTF-16.spdx.xml
--------------------------------------------------------------------------------
/tests/spdx/data/SPDXYAMLExample-UTF-16.spdx.yaml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/data/SPDXYAMLExample-UTF-16.spdx.yaml
--------------------------------------------------------------------------------
/tests/spdx/examples/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/examples/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/jsonschema/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/jsonschema/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/jsonschema/test_checksum_converter.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx.jsonschema.checksum_converter import ChecksumConverter
7 | from spdx_tools.spdx.jsonschema.checksum_properties import ChecksumProperty
8 | from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm
9 |
10 |
11 | @pytest.fixture
12 | def converter() -> ChecksumConverter:
13 | return ChecksumConverter()
14 |
15 |
16 | @pytest.mark.parametrize(
17 | "checksum_property,expected",
18 | [(ChecksumProperty.ALGORITHM, "algorithm"), (ChecksumProperty.CHECKSUM_VALUE, "checksumValue")],
19 | )
20 | def test_json_property_names(converter: ChecksumConverter, checksum_property: ChecksumProperty, expected: str):
21 | assert converter.json_property_name(checksum_property) == expected
22 |
23 |
24 | def test_successful_conversion(converter: ChecksumConverter):
25 | checksum = Checksum(ChecksumAlgorithm.SHA1, "123")
26 |
27 | converted_dict = converter.convert(checksum)
28 |
29 | assert converted_dict == {
30 | converter.json_property_name(ChecksumProperty.ALGORITHM): "SHA1",
31 | converter.json_property_name(ChecksumProperty.CHECKSUM_VALUE): "123",
32 | }
33 |
34 |
35 | def test_json_type(converter: ChecksumConverter):
36 | assert converter.get_json_type() == ChecksumProperty
37 |
38 |
39 | def test_data_model_type(converter: ChecksumConverter):
40 | assert converter.get_data_model_type() == Checksum
41 |
--------------------------------------------------------------------------------
/tests/spdx/mock_utils.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from unittest.mock import NonCallableMagicMock
5 |
6 |
7 | def assert_mock_method_called_with_arguments(mock_object: NonCallableMagicMock, method_name: str, *args):
8 | assert len(mock_object.method_calls) == len(args)
9 | for running_index in range(len(args)):
10 | call = mock_object.method_calls[running_index]
11 | assert call[0] == method_name
12 | assert call[1][0] == args[running_index]
13 |
14 |
15 | def assert_no_mock_methods_called(mock_object: NonCallableMagicMock):
16 | assert len(mock_object.method_calls) == 0
17 |
--------------------------------------------------------------------------------
/tests/spdx/model/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/model/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/model/test_checksum.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | import pytest
6 |
7 | from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm
8 |
9 |
10 | def test_correct_initialization():
11 | checksum = Checksum(ChecksumAlgorithm.BLAKE2B_256, "value")
12 | assert checksum.algorithm == ChecksumAlgorithm.BLAKE2B_256
13 | assert checksum.value == "value"
14 |
15 |
16 | def test_wrong_type_in_algorithm():
17 | with pytest.raises(TypeError):
18 | Checksum(42, "value")
19 |
20 |
21 | def test_wrong_type_in_value():
22 | with pytest.raises(TypeError):
23 | Checksum(ChecksumAlgorithm.BLAKE2B_256, 42)
24 |
--------------------------------------------------------------------------------
/tests/spdx/model/test_external_document_ref.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | from unittest import mock
6 |
7 | import pytest
8 |
9 | from spdx_tools.spdx.model import ExternalDocumentRef
10 |
11 |
12 | @mock.patch("spdx_tools.spdx.model.Checksum", autospec=True)
13 | def test_correct_initialization(checksum):
14 | external_document_ref = ExternalDocumentRef("id", "uri", checksum)
15 | assert external_document_ref.document_ref_id == "id"
16 | assert external_document_ref.document_uri == "uri"
17 | assert external_document_ref.checksum == checksum
18 |
19 |
20 | @mock.patch("spdx_tools.spdx.model.Checksum", autospec=True)
21 | def test_wrong_type_in_spdx_id(checksum):
22 | with pytest.raises(TypeError):
23 | ExternalDocumentRef(42, "uri", checksum)
24 |
25 |
26 | @mock.patch("spdx_tools.spdx.model.Checksum", autospec=True)
27 | def test_wrong_type_in_document_uri(checksum):
28 | with pytest.raises(TypeError):
29 | ExternalDocumentRef("id", 42, checksum)
30 |
31 |
32 | def test_wrong_type_in_checksum():
33 | with pytest.raises(TypeError):
34 | ExternalDocumentRef("id", "uri", 42)
35 |
--------------------------------------------------------------------------------
/tests/spdx/model/test_external_package_reference.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | import pytest
6 |
7 | from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory
8 |
9 |
10 | def test_correct_initialization():
11 | external_package_reference = ExternalPackageRef(ExternalPackageRefCategory.OTHER, "type", "locator", "comment")
12 | assert external_package_reference.category == ExternalPackageRefCategory.OTHER
13 | assert external_package_reference.reference_type == "type"
14 | assert external_package_reference.locator == "locator"
15 | assert external_package_reference.comment == "comment"
16 |
17 |
18 | def test_wrong_type_in_category():
19 | with pytest.raises(TypeError):
20 | ExternalPackageRef([ExternalPackageRefCategory.OTHER], "type", "locator")
21 |
22 |
23 | def test_wrong_type_in_reference_type():
24 | with pytest.raises(TypeError):
25 | ExternalPackageRef(ExternalPackageRefCategory.OTHER, 42, "locator")
26 |
27 |
28 | def test_wrong_type_in_locator():
29 | with pytest.raises(TypeError):
30 | ExternalPackageRef(ExternalPackageRefCategory.OTHER, "type", 42)
31 |
32 |
33 | def test_wrong_type_in_comment():
34 | with pytest.raises(TypeError):
35 | ExternalPackageRef(ExternalPackageRefCategory.OTHER, "type", "locator", [])
36 |
--------------------------------------------------------------------------------
/tests/spdx/model/test_extracted_licensing_info.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | import pytest
6 |
7 | from spdx_tools.spdx.model import ExtractedLicensingInfo
8 |
9 |
10 | def test_correct_initialization():
11 | extracted_licensing_info = ExtractedLicensingInfo("id", "text", "name", ["reference"], "comment")
12 | assert extracted_licensing_info.license_id == "id"
13 | assert extracted_licensing_info.extracted_text == "text"
14 | assert extracted_licensing_info.license_name == "name"
15 | assert extracted_licensing_info.cross_references == ["reference"]
16 | assert extracted_licensing_info.comment == "comment"
17 |
18 |
19 | def test_wrong_type_in_license_id():
20 | with pytest.raises(TypeError):
21 | ExtractedLicensingInfo(license_id=42)
22 |
23 |
24 | def test_wrong_type_in_extracted_text():
25 | with pytest.raises(TypeError):
26 | ExtractedLicensingInfo(extracted_text=42)
27 |
28 |
29 | def test_wrong_type_in_license_name():
30 | with pytest.raises(TypeError):
31 | ExtractedLicensingInfo(license_name=42)
32 |
33 |
34 | def test_wrong_type_in_cross_references():
35 | with pytest.raises(TypeError):
36 | ExtractedLicensingInfo(cross_references=[41, 42])
37 |
38 |
39 | def test_wrong_type_in_comment():
40 | with pytest.raises(TypeError):
41 | ExtractedLicensingInfo(comment=42)
42 |
--------------------------------------------------------------------------------
/tests/spdx/model/test_package_verification_code.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | import pytest
6 |
7 | from spdx_tools.spdx.model import PackageVerificationCode
8 |
9 |
10 | def test_correct_initialization():
11 | package_verification_code = PackageVerificationCode("value", ["file1", "file2"])
12 | assert package_verification_code.value == "value"
13 | assert package_verification_code.excluded_files == ["file1", "file2"]
14 |
15 |
16 | def test_wrong_type_in_value():
17 | with pytest.raises(TypeError):
18 | PackageVerificationCode(42, ["file1", "file2"])
19 |
20 |
21 | def test_wrong_type_in_excluded_files():
22 | with pytest.raises(TypeError):
23 | PackageVerificationCode("value", "file1")
24 |
--------------------------------------------------------------------------------
/tests/spdx/model/test_relationship.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | import pytest
6 |
7 | from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion
8 |
9 |
10 | def test_correct_initialization():
11 | relationship = Relationship("id", RelationshipType.OTHER, SpdxNoAssertion(), "comment")
12 | assert relationship.spdx_element_id == "id"
13 | assert relationship.relationship_type == RelationshipType.OTHER
14 | assert relationship.related_spdx_element_id == SpdxNoAssertion()
15 | assert relationship.comment == "comment"
16 |
17 |
18 | def test_wrong_type_in_spdx_element_id():
19 | with pytest.raises(TypeError):
20 | Relationship(SpdxNoAssertion(), RelationshipType.OTHER, "other_id")
21 |
22 |
23 | def test_wrong_type_in_relationship_type():
24 | with pytest.raises(TypeError):
25 | Relationship("id", 42, "other_id")
26 |
27 |
28 | def test_wrong_type_in_related_spdx_element_id():
29 | with pytest.raises(TypeError):
30 | Relationship("id", RelationshipType.OTHER, 42)
31 |
32 |
33 | def test_wrong_type_in_comment():
34 | with pytest.raises(TypeError):
35 | Relationship("id", RelationshipType.OTHER, "other_id", 42)
36 |
--------------------------------------------------------------------------------
/tests/spdx/model/test_version.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | import pytest
6 |
7 | from spdx_tools.spdx.model import Version
8 |
9 |
10 | @pytest.mark.parametrize("input_string,expected", [("1.2", Version(1, 2)), ("12.345", Version(12, 345))])
11 | def test_version_from_string(input_string, expected):
12 | assert Version.is_valid_version_string(input_string)
13 | version: Version = Version.from_string(input_string)
14 | assert version == expected
15 |
16 |
17 | @pytest.mark.parametrize("input_string", ["1", "1-2", "1.a", "a", "a.b", "a.1", "v1.2", "1.2v"])
18 | def test_invalid_version_string(input_string):
19 | assert not Version.is_valid_version_string(input_string)
20 | with pytest.raises(ValueError) as error:
21 | Version.from_string(input_string)
22 | assert str(error.value) == f"{input_string} is not a valid version string"
23 |
--------------------------------------------------------------------------------
/tests/spdx/parser/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/parser/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/parser/all_formats/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/parser/all_formats/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/parser/jsonlikedict/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/parser/jsonlikedict/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/parser/jsonlikedict/test_checksum_parser.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from unittest import TestCase
5 |
6 | import pytest
7 |
8 | from spdx_tools.spdx.model import ChecksumAlgorithm
9 | from spdx_tools.spdx.parser.error import SPDXParsingError
10 | from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser
11 |
12 |
13 | def test_parse_checksum():
14 | checksum_parser = ChecksumParser()
15 | checksum_dict = {"algorithm": "SHA1", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759"}
16 |
17 | checksum = checksum_parser.parse_checksum(checksum_dict)
18 |
19 | assert checksum.value == "d6a770ba38583ed4bb4525bd96e50461655d2759"
20 | assert checksum.algorithm == ChecksumAlgorithm.SHA1
21 |
22 |
23 | def test_parse_invalid_checksum():
24 | checksum_parser = ChecksumParser()
25 | checksum_dict = {"algorithm": "SHA", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759"}
26 |
27 | with pytest.raises(SPDXParsingError) as err:
28 | checksum_parser.parse_checksum(checksum_dict)
29 |
30 | TestCase().assertCountEqual(
31 | err.value.get_messages(), ["Error while parsing Checksum: ['Invalid ChecksumAlgorithm: SHA']"]
32 | )
33 |
34 |
35 | def test_parse_incomplete_checksum():
36 | checksum_parser = ChecksumParser()
37 | checksum_dict = {"algorithm": "SHA1"}
38 |
39 | with pytest.raises(SPDXParsingError):
40 | checksum_parser.parse_checksum(checksum_dict)
41 |
--------------------------------------------------------------------------------
/tests/spdx/parser/rdf/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/parser/rdf/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info.rdf.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 | documentComment
9 | documentName
10 |
11 |
12 |
13 | 3.19
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/tests/spdx/parser/rdf/test_annotation_parser.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import os
5 | from datetime import datetime
6 |
7 | from rdflib import BNode, Graph, URIRef
8 |
9 | from spdx_tools.spdx.model import Actor, ActorType, AnnotationType
10 | from spdx_tools.spdx.parser.rdf.annotation_parser import parse_annotation
11 | from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE
12 |
13 |
14 | def test_parse_annotation():
15 | graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml"))
16 | doc_namespace = "https://some.namespace"
17 | file_node = URIRef(f"{doc_namespace}#SPDXRef-File")
18 | annotation_node = graph.value(subject=file_node, predicate=SPDX_NAMESPACE.annotation)
19 | assert isinstance(annotation_node, BNode)
20 |
21 | annotation = parse_annotation(annotation_node, graph, file_node, doc_namespace)
22 |
23 | assert annotation.spdx_id == "SPDXRef-File"
24 | assert annotation.annotation_type == AnnotationType.REVIEW
25 | assert annotation.annotator == Actor(ActorType.PERSON, "annotatorName", "some@mail.com")
26 | assert annotation.annotation_date == datetime(2022, 12, 1, 0, 0)
27 | assert annotation.annotation_comment == "annotationComment"
28 |
--------------------------------------------------------------------------------
/tests/spdx/parser/rdf/test_graph_parsing_function.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 | from rdflib import Graph, Namespace, URIRef
6 |
7 | from spdx_tools.spdx.parser.rdf.graph_parsing_functions import parse_spdx_id, remove_prefix
8 |
9 |
10 | @pytest.mark.parametrize(
11 | "resource,doc_namespace,ext_namespace_mapping,expected",
12 | [
13 | (URIRef("docNamespace#SPDXRef-Test"), "docNamespace", ("", Namespace("")), "SPDXRef-Test"),
14 | (URIRef("docNamespaceSPDXRef-Test"), "docNamespace", ("", Namespace("")), "docNamespaceSPDXRef-Test"),
15 | (
16 | URIRef("differentNamespace#SPDXRef-Test"),
17 | "docNamespace",
18 | ("extDoc", Namespace("differentNamespace#")),
19 | "extDoc:SPDXRef-Test",
20 | ),
21 | (None, "", ("", Namespace("")), None),
22 | ],
23 | )
24 | def test_parse_spdx_id(resource, doc_namespace, ext_namespace_mapping, expected):
25 | graph = Graph()
26 | graph.bind(*ext_namespace_mapping)
27 | spdx_id = parse_spdx_id(resource, doc_namespace, graph)
28 |
29 | assert spdx_id == expected
30 |
31 |
32 | @pytest.mark.parametrize(
33 | "string,prefix,expected", [("prefixString", "prefix", "String"), ("prefixString", "refix", "prefixString")]
34 | )
35 | def test_remove_prefix(string, prefix, expected):
36 | shorten_string = remove_prefix(string, prefix)
37 |
38 | assert expected == shorten_string
39 |
--------------------------------------------------------------------------------
/tests/spdx/parser/tagvalue/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/parser/tagvalue/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/test_casing_tools.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx.casing_tools import camel_case_to_snake_case, snake_case_to_camel_case
7 |
8 |
9 | @pytest.mark.parametrize("snake_case_str,camel_case_str", [("snake_case", "snakeCase")])
10 | def test_snake_case_to_camel_case(snake_case_str, camel_case_str):
11 | camel_case = snake_case_to_camel_case(snake_case_str)
12 |
13 | assert camel_case == camel_case_str
14 |
15 |
16 | @pytest.mark.parametrize(
17 | "camel_case_str,snake_case_str",
18 | [("camelCase", "camel_case"), ("camelCaseMore", "camel_case_more"), ("CamelCase", "camel_case")],
19 | )
20 | def test_camel_case_to_snake_case(camel_case_str, snake_case_str):
21 | snake_case = camel_case_to_snake_case(camel_case_str)
22 |
23 | assert snake_case == snake_case_str
24 |
--------------------------------------------------------------------------------
/tests/spdx/validation/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/validation/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/validation/test_actor_validator.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | from typing import List
6 |
7 | import pytest
8 |
9 | from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID
10 | from spdx_tools.spdx.model import ActorType
11 | from spdx_tools.spdx.validation.actor_validator import validate_actor
12 | from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage
13 | from tests.spdx.fixtures import actor_fixture
14 |
15 |
16 | def test_valid_actor_person():
17 | actor = actor_fixture()
18 | validation_messages: List[ValidationMessage] = validate_actor(actor, DOCUMENT_SPDX_ID)
19 |
20 | assert validation_messages == []
21 |
22 |
23 | @pytest.mark.parametrize(
24 | "actor, expected_message",
25 | [
26 | (
27 | actor_fixture(actor_type=ActorType.TOOL, email="mail@mail.com"),
28 | "email must be None if actor_type is TOOL, but is: mail@mail.com",
29 | ),
30 | ],
31 | )
32 | def test_invalid_actor(actor, expected_message):
33 | parent_id = DOCUMENT_SPDX_ID
34 | validation_messages: List[ValidationMessage] = validate_actor(actor, parent_id)
35 |
36 | expected = ValidationMessage(
37 | expected_message,
38 | ValidationContext(parent_id=parent_id, element_type=SpdxElementType.ACTOR, full_element=actor),
39 | )
40 |
41 | assert validation_messages == [expected]
42 |
--------------------------------------------------------------------------------
/tests/spdx/validation/test_annotation_validator.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | from typing import List
6 |
7 | import pytest
8 |
9 | from spdx_tools.spdx.model import Annotation, Document
10 | from spdx_tools.spdx.validation.annotation_validator import validate_annotation
11 | from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage
12 | from tests.spdx.fixtures import annotation_fixture, document_fixture, file_fixture
13 |
14 |
15 | def test_valid_annotation():
16 | validation_messages: List[ValidationMessage] = validate_annotation(annotation_fixture(), document_fixture())
17 |
18 | assert validation_messages == []
19 |
20 |
21 | @pytest.mark.parametrize(
22 | "annotation_id, file_id, expected_message",
23 | [
24 | (
25 | "SPDXRef-File",
26 | "SPDXRef-hiddenFile",
27 | 'did not find the referenced spdx_id "SPDXRef-File" in the SPDX document',
28 | )
29 | ],
30 | )
31 | def test_invalid_annotation(annotation_id, file_id, expected_message):
32 | annotation: Annotation = annotation_fixture(spdx_id=annotation_id)
33 | document: Document = document_fixture(files=[file_fixture(spdx_id=file_id)])
34 | validation_messages: List[ValidationMessage] = validate_annotation(annotation, document)
35 |
36 | expected = ValidationMessage(
37 | expected_message, ValidationContext(element_type=SpdxElementType.ANNOTATION, full_element=annotation)
38 | )
39 |
40 | assert validation_messages == [expected]
41 |
--------------------------------------------------------------------------------
/tests/spdx/validation/test_external_document_ref_validator.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | from typing import List
6 |
7 | from spdx_tools.spdx.validation.external_document_ref_validator import validate_external_document_ref
8 | from spdx_tools.spdx.validation.validation_message import ValidationMessage
9 | from tests.spdx.fixtures import external_document_ref_fixture
10 |
11 |
12 | def test_valid_external_document_ref():
13 | external_document_ref = external_document_ref_fixture()
14 | validation_messages: List[ValidationMessage] = validate_external_document_ref(
15 | external_document_ref, "parent_id", "SPDX-2.3"
16 | )
17 |
18 | assert validation_messages == []
19 |
--------------------------------------------------------------------------------
/tests/spdx/writer/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/writer/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/writer/json/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/writer/json/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/writer/json/expected_results/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/writer/json/expected_results/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/writer/rdf/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/writer/rdf/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/writer/rdf/test_annotation_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from rdflib import RDF, RDFS, Graph, Literal, URIRef
5 |
6 | from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string
7 | from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE
8 | from spdx_tools.spdx.writer.rdf.annotation_writer import add_annotation_to_graph
9 | from tests.spdx.fixtures import annotation_fixture
10 |
11 |
12 | def test_add_annotation_to_graph():
13 | graph = Graph()
14 | annotation = annotation_fixture()
15 |
16 | add_annotation_to_graph(annotation, graph, "docNamespace", {})
17 |
18 | assert (URIRef("docNamespace#SPDXRef-File"), SPDX_NAMESPACE.annotation, None) in graph
19 | assert (None, RDF.type, SPDX_NAMESPACE.Annotation) in graph
20 | assert (None, SPDX_NAMESPACE.annotationType, SPDX_NAMESPACE.annotationType_review) in graph
21 | assert (None, SPDX_NAMESPACE.annotationDate, Literal(datetime_to_iso_string(annotation.annotation_date))) in graph
22 | assert (None, SPDX_NAMESPACE.annotator, Literal(annotation.annotator.to_serialized_string())) in graph
23 | assert (None, RDFS.comment, Literal(annotation.annotation_comment)) in graph
24 |
--------------------------------------------------------------------------------
/tests/spdx/writer/rdf/test_external_document_ref_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from rdflib import RDF, Graph, URIRef
5 |
6 | from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE
7 | from spdx_tools.spdx.writer.rdf.external_document_ref_writer import add_external_document_ref_to_graph
8 | from tests.spdx.fixtures import external_document_ref_fixture
9 |
10 |
11 | def test_add_external_document_ref_to_graph():
12 | graph = Graph()
13 | external_document_ref = external_document_ref_fixture()
14 |
15 | add_external_document_ref_to_graph(external_document_ref, graph, URIRef("docNode"), "docNamespace")
16 |
17 | assert (
18 | URIRef("docNode"),
19 | SPDX_NAMESPACE.externalDocumentRef,
20 | URIRef("docNamespace#DocumentRef-external"),
21 | ) in graph
22 | assert (None, RDF.type, SPDX_NAMESPACE.ExternalDocumentRef) in graph
23 | assert (None, SPDX_NAMESPACE.checksum, None) in graph
24 | assert (None, RDF.type, SPDX_NAMESPACE.Checksum) in graph
25 | assert (None, SPDX_NAMESPACE.spdxDocument, URIRef(external_document_ref.document_uri)) in graph
26 |
--------------------------------------------------------------------------------
/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from rdflib import RDF, RDFS, Graph, Literal, URIRef
5 |
6 | from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE
7 | from spdx_tools.spdx.writer.rdf.extracted_licensing_info_writer import add_extracted_licensing_info_to_graph
8 | from tests.spdx.fixtures import extracted_licensing_info_fixture
9 |
10 |
11 | def test_add_extracted_licensing_info_to_graph():
12 | graph = Graph()
13 | extracted_licensing_info = extracted_licensing_info_fixture()
14 |
15 | add_extracted_licensing_info_to_graph(extracted_licensing_info, graph, URIRef("docNode"), "docNamespace")
16 |
17 | assert (URIRef("docNode"), SPDX_NAMESPACE.hasExtractedLicensingInfo, None) in graph
18 | assert (URIRef("docNamespace#LicenseRef-1"), RDF.type, SPDX_NAMESPACE.ExtractedLicensingInfo) in graph
19 | assert (None, SPDX_NAMESPACE.licenseId, Literal(extracted_licensing_info.license_id)) in graph
20 | assert (None, SPDX_NAMESPACE.extractedText, Literal(extracted_licensing_info.extracted_text)) in graph
21 | assert (None, RDFS.seeAlso, Literal(extracted_licensing_info.cross_references[0])) in graph
22 | assert (None, SPDX_NAMESPACE.name, Literal(extracted_licensing_info.license_name)) in graph
23 | assert (None, RDFS.comment, Literal(extracted_licensing_info.comment)) in graph
24 |
--------------------------------------------------------------------------------
/tests/spdx/writer/rdf/test_rdf_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import os
5 |
6 | import pytest
7 |
8 | from spdx_tools.spdx.model import Document
9 | from spdx_tools.spdx.writer.rdf.rdf_writer import write_document_to_file
10 | from tests.spdx.fixtures import document_fixture
11 |
12 |
13 | @pytest.fixture
14 | def temporary_file_path() -> str:
15 | temporary_file_path = "temp_test_rdf_writer_output.rdf.xml"
16 | yield temporary_file_path
17 | os.remove(temporary_file_path)
18 |
19 |
20 | def test_write_document_to_file(temporary_file_path: str):
21 | document: Document = document_fixture()
22 |
23 | write_document_to_file(document, temporary_file_path, False)
24 |
--------------------------------------------------------------------------------
/tests/spdx/writer/rdf/test_relationship_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from rdflib import RDFS, Graph, Literal, URIRef
5 |
6 | from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID
7 | from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE
8 | from spdx_tools.spdx.writer.rdf.relationship_writer import add_relationship_to_graph
9 | from tests.spdx.fixtures import relationship_fixture
10 |
11 |
12 | def test_add_relationship_to_graph():
13 | relationship = relationship_fixture()
14 | graph = Graph()
15 | add_relationship_to_graph(relationship, graph, "docNamespace", {})
16 |
17 | assert (URIRef(f"docNamespace#{DOCUMENT_SPDX_ID}"), SPDX_NAMESPACE.relationship, None) in graph
18 | assert (None, SPDX_NAMESPACE.relationshipType, SPDX_NAMESPACE.relationshipType_describes) in graph
19 | assert (None, SPDX_NAMESPACE.relatedSpdxElement, URIRef("docNamespace#SPDXRef-File")) in graph
20 | assert (None, RDFS.comment, Literal(relationship.comment)) in graph
21 |
--------------------------------------------------------------------------------
/tests/spdx/writer/rdf/test_writer_utils.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id
7 |
8 |
9 | @pytest.mark.parametrize(
10 | "spdx_id,namespace,external_namespaces,expected",
11 | [
12 | ("SPDXRef-File", "docNamespace", {}, "docNamespace#SPDXRef-File"),
13 | (
14 | "externalDoc:SPDXRef-File",
15 | "docNamespace",
16 | {"externalDoc": "externalNamespace"},
17 | "externalNamespace#SPDXRef-File",
18 | ),
19 | ("externalDoc#A-Ref", "", {}, "externalDoc#A-Ref"),
20 | ("externalDoc:A-Ref", "", {}, "externalDoc:A-Ref"),
21 | ],
22 | )
23 | def test_add_namespace_to_spdx_id(spdx_id, namespace, expected, external_namespaces):
24 | extended_spdx_id = add_namespace_to_spdx_id(spdx_id, namespace, external_namespaces)
25 |
26 | assert extended_spdx_id == expected
27 |
--------------------------------------------------------------------------------
/tests/spdx/writer/tagvalue/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx/writer/tagvalue/__init__.py
--------------------------------------------------------------------------------
/tests/spdx/writer/tagvalue/expected_results/expected_tag_value.spdx:
--------------------------------------------------------------------------------
1 | ## Document Information
2 | SPDXVersion: spdxVersion
3 | DataLicense: dataLicense
4 | SPDXID: documentId
5 | DocumentName: documentName
6 | DocumentNamespace: documentNamespace
7 | DocumentComment: comment
8 |
9 | ## External Document References
10 | ExternalDocumentRef: docRefId externalDocumentUri SHA1: externalRefSha1
11 |
12 | ## Creation Information
13 | LicenseListVersion: spdxVersion
14 | Creator: Tool: tools-python (tools-python@github.com)
15 | Created: 2022-12-01T00:00:00Z
16 |
17 | ## File Information
18 | FileName: fileName
19 | SPDXID: fileId
20 | FileChecksum: SHA1: fileSha1
21 |
22 | ## Snippet Information
23 | SnippetSPDXID: snippetId
24 | SnippetFromFileSPDXID: fileId
25 | SnippetByteRange: 1:2
26 |
27 | ## Package Information
28 | PackageName: packageName
29 | SPDXID: packageId
30 | PackageDownloadLocation: NONE
31 | FilesAnalyzed: True
32 |
33 | ## License Information
34 | LicenseID: licenseId
35 | ExtractedText: licenseText
36 |
37 | ## Relationships
38 | Relationship: documentId DESCRIBES packageId
39 | Relationship: documentId DESCRIBES fileId
40 | RelationshipComment: relationshipComment
41 | Relationship: relationshipOriginId AMENDS relationShipTargetId
42 |
43 | ## Annotations
44 | Annotator: Person: reviewerName
45 | AnnotationDate: 2022-12-02T00:00:00Z
46 | AnnotationType: REVIEW
47 | SPDXREF: documentId
48 | AnnotationComment: reviewComment
49 |
50 | Annotator: Tool: toolName
51 | AnnotationDate: 2022-12-03T00:00:00Z
52 | AnnotationType: OTHER
53 | SPDXREF: fileId
54 | AnnotationComment: otherComment
55 |
--------------------------------------------------------------------------------
/tests/spdx/writer/tagvalue/test_annotation_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from unittest.mock import MagicMock, call, mock_open, patch
5 |
6 | from spdx_tools.spdx.writer.tagvalue.annotation_writer import write_annotation
7 | from tests.spdx.fixtures import annotation_fixture
8 |
9 |
10 | def test_annotation_writer():
11 | annotation = annotation_fixture()
12 |
13 | mock: MagicMock = mock_open()
14 | with patch(f"{__name__}.open", mock, create=True):
15 | with open("foo", "w") as file:
16 | write_annotation(annotation, file)
17 |
18 | mock.assert_called_once_with("foo", "w")
19 | handle = mock()
20 | handle.write.assert_has_calls(
21 | [
22 | call(f"Annotator: Person: {annotation.annotator.name} ({annotation.annotator.email})\n"),
23 | call("AnnotationDate: 2022-12-24T00:00:00Z\n"),
24 | call(f"AnnotationType: {annotation.annotation_type.name}\n"),
25 | call(f"SPDXREF: {annotation.spdx_id}\n"),
26 | call(f"AnnotationComment: {annotation.annotation_comment}\n"),
27 | ]
28 | )
29 |
--------------------------------------------------------------------------------
/tests/spdx/writer/tagvalue/test_checksum_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx.model import ChecksumAlgorithm
7 | from spdx_tools.spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value
8 | from tests.spdx.fixtures import checksum_fixture
9 |
10 |
11 | @pytest.mark.parametrize(
12 | "checksum, expected_string",
13 | [
14 | (checksum_fixture(), "SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c"),
15 | (checksum_fixture(algorithm=ChecksumAlgorithm.SHA3_256, value="fdsef"), "SHA3-256: fdsef"),
16 | (checksum_fixture(algorithm=ChecksumAlgorithm.SHA3_384, value="fdsef"), "SHA3-384: fdsef"),
17 | (checksum_fixture(algorithm=ChecksumAlgorithm.SHA3_512, value="fdsef"), "SHA3-512: fdsef"),
18 | (checksum_fixture(algorithm=ChecksumAlgorithm.BLAKE2B_256, value="fdsef"), "BLAKE2b-256: fdsef"),
19 | (checksum_fixture(algorithm=ChecksumAlgorithm.BLAKE2B_384, value="fdsef"), "BLAKE2b-384: fdsef"),
20 | (checksum_fixture(algorithm=ChecksumAlgorithm.BLAKE2B_512, value="fdsef"), "BLAKE2b-512: fdsef"),
21 | ],
22 | )
23 | def test_checksum_writer(checksum, expected_string):
24 | checksum_string = write_checksum_to_tag_value(checksum)
25 |
26 | assert checksum_string == expected_string
27 |
--------------------------------------------------------------------------------
/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from unittest.mock import MagicMock, call, mock_open, patch
5 |
6 | from spdx_tools.spdx.writer.tagvalue.extracted_licensing_info_writer import write_extracted_licensing_info
7 | from tests.spdx.fixtures import extracted_licensing_info_fixture
8 |
9 |
10 | def test_extracted_licensing_info_writer():
11 | extracted_licensing_info = extracted_licensing_info_fixture()
12 |
13 | mock: MagicMock = mock_open()
14 | with patch(f"{__name__}.open", mock, create=True):
15 | with open("foo", "w") as file:
16 | write_extracted_licensing_info(extracted_licensing_info, file)
17 |
18 | mock.assert_called_once_with("foo", "w")
19 | handle = mock()
20 | handle.write.assert_has_calls(
21 | [
22 | call(f"LicenseID: {extracted_licensing_info.license_id}\n"),
23 | call(f"ExtractedText: {extracted_licensing_info.extracted_text}\n"),
24 | call(f"LicenseName: {extracted_licensing_info.license_name}\n"),
25 | call(f"LicenseCrossReference: {extracted_licensing_info.cross_references[0]}\n"),
26 | call(f"LicenseComment: {extracted_licensing_info.comment}\n"),
27 | ]
28 | )
29 |
--------------------------------------------------------------------------------
/tests/spdx3/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx3/__init__.py
--------------------------------------------------------------------------------
/tests/spdx3/bump/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx3/bump/__init__.py
--------------------------------------------------------------------------------
/tests/spdx3/bump/test_bump_utils.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2022 spdx contributors
2 |
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none
7 | from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion
8 | from spdx_tools.spdx.model.spdx_none import SpdxNone
9 |
10 |
11 | @pytest.mark.parametrize(
12 | "input_argument,expected_value,expected_stdout",
13 | [
14 | (SpdxNone(), None, "test_field: Missing conversion for SpdxNone.\n"),
15 | (SpdxNoAssertion(), None, ""),
16 | ("test_string", "test_string", ""),
17 | ],
18 | )
19 | def test_handle_no_assertion_or_none(input_argument, expected_value, expected_stdout, capsys):
20 | value = handle_no_assertion_or_none(input_argument, "test_field")
21 |
22 | captured = capsys.readouterr()
23 |
24 | assert value == expected_value
25 | assert captured.out == expected_stdout
26 |
--------------------------------------------------------------------------------
/tests/spdx3/bump/test_file_bump.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | from spdx_tools.spdx3.bump_from_spdx2.file import bump_file
6 | from spdx_tools.spdx3.model import Hash, HashAlgorithm
7 | from spdx_tools.spdx3.model.software import File
8 | from spdx_tools.spdx3.payload import Payload
9 | from spdx_tools.spdx.model.file import File as Spdx2_File
10 | from tests.spdx.fixtures import file_fixture
11 |
12 |
13 | def test_bump_file():
14 | payload = Payload()
15 | document_namespace = "https://doc.namespace"
16 | spdx2_file: Spdx2_File = file_fixture()
17 | integrity_method: Hash = Hash(HashAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c")
18 | expected_new_file_id = f"{document_namespace}#{spdx2_file.spdx_id}"
19 |
20 | bump_file(spdx2_file, payload, document_namespace, [], [])
21 | file = payload.get_element(expected_new_file_id)
22 |
23 | assert isinstance(file, File)
24 | assert file.spdx_id == expected_new_file_id
25 | assert file.verified_using == [integrity_method]
26 | assert file.copyright_text == spdx2_file.copyright_text
27 | assert file.attribution_text == spdx2_file.attribution_texts[0]
28 |
--------------------------------------------------------------------------------
/tests/spdx3/bump/test_snippet_bump.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | from spdx_tools.spdx3.bump_from_spdx2.snippet import bump_snippet
6 | from spdx_tools.spdx3.model.software import Snippet
7 | from spdx_tools.spdx3.payload import Payload
8 | from spdx_tools.spdx.model.snippet import Snippet as Spdx2_Snippet
9 | from tests.spdx.fixtures import snippet_fixture
10 |
11 |
12 | def test_bump_snippet():
13 | payload = Payload()
14 | document_namespace = "https://doc.namespace"
15 | spdx2_snippet: Spdx2_Snippet = snippet_fixture()
16 | expected_new_snippet_id = f"{document_namespace}#{spdx2_snippet.spdx_id}"
17 |
18 | bump_snippet(spdx2_snippet, payload, document_namespace, [], [])
19 | snippet = payload.get_element(expected_new_snippet_id)
20 |
21 | assert isinstance(snippet, Snippet)
22 | assert snippet.spdx_id == expected_new_snippet_id
23 | assert snippet.copyright_text == spdx2_snippet.copyright_text
24 | assert snippet.attribution_text == spdx2_snippet.attribution_texts[0]
25 |
--------------------------------------------------------------------------------
/tests/spdx3/bump/test_spdx_document_bump.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import sys
5 |
6 | from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document
7 | from spdx_tools.spdx3.payload import Payload
8 | from spdx_tools.spdx3.writer.console.payload_writer import write_payload
9 | from spdx_tools.spdx.model.actor import ActorType
10 | from spdx_tools.spdx.model.document import Document as Spdx2_Document
11 | from tests.spdx.fixtures import actor_fixture, annotation_fixture, creation_info_fixture, document_fixture
12 |
13 |
14 | def test_bump_spdx_document():
15 | spdx2_document: Spdx2_Document = document_fixture()
16 | spdx2_document.creation_info.creators.append(actor_fixture(ActorType.TOOL, "tool_name", None))
17 | document_namespace = document_fixture().creation_info.document_namespace
18 |
19 | payload: Payload = bump_spdx_document(spdx2_document)
20 |
21 | write_payload(payload, sys.stdout)
22 |
23 | assert f"{document_namespace}#SPDXRef-Package" in payload.get_full_map()
24 | assert len(payload.get_full_map()) == 11
25 |
26 | # this is more of a temporary test to make sure the dates don't get messed up again
27 | assert (
28 | payload.get_element("#".join([document_namespace, "SPDXRef-DOCUMENT"])).creation_info.created
29 | == creation_info_fixture().created
30 | )
31 | assert (
32 | payload.get_element("#".join([document_namespace, "SPDXRef-Annotation-0"])).creation_info.created
33 | == annotation_fixture().annotation_date
34 | )
35 |
--------------------------------------------------------------------------------
/tests/spdx3/model/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx3/model/__init__.py
--------------------------------------------------------------------------------
/tests/spdx3/model/licensing/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx3/model/licensing/__init__.py
--------------------------------------------------------------------------------
/tests/spdx3/model/licensing/test_conjunctive_license_set.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx3.model.licensing import ConjunctiveLicenseSet, ListedLicense
7 | from tests.spdx3.fixtures import fixture_factory
8 |
9 |
10 | def test_valid_initialization():
11 | lic = fixture_factory(ListedLicense)
12 | conjunctive_license_set = ConjunctiveLicenseSet([lic, lic])
13 |
14 | assert conjunctive_license_set.member == [lic, lic]
15 |
16 |
17 | def test_invalid_initialization():
18 | lic = fixture_factory(ListedLicense)
19 | with pytest.raises(TypeError) as err:
20 | ConjunctiveLicenseSet(lic)
21 |
22 | assert len(err.value.args[0]) == 1
23 | assert err.value.args[0][0].startswith("SetterError ConjunctiveLicenseSet:")
24 |
--------------------------------------------------------------------------------
/tests/spdx3/model/licensing/test_disjunctive_license_set.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx3.model.licensing import DisjunctiveLicenseSet, ListedLicense
7 | from tests.spdx3.fixtures import fixture_factory
8 |
9 |
10 | def test_valid_initialization():
11 | lic = fixture_factory(ListedLicense)
12 | disjunctive_license_set = DisjunctiveLicenseSet([lic, lic])
13 |
14 | assert disjunctive_license_set.member == [lic, lic]
15 |
16 |
17 | def test_invalid_initialization():
18 | lic = fixture_factory(ListedLicense)
19 | with pytest.raises(TypeError) as err:
20 | DisjunctiveLicenseSet(lic)
21 |
22 | assert len(err.value.args[0]) == 1
23 | assert err.value.args[0][0].startswith("SetterError DisjunctiveLicenseSet:")
24 |
--------------------------------------------------------------------------------
/tests/spdx3/model/licensing/test_or_later_operator.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx3.model.licensing import ListedLicense, OrLaterOperator
7 | from tests.spdx3.fixtures import fixture_factory
8 |
9 |
10 | def test_valid_initialization():
11 | lic = fixture_factory(ListedLicense)
12 | or_later_operator = OrLaterOperator(lic)
13 |
14 | assert or_later_operator.subject_license == lic
15 |
16 |
17 | def test_invalid_initialization():
18 | with pytest.raises(TypeError) as err:
19 | OrLaterOperator("License")
20 |
21 | assert len(err.value.args[0]) == 1
22 | assert err.value.args[0][0].startswith("SetterError OrLaterOperator:")
23 |
--------------------------------------------------------------------------------
/tests/spdx3/model/licensing/test_with_addition_operator.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx3.model.licensing import ListedLicense, ListedLicenseException, WithAdditionOperator
7 | from tests.spdx3.fixtures import fixture_factory
8 |
9 |
10 | def test_valid_initialization():
11 | lic = fixture_factory(ListedLicense)
12 | lic_addition = fixture_factory(ListedLicenseException)
13 | with_addition_operator = WithAdditionOperator(lic, lic_addition)
14 |
15 | assert with_addition_operator.subject_license == lic
16 |
17 |
18 | def test_invalid_initialization():
19 | with pytest.raises(TypeError) as err:
20 | WithAdditionOperator("License", "LicenseAddition")
21 |
22 | assert len(err.value.args[0]) == 2
23 | for arg in err.value.args[0]:
24 | assert arg.startswith("SetterError WithAdditionOperator:")
25 |
--------------------------------------------------------------------------------
/tests/spdx3/model/model_test_utils.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | from typing import Any, List, Type
5 |
6 |
7 | def get_property_names(clazz: Type[Any]) -> List[str]:
8 | return [
9 | attribute
10 | for attribute in dir(clazz)
11 | if not attribute.startswith("_") and not callable(getattr(clazz, attribute))
12 | ]
13 |
14 |
15 | class InvalidTypeClass:
16 | pass
17 |
--------------------------------------------------------------------------------
/tests/spdx3/model/test_abstract_classes.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx3.model import Artifact, Element, ElementCollection, IntegrityMethod
7 |
8 |
9 | @pytest.mark.parametrize("abstract_class", [Element, Artifact, ElementCollection, IntegrityMethod])
10 | def test_initialization_throws_error(abstract_class):
11 | with pytest.raises(TypeError) as err:
12 | abstract_class()
13 |
14 | assert f"Can't instantiate abstract class {abstract_class.__name__}" in err.value.args[0]
15 |
--------------------------------------------------------------------------------
/tests/spdx3/model/test_external_identifier.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx3.model import ExternalIdentifier, ExternalIdentifierType
7 | from tests.spdx3.fixtures import external_identifier_fixture
8 | from tests.spdx3.model.model_test_utils import get_property_names
9 |
10 |
11 | def test_correct_initialization():
12 | external_identifier = external_identifier_fixture()
13 |
14 | for property_name in get_property_names(ExternalIdentifier):
15 | assert getattr(external_identifier, property_name) is not None
16 |
17 | assert external_identifier.external_identifier_type == ExternalIdentifierType.OTHER
18 | assert external_identifier.identifier == "externalIdentifierIdentifier"
19 | assert external_identifier.comment == "externalIdentifierComment"
20 | assert external_identifier.identifier_locator == [
21 | "https://spdx.test/tools-python/external_identifier_identifier_locator"
22 | ]
23 | assert (
24 | external_identifier.issuing_authority == "https://spdx.test/tools-python/external_identifier_issuing_authority"
25 | )
26 |
27 |
28 | def test_invalid_initialization():
29 | with pytest.raises(TypeError) as err:
30 | ExternalIdentifier("CPE22", ["identifier", "another_identifier"], 34, "locator", True)
31 |
32 | assert len(err.value.args[0]) == 5
33 | for error in err.value.args[0]:
34 | assert error.startswith("SetterError ExternalIdentifier:")
35 |
--------------------------------------------------------------------------------
/tests/spdx3/model/test_external_map.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 |
5 | import pytest
6 |
7 | from spdx_tools.spdx3.model import ExternalMap
8 | from tests.spdx3.fixtures import external_map_fixture, hash_fixture
9 | from tests.spdx3.model.model_test_utils import get_property_names
10 |
11 |
12 | def test_correct_initialization():
13 | external_map = external_map_fixture()
14 |
15 | for property_name in get_property_names(ExternalMap):
16 | assert getattr(external_map, property_name) is not None
17 |
18 | assert external_map.external_id == "https://spdx.test/tools-python/external_map_external_id"
19 | assert external_map.verified_using == [hash_fixture()]
20 | assert external_map.location_hint == "https://spdx.test/tools-python/external_map_location_hint"
21 | assert external_map.defining_document == "https://spdx.test/tools-python/defining_document"
22 |
23 |
24 | def test_invalid_initialization():
25 | with pytest.raises(TypeError) as err:
26 | ExternalMap(234, None, ["location hints"])
27 |
28 | assert len(err.value.args[0]) == 2
29 | for error in err.value.args[0]:
30 | assert error.startswith("SetterError ExternalMap:")
31 |
--------------------------------------------------------------------------------
/tests/spdx3/model/test_external_reference.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx3.model import ExternalReference, ExternalReferenceType
7 | from tests.spdx3.fixtures import external_reference_fixture
8 | from tests.spdx3.model.model_test_utils import get_property_names
9 |
10 |
11 | def test_correct_initialization():
12 | external_reference = external_reference_fixture()
13 |
14 | for property_name in get_property_names(ExternalReference):
15 | assert getattr(external_reference, property_name) is not None
16 |
17 | assert external_reference.external_reference_type == ExternalReferenceType.OTHER
18 | assert external_reference.locator == ["org.apache.tomcat:tomcat:9.0.0.M4"]
19 | assert external_reference.content_type == "externalReferenceContentType"
20 | assert external_reference.comment == "externalReferenceComment"
21 |
22 |
23 | def test_invalid_initialization():
24 | with pytest.raises(TypeError) as err:
25 | ExternalReference("OTHER", "a URI", 34, True)
26 |
27 | assert len(err.value.args[0]) == 4
28 | for error in err.value.args[0]:
29 | assert error.startswith("SetterError ExternalReference:")
30 |
--------------------------------------------------------------------------------
/tests/spdx3/model/test_hash.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx3.model import Hash, HashAlgorithm
7 | from tests.spdx3.fixtures import hash_fixture
8 | from tests.spdx3.model.model_test_utils import get_property_names
9 |
10 |
11 | def test_correct_initialization():
12 | hash = hash_fixture()
13 |
14 | for property_name in get_property_names(Hash):
15 | assert getattr(hash, property_name) is not None
16 |
17 | assert hash.algorithm == HashAlgorithm.SHA1
18 | assert hash.hash_value == "71c4025dd9897b364f3ebbb42c484ff43d00791c"
19 | assert hash.comment == "hashComment"
20 |
21 |
22 | def test_invalid_initialization():
23 | with pytest.raises(TypeError) as err:
24 | Hash("SHA1", 345)
25 |
26 | assert len(err.value.args[0]) == 2
27 | for error in err.value.args[0]:
28 | assert error.startswith("SetterError Hash:")
29 |
--------------------------------------------------------------------------------
/tests/spdx3/model/test_namespace_map.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import pytest
5 |
6 | from spdx_tools.spdx3.model import NamespaceMap
7 | from tests.spdx3.fixtures import namespace_map_fixture
8 | from tests.spdx3.model.model_test_utils import get_property_names
9 |
10 |
11 | def test_correct_initialization():
12 | namespace_map = namespace_map_fixture()
13 |
14 | for property_name in get_property_names(NamespaceMap):
15 | assert getattr(namespace_map, property_name) is not None
16 |
17 | assert namespace_map.prefix == "namespaceMapPrefix"
18 | assert namespace_map.namespace == "https://spdx.test/tools-python/namespace_map_namespace"
19 |
20 |
21 | def test_invalid_initialization():
22 | with pytest.raises(TypeError) as err:
23 | NamespaceMap(34, ["list of namespaces"])
24 |
25 | assert len(err.value.args[0]) == 2
26 | for error in err.value.args[0]:
27 | assert error.startswith("SetterError NamespaceMap:")
28 |
--------------------------------------------------------------------------------
/tests/spdx3/validation/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx3/validation/__init__.py
--------------------------------------------------------------------------------
/tests/spdx3/validation/json_ld/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx3/validation/json_ld/__init__.py
--------------------------------------------------------------------------------
/tests/spdx3/validation/json_ld/test_shacl_validation.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import os
5 |
6 | import pytest
7 |
8 | from spdx_tools.spdx3.validation.json_ld.shacl_validation import validate_against_shacl_from_file
9 |
10 |
11 | @pytest.mark.skip("Currently the validation against SHACL fails, refer to process.md and the known limitations.")
12 | def test_shacl_validation():
13 | # insert path to example json ld
14 | conforms, results_graph, results_text = validate_against_shacl_from_file(
15 | data_file=os.path.join(os.path.dirname(__file__), "../../../SPDX3_jsonld_test.jsonld"),
16 | shacl_file=os.path.join(
17 | os.path.dirname(__file__), "../../../../src/spdx_tools/spdx3/writer/json_ld/model.ttl"
18 | ),
19 | )
20 | # results_graph.serialize("validation_result.rdf.xml", format="pretty-xml")
21 | print(results_text)
22 | assert conforms
23 |
--------------------------------------------------------------------------------
/tests/spdx3/writer/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx3/writer/__init__.py
--------------------------------------------------------------------------------
/tests/spdx3/writer/json_ld/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spdx/tools-python/8dc336f783e993d7e347d20b8ecd50b8808abf70/tests/spdx3/writer/json_ld/__init__.py
--------------------------------------------------------------------------------
/tests/spdx3/writer/json_ld/test_json_ld_writer.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2023 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import os
5 |
6 | from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document
7 | from spdx_tools.spdx3.payload import Payload
8 | from spdx_tools.spdx3.writer.json_ld.json_ld_writer import write_payload
9 | from spdx_tools.spdx.model.document import Document as Spdx2_Document
10 | from tests.spdx.fixtures import document_fixture
11 |
12 |
13 | def test_json_writer():
14 | spdx2_document: Spdx2_Document = document_fixture()
15 | payload: Payload = bump_spdx_document(spdx2_document)
16 |
17 | # this currently generates an actual file to look at, this should be changed to a temp file later
18 | write_payload(payload, os.path.join(os.path.dirname(__file__), "../../../SPDX3_jsonld_test"))
19 |
--------------------------------------------------------------------------------
/tests/spdx3/writer/tag_value/test_write_document.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: 2024 spdx contributors
2 | #
3 | # SPDX-License-Identifier: Apache-2.0
4 | import io
5 | from datetime import datetime
6 |
7 | from semantic_version import Version
8 |
9 | from spdx_tools.spdx3.model import CreationInfo, ProfileIdentifierType, SpdxDocument
10 | from spdx_tools.spdx3.writer.console.spdx_document_writer import write_spdx_document
11 |
12 |
13 | def test_render_creation_info():
14 | fake_datetime = datetime(year=2024, month=1, day=1)
15 | spec_version = Version("3.0.0")
16 | creation_info = CreationInfo(
17 | spec_version=spec_version,
18 | created=fake_datetime,
19 | created_by=[],
20 | profile=[ProfileIdentifierType.SOFTWARE],
21 | )
22 | spdx_document = SpdxDocument(
23 | spdx_id="SPDXRef-FOO",
24 | name="BAR",
25 | element=[],
26 | root_element=[],
27 | creation_info=creation_info,
28 | )
29 | output_str = io.StringIO()
30 | write_spdx_document(spdx_document, text_output=output_str)
31 |
32 | assert (
33 | output_str.getvalue()
34 | == """\
35 | ## SPDX Document
36 | SPDXID: SPDXRef-FOO
37 | name: BAR
38 | # Creation Information
39 | specVersion: 3.0.0
40 | created: 2024-01-01T00:00:00Z
41 | profile: SOFTWARE
42 | data license: CC0-1.0
43 | elements:
44 | """ # noqa: W291 # elements: are printed with a space
45 | )
46 |
--------------------------------------------------------------------------------