Skip to content

Commit

Permalink
Migrate from records to specs with validation (#148)
Browse files Browse the repository at this point in the history
  • Loading branch information
pilosus authored Apr 28, 2023
1 parent 26f4a52 commit cff164f
Show file tree
Hide file tree
Showing 24 changed files with 821 additions and 368 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ This change log follows the conventions of [keepachangelog.com](http://keepachan

## [Unreleased]

## [0.48.0] - 2023-04-28

### Changed
- Code refactoing to remove `defrecord` in favour of
[clojure.spec.alpha](https://clojure.org/guides/spec)

## [0.47.0] - 2023-04-14

### Changed
Expand Down Expand Up @@ -460,7 +466,8 @@ weak copyleft types.
### Added
- Structure for Leiningen app project

[Unreleased]: https://github.com/pilosus/pip-license-checker/compare/0.47.0...HEAD
[Unreleased]: https://github.com/pilosus/pip-license-checker/compare/0.48.0...HEAD
[0.48.0]: https://github.com/pilosus/pip-license-checker/compare/0.47.0...0.48.0
[0.47.0]: https://github.com/pilosus/pip-license-checker/compare/0.46.1...0.47.0
[0.46.1]: https://github.com/pilosus/pip-license-checker/compare/0.46.0...0.46.1
[0.46.0]: https://github.com/pilosus/pip-license-checker/compare/0.45.0...0.46.0
Expand Down
7 changes: 5 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,15 @@ dicussed on the code review).

### Release management

#### Checlist
#### Checklist

1. Follow the [SemVer](https://semver.org/) conventions for the release number.
2. Update the [project version](https://github.com/pilosus/pip-license-checker/blob/main/project.clj).
3. Update the [CHANGELOG](https://github.com/pilosus/action-pip-license-checker/blob/main/CHANGELOG.md).
4. Update the [README](https://github.com/pilosus/action-pip-license-checker/blob/main/README.md) if needed.
4. Update the [README](https://github.com/pilosus/action-pip-license-checker/blob/main/README.md) if needed:
- check if the `Help` section is in line with `lein run` output, especially if CLI options are updated
- check if versions mentioned in the text are still relevant

5. Merge the changes to the `main` branch.
6. Push a version-specific tag, e.g. `2.1.9`:

Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ Description:
--external-format FILE_FORMAT csv External file format: csv, cocoapods, gradle
--external-options OPTS_EDN_STRING {:skip-header true, :skip-footer true} String of options map in EDN format
--report-format FORMAT stdout Report format: stdout, json, json-pretty, csv
--formatter PRINTF_FMT %-35s %-55s %-20s Printf-style formatter string for stdout report formatting
--formatter PRINTF_FMT %-35s %-55s %-20s %-40s Printf-style formatter string for stdout report formatting
-f, --fail LICENSE_TYPE #{} Return non-zero exit code if license type is found
-e, --exclude REGEX PCRE to exclude packages with matching names
--exclude-license REGEX PCRE to exclude packages with matching license names
Expand Down Expand Up @@ -199,7 +199,8 @@ pip-license-checker -r resources/requirements.github.txt --github-token your-tok
pip-license-checker -x resources/external.csv --exclude-license '(?i).*(?:mit|bsd).*'
pip-license-checker -x resources/external.csv --external-options '{:skip-header false}'
pip-license-checker -x resources/external.cocoapods --external-format cocoapods'
pip-license-checker -x resources/external.edn --external-format edn --formatter '%-70s %-60s %-35s'
pip-license-checker -x resources/external.edn --external-format edn --formatter '%-70s %-60s %-35s %-40s'
pip-license-checker -r resources/requirements.txt --report-format 'json-pretty' --totals --headers -vvv
```
### License types
Expand Down
8 changes: 6 additions & 2 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(defproject org.pilosus/pip-license-checker "0.47.0"
(defproject org.pilosus/pip-license-checker "0.48.0"
:description "License compliance tool to identify dependencies license names and types: permissive, copyleft, proprietory, etc."
:url "https://github.com/pilosus/pip-license-checker"
:license {:name "Eclipse Public License 2.0 OR GNU GPL v2+ with Classpath exception"
Expand All @@ -21,9 +21,13 @@
:aot [pip-license-checker.core]
:target-path "target/%s"
:profiles {:uberjar {:aot :all
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}}
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}
:test {:cloverage {:fail-threshold 80
:exclude-call [clojure.spec.alpha/assert
clojure.spec.alpha/def]}}}
:test-selectors {:integration :integration
:cli :cli}
:cljfmt {:sort-ns-references? true}
:repositories [["releases" {:url "https://repo.clojars.org"
:sign-releases false
:username :env/clojars_username
Expand Down
21 changes: 13 additions & 8 deletions src/pip_license_checker/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,17 @@
(:gen-class)
(:require
[clojure.set :refer [intersection]]
[clojure.spec.alpha :as s]
[clojure.string :as str]
[clojure.tools.cli :refer [parse-opts]]
[pip-license-checker.data :as d]
[pip-license-checker.external :as external]
[pip-license-checker.file :as file]
[pip-license-checker.filters :as filters]
[pip-license-checker.license :as license]
[pip-license-checker.logging :as logging]
[pip-license-checker.pypi :as pypi]
[pip-license-checker.report :as report]))
[pip-license-checker.report :as report]
[pip-license-checker.spec :as sp]))

;; helpers

Expand All @@ -53,7 +54,8 @@
"Remove unused keys from dependency record"
[dep options]
(let [misc (logging/format-logs (:logs dep) options)]
(d/map->ReportItem
(s/assert
::sp/report-item
{:dependency (select-keys (:requirement dep) [:name :version])
:license (select-keys (:license dep) [:name :type])
:misc misc})))
Expand All @@ -77,10 +79,12 @@
(into (sorted-set))
(intersection (:fail options))
seq)]
(d/map->Report {:headers report/report-headers
:items items
:totals totals
:fails fails})))
(s/assert
::sp/report
{:headers report/report-headers
:items items
:totals totals
:fails fails})))

(defn shutdown
"Shutdown the app gracefully"
Expand Down Expand Up @@ -120,7 +124,8 @@
"pip-license-checker -x resources/external.csv --exclude-license '(?i).*(?:mit|bsd).*'"
"pip-license-checker -x resources/external.csv --external-options '{:skip-header false}'"
"pip-license-checker -x resources/external.cocoapods --external-format cocoapods'"
"pip-license-checker -x resources/external.edn --external-format edn --formatter '%-70s %-60s %-35s'"]
"pip-license-checker -x resources/external.edn --external-format edn --formatter '%-70s %-60s %-35s %-40s'"
"pip-license-checker -r resources/requirements.txt --report-format 'json-pretty' --totals --headers -vvv"]
(str/join \newline)))

(defn error-msg [errors]
Expand Down
83 changes: 0 additions & 83 deletions src/pip_license_checker/data.clj

This file was deleted.

10 changes: 6 additions & 4 deletions src/pip_license_checker/external.clj
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
(:gen-class)
(:require
[clojure.edn :as edn]
[clojure.spec.alpha :as s]
[clojure.string :as str]
[pip-license-checker.data :as d]
[pip-license-checker.file :as file]
[pip-license-checker.filters :as filters]
[pip-license-checker.license :as license]))
[pip-license-checker.license :as license]
[pip-license-checker.spec :as sp]))

(def regex-version-separator #"(@|:)")

Expand Down Expand Up @@ -65,7 +66,7 @@
splitted? (> (count split) 1)
version (if splitted? (last split) nil)
name (if splitted? (str/join (butlast split)) (first split))]
(d/map->Requirement {:name name :version version})))
(s/assert ::sp/requirement {:name name :version version})))

(defn license-name->map
"Format license name into a license record"
Expand All @@ -75,7 +76,8 @@
(defn external-obj->dep
"Format object parsed from external file into dependency object"
[{:keys [package license]}]
(d/map->Dependency
(s/assert
::sp/dependency
{:requirement (package-name->requirement package)
:license (license-name->map license)
:logs (:logs license)}))
Expand Down
11 changes: 7 additions & 4 deletions src/pip_license_checker/github.clj
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
(:gen-class)
(:require
[cheshire.core :as json]
[clojure.spec.alpha :as s]
[clojure.string :as str]
[pip-license-checker.data :as d]
[pip-license-checker.http :as http]
[pip-license-checker.logging :as l]))
[pip-license-checker.logging :as l]
[pip-license-checker.spec :as sp]))

(def url-github-base "https://api.github.com/repos")

Expand Down Expand Up @@ -71,7 +72,7 @@
:body
json/parse-string
(get-in ["license" "name"]))]
(d/map->License {:name license-name :type nil :logs logs})))
(s/assert ::sp/license {:name license-name :type nil :logs logs})))

(defn homepage->license
"Get license name from homepage if it's a GitHub URL"
Expand All @@ -83,5 +84,7 @@
url-valid? (= 3 (count github-url))
license (if url-valid?
(api-get-license github-url options rate-limiter)
(d/->License nil nil [meta-not-found]))]
(s/assert
::sp/license
{:name nil :type nil :logs [meta-not-found]}))]
license))
30 changes: 22 additions & 8 deletions src/pip_license_checker/license.clj
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
"Licenses constants"
(:gen-class)
(:require
[clojure.spec.alpha :as s]
[clojure.string :as str]
[pip-license-checker.data :as d]))
[pip-license-checker.spec :as sp]))

;; Lincense regex

Expand Down Expand Up @@ -279,14 +280,23 @@
;; Do not add logs here as they are excessive
;; NPE is caught when license is nil,
;; i.e. there were other reasons why license name is absent
(def license-error (d/->License name-error type-error nil))
(def license-error
(s/assert
::sp/license
{:name name-error
:type type-error
:logs nil}))

;; Functions

(defn get-license-error
"Get license object of error type"
[ex]
(d/->License name-error type-error ex))
(s/assert
::sp/license
{:name name-error
:type type-error
:logs ex}))

(defn is-type-valid?
"Return true if license-type string is valid, false otherwise"
Expand Down Expand Up @@ -314,10 +324,14 @@
regex-permissive (strings->pattern regex-list-permissive)
match-permissive (some? (re-find regex-permissive name))]
(cond
match-copyleft-network (d/->License name type-copyleft-network nil)
match-copyleft-strong (d/->License name type-copyleft-strong nil)
match-copyleft-weak (d/->License name type-copyleft-weak nil)
match-permissive (d/->License name type-permissive nil)
:else (d/->License name type-other nil)))
match-copyleft-network
(s/assert ::sp/license {:name name :type type-copyleft-network :logs nil})
match-copyleft-strong
(s/assert ::sp/license {:name name :type type-copyleft-strong :logs nil})
match-copyleft-weak
(s/assert ::sp/license {:name name :type type-copyleft-weak :logs nil})
match-permissive
(s/assert ::sp/license {:name name :type type-permissive :logs nil})
:else (s/assert ::sp/license {:name name :type type-other :logs nil})))
(catch NullPointerException _
license-error)))
Loading

0 comments on commit cff164f

Please sign in to comment.