Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial implementation #1

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
name: Test SPDX Go Bindings
on:
- push
- pull_request
- workflow_call

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
go-version:
- "1.18"
- "1.19"
- "1.20"
- "1.21"
- "1.22"
- "1.23"
steps:
- uses: actions/checkout@v4
- name: Setup Go ${{ matrix.go-version }}
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Install dependencies
run: go get .
- name: Run tests
run: go test -v
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.bak
*.tmp
*.swp
*~

*.json
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,40 @@
# spdx-go-model-3

Generated Golang code for the SPDX Spec version 3

All bindings in this repository are generated using
[shacl2code](https://github.com/JPEWdev/shacl2code) at the time the package is
built with the `generate-bindings` script. The binding should not be manually
edited.

**NOTE:** The bindings are pretty low level, intended for more directly
manipulating SPDX files. While they are fully functions, they lack higher level
helper functions that may be useful for creating SPDX documents. If you want a
higher level approach, please see the
[SPDX Golang Tools](https://github.com/spdx/tools-golang) (however this repo
doesn't yet support SPDX 3)

## Usage

Each version of the SPDX spec has a module named `v{MAJOR}_{MINOR}_{MICRO}`
that contains the bindings for that version under the `github.com/spdx/spdx-go-model`
top level modules. It is recommend you import this with an alias like:

```golang
import (
"github.com/spdx/spdx-go-model/spdx_v3_0_1"
)

...
p := spdx_v3_0_1.MakePerson()
...
```

## Examples

For examples of how to use the bindings, see the `examples_test.go` file

## Testing

This repository has support for running tests against the generated bindings using
`go test`.
65 changes: 65 additions & 0 deletions examples_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package spdx_go_test

import (
"encoding/json"
"os"
"testing"
"time"

"github.com/spdx/spdx-go-model/spdx_v3_0_1"
)

func TestImport(t *testing.T) {
spdx_v3_0_1.MakePerson()
}

func TestExample(t *testing.T) {
// Create a new Person
p := spdx_v3_0_1.MakePerson()

// Set the unique identifier (IRI) for the person
p.ID().Set("http://spdx.org/spdxdocs/person-example")

// Set the name for the person
p.Name().Set("Joshua")

// Create a creation info object
ci := spdx_v3_0_1.MakeCreationInfo()
ci.SpecVersion().Set("3.0.1")
ci.Created().Set(time.Now())
Comment on lines +21 to +29

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid Unnecessary Getters

  • Instead of using p.ID().Set(value), use p.SetID(value),
  • Similarly, p.Name().Set(value), use p.SetName(value)
  • Similarly, ci.SpecVersion().Set(value), use ci.SetSpecVersion(value)
  • and, ci.Created().Set(valu), use ci.SetCreated(value)

Something like this: https://go.dev/play/p/tREj7_5eQFN

You can checkout these resources to understand more about getter and setter in go:


// Set the person as the creator of the SPDX data
ci.CreatedBy().AppendObj(p)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use append() for Slices Instead of Custom Methods.

  • Instead of ci.CreatedBy().AppendObj(p), use ci.CreatedBy = append(ci.CreatedBy, p).

The built-in append function is the idiomatic way to work with slices in Go.


// Set the creation info as the creation info of the Person
p.CreationInfo().SetObj(ci)

// Add an e-mail address for the person
email := spdx_v3_0_1.MakeExternalIdentifier()
email.ExternalIdentifierType().Set(spdx_v3_0_1.ExternalIdentifierTypeEmail)
email.Identifier().Set("[email protected]")
Comment on lines +39 to +40

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly here: Avoid Unnecessary Getter/Setter Chaining:

Refractor it to:

email.SetExternalIdentifierType(spdx_v3_0_1.ExternalIdentifierTypeEmail)
email.SetIdentifier("[email protected]")

p.ExternalIdentifier().AppendObj(email)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly avoid AppendObj and simply refractor it to:

p.ExternalIdentifiers = append(p.ExternalIdentifiers, email)


// Create a SPDX Document object
doc := spdx_v3_0_1.MakeSpdxDocument()
doc.ID().Set("http://spdx.org/spdxdocs/doc-example")
doc.CreationInfo().SetObj(ci)
Comment on lines +45 to +46

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly these one, as per above suggested to avoid getter.

  • Instead of doc.CreationInfo.Set(value), use doc.SetCreationInfo(ci), and
  • doc.ID().Set(value), by doc.SetID(value)

Refractor with:

func (d *SpdxDocument) SetCreationInfo(ci CreationInfo) {
    d.CreationInfo = ci
}

and

func (d *SpdxDocument) SetID(id string) {
    d.SetID = id
}


// Add the document and person to an object set and serialize
objset := spdx_v3_0_1.NewSHACLObjectSet()
objset.AddObject(p)
objset.AddObject(doc)
Comment on lines +50 to +51

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this, if it is internally appending an objects as name suggest, AddObject, then instead of that use a simple append().
Refractor it as:

objset.Objects = append(objset.Objects, p, doc)


file, err := os.Create("out.json")
if err != nil {
t.Error(err)
return
}
defer file.Close()

encoder := json.NewEncoder(file)
if err := objset.Encode(encoder); err != nil {
t.Error(err)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensures test execution stops immediately when a failure occurs.

  • t.Error(err) will continue test even after errors
  • whereas, t.Fatal(err), will stops execution test upon failure.

So, refractor this too:

if err != nil {
    t.Fatal(err) // Terminates test immediately
}

return
}
}
39 changes: 39 additions & 0 deletions generate-bindings
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#! /bin/sh
#
# SPDX-License-Identifier: Apache-2.0

set -eu

SPDX_VERSIONS="3.0.1"
SHACL2CODE_VERSION="0.0.19"

THIS_DIR="$(dirname "$0")"
VENV_DIR="$(mktemp -d)"

cd $THIS_DIR

# Install shacl2code in a virtual environment
python3 -m venv "$VENV_DIR"
"$VENV_DIR/bin/pip" install -q "shacl2code==$SHACL2CODE_VERSION"
SHACL2CODE="$VENV_DIR/bin/shacl2code"

# Remove existing go files in subdirectories
find . -path './*/*.go' -delete

for v in $SPDX_VERSIONS; do
MODNAME="spdx_v$(echo "$v" | sed 's/[^a-zA-Z0-9_]/_/g')"
rm -rf "$MODNAME"
mkdir -p "$MODNAME"

"$SHACL2CODE" generate \
--input https://spdx.org/rdf/$v/spdx-model.ttl \
--input https://spdx.org/rdf/$v/spdx-json-serialize-annotations.ttl \
--context https://spdx.org/rdf/$v/spdx-context.jsonld \
--license Apache-2.0 \
golang \
-o "$MODNAME" -p "$MODNAME"
done

go mod tidy

rm -rf "$VENV_DIR"
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/spdx/spdx-go-model

go 1.18

require github.com/ncruces/go-strftime v0.1.9
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
Loading