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

Make the code work on Julia 1.3 #8

Merged
merged 3 commits into from
Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
fail-fast: false
matrix:
version:
- '1.5'
- '1.3'
- '1'
- 'nightly'
os:
Expand Down
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
name = "LicenseCheck"
uuid = "726dbf0d-6eb6-41af-b36c-cd770e0f00cc"
authors = ["Eric P. Hanson"]
version = "0.2.1"
version = "0.2.2"

[deps]
licensecheck_jll = "4ecb348a-8b88-51ea-b912-4c460483ee91"

[compat]
julia = "1.5"
julia = "1.3"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
4 changes: 1 addition & 3 deletions generate_osi_list/generate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ spdx = JSON3.read(String(r.body))

@assert spdx.licenseListVersion == "3.10"

osi_licenses = sort!([lic.licenseId
for lic in spdx.licenses
if lic.isOsiApproved])
osi_licenses = sort!([lic.licenseId for lic in spdx.licenses if lic.isOsiApproved])

open(joinpath(@__DIR__, "..", "src", "OSI_LICENSES.jl"); write=true) do io
header = """
Expand Down
16 changes: 10 additions & 6 deletions src/LicenseCheck.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ using licensecheck_jll: licensecheck_jll

export licensecheck, is_osi_approved
export find_licenses, find_license
export find_licenses_by_bruteforce, find_licenses_by_list, find_licenses_by_list_intersection
export find_licenses_by_bruteforce, find_licenses_by_list,
find_licenses_by_list_intersection

include("OSI_LICENSES.jl")
include("find_licenses.jl")
Expand All @@ -30,11 +31,12 @@ julia> licensecheck(text)
```
"""
function licensecheck(text::String)
arr, dims, license_file_percent_covered = ccall((:License, licensecheck_jll.licensecheck),
Tuple{Ptr{Ptr{UInt8}},Cint,Float64}, (Cstring,),
text)
arr, dims, license_file_percent_covered = ccall((:License,
licensecheck_jll.licensecheck),
Tuple{Ptr{Ptr{UInt8}},Cint,Float64},
(Cstring,), text)
return (; licenses_found=unsafe_string.(unsafe_wrap(Array, arr, dims; own=true)),
license_file_percent_covered)
license_file_percent_covered=license_file_percent_covered)
end

"""
Expand Down Expand Up @@ -67,7 +69,9 @@ false
```
"""
is_osi_approved(spdx_identifier::String) = spdx_identifier ∈ OSI_LICENSES
is_osi_approved(nt::NamedTuple) = !isempty(nt.licenses_found) && all(is_osi_approved, nt.licenses_found)
function is_osi_approved(nt::NamedTuple)
return !isempty(nt.licenses_found) && all(is_osi_approved, nt.licenses_found)
end
is_osi_approved(::Nothing) = false # so that it can always be used with `find_license`

end # module
28 changes: 16 additions & 12 deletions src/find_licenses.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# is the `APL-1.0` license which is 45 KB.
# We take a factor of 10 larger, to allow for
# compound licenses.
const MAX_LICENSE_SIZE_IN_BYTES = 45958*10
const MAX_LICENSE_SIZE_IN_BYTES = 45958 * 10

# Based on
# https://github.com/ericphanson/LicenseCheck.jl/issues/2#issue-805995984
Expand All @@ -11,20 +11,23 @@ const LICENSE_NAMES = let
name_cases = (uppercase, uppercasefirst, lowercase)
ext_cases = (uppercase, lowercase)
extensions = (".md", ".txt", "", ".rst")
Set(string(case(name), extcase(ext)) for name in names, case in name_cases, ext in extensions, extcase in ext_cases)
Set(string(case(name), extcase(ext))
for name in names, case in name_cases, ext in extensions, extcase in ext_cases)
end

# only ~500 items this way
const LOWERCASE_LICENSE_NAMES = Set(lowercase(lic) for lic in LICENSE_NAMES)

const LICENSE_TABLE_TYPE = Vector{@NamedTuple{license_filename::String, licenses_found::Vector{String}, license_file_percent_covered::Float64}}
const LICENSE_TABLE_TYPE = Vector{NamedTuple{(:license_filename, :licenses_found,
:license_file_percent_covered),
Tuple{String,Vector{String},Float64}}}
const LICENSE_TABLE_TYPE_STRING = "Vector{@NamedTuple{license_filename::String, licenses_found::Vector{String}, license_file_percent_covered::Float64}}"

# like `readdir`, but returns only files
readfiles(dir) = filter!(f -> isfile(joinpath(dir, f)), readdir(dir))

# constructs a table of `licensecheck` results
function license_table(dir, names; validate_strings = true, validate_paths = true)
function license_table(dir, names; validate_strings=true, validate_paths=true)
table = LICENSE_TABLE_TYPE()
for lic in names
path = joinpath(dir, lic)
Expand All @@ -38,7 +41,7 @@ function license_table(dir, names; validate_strings = true, validate_paths = tru
push!(table, (; license_filename=lic, lc...))
end
end
sort!(table; by = x -> x.license_file_percent_covered, rev=true)
sort!(table; by=x -> x.license_file_percent_covered, rev=true)
return table
end

Expand All @@ -54,9 +57,9 @@ Operates by filtering the results of `readdir`, which should be efficient
for small and moderately sized directories. See [`find_licenses_by_list`](@ref)
for an alternate approach for very large directories.
"""
function find_licenses_by_list_intersection(dir; files = readfiles(dir))
function find_licenses_by_list_intersection(dir; files=readfiles(dir))
names = filter!(lic -> lowercase(lic) ∈ LOWERCASE_LICENSE_NAMES, files)
return license_table(dir, names; validate_paths = false)
return license_table(dir, names; validate_paths=false)
end

"""
Expand All @@ -82,9 +85,10 @@ find_licenses_by_list(dir) = license_table(dir, LICENSE_NAMES)
Calls [`licensecheck`](@ref) on every plaintext file in `dir` whose size is less than `max_bytes`,
returning the results as a table. The parameter `max_bytes` defaults to $(MAX_LICENSE_SIZE_IN_BYTES ÷ 1000) KiB.
"""
function find_licenses_by_bruteforce(dir; max_bytes = MAX_LICENSE_SIZE_IN_BYTES, files = readfiles(dir))
function find_licenses_by_bruteforce(dir; max_bytes=MAX_LICENSE_SIZE_IN_BYTES,
files=readfiles(dir))
names = filter!(file -> stat(joinpath(dir, file)).size < max_bytes, files)
return license_table(dir, names; validate_paths = false)
return license_table(dir, names; validate_paths=false)
end

const CUTOFF = 100
Expand All @@ -106,12 +110,12 @@ julia> find_licenses(".")

```
"""
function find_licenses(dir; allow_brute=true, max_bytes = MAX_LICENSE_SIZE_IN_BYTES)
function find_licenses(dir; allow_brute=true, max_bytes=MAX_LICENSE_SIZE_IN_BYTES)
files = readfiles(dir)
if allow_brute && (length(files) < CUTOFF)
return find_licenses_by_bruteforce(dir; files, max_bytes)
return find_licenses_by_bruteforce(dir; files=files, max_bytes=max_bytes)
else
return find_licenses_by_list_intersection(dir; files)
return find_licenses_by_list_intersection(dir; files=files)
end
end

Expand Down
28 changes: 18 additions & 10 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
using LicenseCheck
using Test

if VERSION < v"1.4"
# backport a simple version of `only`
only(x) = (length(x) == 1 || error("Must have 1 element!"); first(x))
end

MIT = """
MIT License Copyright (c) <year> <copyright holders>

Expand Down Expand Up @@ -70,35 +75,36 @@ dorian_gray = """

result = licensecheck(MIT * "\n" * dorian_gray)
@test result.licenses_found == ["MIT"]
@test result.license_file_percent_covered ≈ 100 * length(MIT) / (length(dorian_gray) + length(MIT)) atol = 5
@test result.license_file_percent_covered ≈
100 * length(MIT) / (length(dorian_gray) + length(MIT)) atol = 5

result = licensecheck(MIT * "\n" * dorian_gray * "\n" * Latex2e)
@test result.licenses_found == ["MIT", "Latex2e"]
@test result.license_file_percent_covered ≈
100 * (length(MIT) + length(Latex2e)) /
(length(dorian_gray) + length(MIT) + length(Latex2e)) atol = 5
100 * (length(MIT) + length(Latex2e)) /
(length(dorian_gray) + length(MIT) + length(Latex2e)) atol = 5
end

@testset "`is_osi_approved`" begin
@test is_osi_approved("MIT") == true
@test is_osi_approved("LGPL-3.0") == true
@test is_osi_approved("ABC") == false

@test is_osi_approved(find_license(pkgdir(LicenseCheck))) == true
VERSION >= v"1.5" &&
@test is_osi_approved(find_license(pkgdir(LicenseCheck))) == true
@test !is_osi_approved(nothing) # for if `find_license` returns `nothing`
@test is_osi_approved((; licenses_found = ["MIT", "MIT"]))
@test !is_osi_approved((; licenses_found = String[]))
@test is_osi_approved((; licenses_found=["MIT", "MIT"]))
@test !is_osi_approved((; licenses_found=String[]))
end


@testset "`find_licenses_*`" begin
fl = find_license(joinpath(@__DIR__, ".."))
# check it found the right one
@test fl.license_filename == "LICENSE"
@test fl.licenses_found == ["MIT"]
@test fl.license_file_percent_covered > 90

for method in (find_licenses, dir -> find_licenses(dir; allow_brute=false), find_licenses_by_bruteforce, find_licenses_by_list_intersection)
for method in (find_licenses, dir -> find_licenses(dir; allow_brute=false),
find_licenses_by_bruteforce, find_licenses_by_list_intersection)
results = method(joinpath(@__DIR__, ".."))
@test only(results) == fl
end
Expand All @@ -113,6 +119,8 @@ dorian_gray = """
@test fl.license_filename == "LICENSE"
@test fl.licenses_found == ["MIT"]
@test fl.license_file_percent_covered > 90
@test_throws ArgumentError LicenseCheck.license_table("nul_string_dir", ["file_with_nul_in_the_middle.txt"]; validate_strings = false)
@test_throws ArgumentError LicenseCheck.license_table("nul_string_dir",
["file_with_nul_in_the_middle.txt"];
validate_strings=false)
end
end