From d77f47314ec022d02ee02ff005ab7e0ec45321aa Mon Sep 17 00:00:00 2001 From: Caleb Courier Date: Fri, 14 Mar 2025 08:26:36 -0500 Subject: [PATCH 01/12] update to jsonschema's format-nongpl extra --- poetry.lock | 21 +++------------------ pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/poetry.lock b/poetry.lock index e4df2a28d..bcefc666c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2852,13 +2852,9 @@ jsonschema-specifications = ">=2023.03.6" referencing = ">=0.28.4" rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} -rfc3987 = {version = "*", optional = true, markers = "extra == \"format\""} rpds-py = ">=0.7.1" uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -webcolors = [ - {version = ">=1.11", optional = true, markers = "extra == \"format\""}, - {version = ">=24.6.0", optional = true, markers = "extra == \"format-nongpl\""}, -] +webcolors = {version = ">=24.6.0", optional = true, markers = "extra == \"format-nongpl\""} [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] @@ -6927,24 +6923,13 @@ idna2008 = ["idna"] name = "rfc3986-validator" version = "0.1.1" description = "Pure python rfc3986 validator" -optional = true +optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ {file = "rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9"}, {file = "rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055"}, ] -[[package]] -name = "rfc3987" -version = "1.3.8" -description = "Parsing and validation of URIs (RFC 3986) and IRIs (RFC 3987)" -optional = false -python-versions = "*" -files = [ - {file = "rfc3987-1.3.8-py2.py3-none-any.whl", hash = "sha256:10702b1e51e5658843460b189b185c0366d2cf4cff716f13111b0ea9fd2dce53"}, - {file = "rfc3987-1.3.8.tar.gz", hash = "sha256:d3c4d257a560d544e9826b38bc81db676890c79ab9d7ac92b39c7a253d5ca733"}, -] - [[package]] name = "rich" version = "13.9.2" @@ -9050,4 +9035,4 @@ vectordb = ["faiss-cpu", "numpy"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "8aca97beee32617c22bb953722ff36173e8895e009892b22e0c130081cbebc72" +content-hash = "16f6caf6623a54ef9e609fe3eacf27393825d204277efbfd46c18969d28d63fc" diff --git a/pyproject.toml b/pyproject.toml index 9ee323de7..bc5a798f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ requests = "^2.31.0" faker = "^25.2.0" jsonref = "^1.1.0" jsonformer = {version = "0.12.0", optional = true} -jsonschema = {version = "^4.22.0", extras = ["format"]} +jsonschema = {version = "^4.22.0", extras = ["format-nongpl"]} pip = ">=22" pyjwt = "^2.8.0" opentelemetry-sdk = "^1.24.0" From dca2aff0e21b9ffa2a3cb15aa99bb1c9f1b30a6e Mon Sep 17 00:00:00 2001 From: Caleb Courier Date: Fri, 14 Mar 2025 10:04:41 -0500 Subject: [PATCH 02/12] add allowed license config; add license checks to PR checks --- .github/workflows/ci.yml | 27 +++++++++++++++++ poetry.lock | 62 ++++++++++++++++++++++++++++++++++++++-- pyproject.toml | 56 +++++++++++++++++++++++++++++++++++- 3 files changed, 141 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 881dda180..6338e0ffe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,33 @@ on: workflow_dispatch: jobs: + LicenseChecks: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12"] + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Poetry + uses: snok/install-poetry@v1 + + - name: Install Dependencies + # TODO: fix errors so that we can run `make dev` instead + run: | + # Setup Virtual Environment + python3 -m venv ./.venv + source .venv/bin/activate + make full + + - name: Check license + run: | + source .venv/bin/activate + liccheck Linting: runs-on: ubuntu-latest strategy: diff --git a/poetry.lock b/poetry.lock index bcefc666c..08a9244e8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2852,9 +2852,13 @@ jsonschema-specifications = ">=2023.03.6" referencing = ">=0.28.4" rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} +rfc3987 = {version = "*", optional = true, markers = "extra == \"format\""} rpds-py = ">=0.7.1" uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -webcolors = {version = ">=24.6.0", optional = true, markers = "extra == \"format-nongpl\""} +webcolors = [ + {version = ">=1.11", optional = true, markers = "extra == \"format\""}, + {version = ">=24.6.0", optional = true, markers = "extra == \"format-nongpl\""}, +] [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] @@ -3364,6 +3368,21 @@ pydantic = [ requests = ">=2,<3" requests-toolbelt = ">=1.0.0,<2.0.0" +[[package]] +name = "liccheck" +version = "0.9.2" +description = "Check python packages from requirement.txt and report issues" +optional = false +python-versions = ">=3.5" +files = [ + {file = "liccheck-0.9.2-py2.py3-none-any.whl", hash = "sha256:15cbedd042515945fe9d58b62e0a5af2f2a7795def216f163bb35b3016a16637"}, + {file = "liccheck-0.9.2.tar.gz", hash = "sha256:bdc2190f8e95af3c8f9c19edb784ba7d41ecb2bf9189422eae6112bf84c08cd5"}, +] + +[package.dependencies] +semantic-version = ">=2.7.0" +toml = "*" + [[package]] name = "litellm" version = "1.50.1" @@ -6923,13 +6942,24 @@ idna2008 = ["idna"] name = "rfc3986-validator" version = "0.1.1" description = "Pure python rfc3986 validator" -optional = false +optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ {file = "rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9"}, {file = "rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055"}, ] +[[package]] +name = "rfc3987" +version = "1.3.8" +description = "Parsing and validation of URIs (RFC 3986) and IRIs (RFC 3987)" +optional = false +python-versions = "*" +files = [ + {file = "rfc3987-1.3.8-py2.py3-none-any.whl", hash = "sha256:10702b1e51e5658843460b189b185c0366d2cf4cff716f13111b0ea9fd2dce53"}, + {file = "rfc3987-1.3.8.tar.gz", hash = "sha256:d3c4d257a560d544e9826b38bc81db676890c79ab9d7ac92b39c7a253d5ca733"}, +] + [[package]] name = "rich" version = "13.9.2" @@ -7369,6 +7399,21 @@ files = [ cryptography = ">=2.0" jeepney = ">=0.6" +[[package]] +name = "semantic-version" +version = "2.10.0" +description = "A library implementing the 'SemVer' scheme." +optional = false +python-versions = ">=2.7" +files = [ + {file = "semantic_version-2.10.0-py2.py3-none-any.whl", hash = "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177"}, + {file = "semantic_version-2.10.0.tar.gz", hash = "sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c"}, +] + +[package.extras] +dev = ["Django (>=1.11)", "check-manifest", "colorama (<=0.4.1)", "coverage", "flake8", "nose2", "readme-renderer (<25.0)", "tox", "wheel", "zest.releaser[recommended]"] +doc = ["Sphinx", "sphinx-rtd-theme"] + [[package]] name = "semver" version = "3.0.2" @@ -8079,6 +8124,17 @@ dev = ["tokenizers[testing]"] docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"] testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests", "ruff"] +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + [[package]] name = "tomli" version = "2.0.2" @@ -9035,4 +9091,4 @@ vectordb = ["faiss-cpu", "numpy"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "16f6caf6623a54ef9e609fe3eacf27393825d204277efbfd46c18969d28d63fc" +content-hash = "0a897c6c2514dccfa8ef219019c95591719447e3a72c465190b4d8d89b62aa23" diff --git a/pyproject.toml b/pyproject.toml index bc5a798f8..d3fee9b68 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ requests = "^2.31.0" faker = "^25.2.0" jsonref = "^1.1.0" jsonformer = {version = "0.12.0", optional = true} -jsonschema = {version = "^4.22.0", extras = ["format-nongpl"]} +jsonschema = {version = "^4.22.0", extras = ["format"]} pip = ">=22" pyjwt = "^2.8.0" opentelemetry-sdk = "^1.24.0" @@ -87,6 +87,8 @@ pypdfium2 = "^4.23.1" pyright = "1.1.334" lxml-stubs = "^0.4.0" ruff = ">=0.4.1" +liccheck = "^0.9.2" + [tool.poetry.group.api] optional = true @@ -132,3 +134,55 @@ markers = [ [pytest] log_cli = "True" log_cli_level = "DEBUG" + + +[tool.liccheck] +authorized_licenses = [ + "3-clause bsd", + "bsd", + "new bsd", + "bsd license", + "new bsd license", + "simplified bsd", + "academic free license (afl)", + "apache", + "apache 2.0", + "apache software", + "apache software license", + "gnu lgpl", + "lgpl with exceptions or zpl", + "gnu library or lesser general public license (lgpl)", + "isc", + "isc license", + "isc license (iscl)", + "mit", + "mit license", + "mozilla public license 2.0 (mpl 2.0)", + "the unlicense (unlicense)", + "python software foundation", + "python software foundation license", + "zpl 2.1", +] +unauthorized_licenses = [ + "gpl v3", +] +level = "Paranoid" +dependencies = true # to load [tool.poetry.dependencies] +optional_dependencies = [ + "sql", + "vectordb", + "manifest", + "anthropic", + "huggingface", + "api", + "databricks", + "uv", + "llama" +] # to load extras from [tool.poetry.extras] + +[tool.liccheck.authorized_packages] +aiocache = "0.12.3" # BSD 3-Clause +aiohappyeyeballs = "2.4.3" # Python Software Foundation +guardrails-api = "*" # Modified ELSSTIC +jsonformer = "0.12.0" # MIT +pillow = "10.4.0" # Historical Permission Notice and Disclaimer (HPND) \ No newline at end of file From 21650cc40ea1a1580007eb808ea62e140248e091 Mon Sep 17 00:00:00 2001 From: Caleb Courier Date: Fri, 14 Mar 2025 10:06:58 -0500 Subject: [PATCH 03/12] bump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d3fee9b68..b2ca6dd23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "guardrails-ai" -version = "0.6.4" +version = "0.6.5" description = "Adding guardrails to large language models." authors = ["Guardrails AI "] license = "Apache License 2.0" From 1a959307d27ff0c54d0edf4f36eb9fee73efbdb0 Mon Sep 17 00:00:00 2001 From: Caleb Courier Date: Fri, 14 Mar 2025 10:13:26 -0500 Subject: [PATCH 04/12] test authorizing nvidia packages with wildcard --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b2ca6dd23..8982d71e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -185,4 +185,5 @@ aiocache = "0.12.3" # BSD 3-Clause aiohappyeyeballs = "2.4.3" # Python Software Foundation guardrails-api = "*" # Modified ELSSTIC jsonformer = "0.12.0" # MIT -pillow = "10.4.0" # Historical Permission Notice and Disclaimer (HPND) \ No newline at end of file +pillow = "10.4.0" # Historical Permission Notice and Disclaimer (HPND) +nvidia-* = "*" \ No newline at end of file From 8b8b07e1f0660a58c7cb6ac8c7a810beacdba9ee Mon Sep 17 00:00:00 2001 From: Caleb Courier Date: Fri, 14 Mar 2025 10:14:32 -0500 Subject: [PATCH 05/12] revert --- pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8982d71e9..b2ca6dd23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -185,5 +185,4 @@ aiocache = "0.12.3" # BSD 3-Clause aiohappyeyeballs = "2.4.3" # Python Software Foundation guardrails-api = "*" # Modified ELSSTIC jsonformer = "0.12.0" # MIT -pillow = "10.4.0" # Historical Permission Notice and Disclaimer (HPND) -nvidia-* = "*" \ No newline at end of file +pillow = "10.4.0" # Historical Permission Notice and Disclaimer (HPND) \ No newline at end of file From 5050436e03674d05f5d40a548c93c3bdb617efc0 Mon Sep 17 00:00:00 2001 From: Caleb Courier Date: Fri, 14 Mar 2025 10:14:55 -0500 Subject: [PATCH 06/12] nongpl format --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b2ca6dd23..2d6fe2a20 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ requests = "^2.31.0" faker = "^25.2.0" jsonref = "^1.1.0" jsonformer = {version = "0.12.0", optional = true} -jsonschema = {version = "^4.22.0", extras = ["format"]} +jsonschema = {version = "^4.22.0", extras = ["format-nongpl"]} pip = ">=22" pyjwt = "^2.8.0" opentelemetry-sdk = "^1.24.0" From 81bb12bc53aa168fd7e7367ffce1894f55a3c1ed Mon Sep 17 00:00:00 2001 From: Caleb Courier Date: Fri, 14 Mar 2025 10:16:27 -0500 Subject: [PATCH 07/12] update poetry lock --- poetry.lock | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/poetry.lock b/poetry.lock index 08a9244e8..96e3daa99 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2852,13 +2852,9 @@ jsonschema-specifications = ">=2023.03.6" referencing = ">=0.28.4" rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} -rfc3987 = {version = "*", optional = true, markers = "extra == \"format\""} rpds-py = ">=0.7.1" uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -webcolors = [ - {version = ">=1.11", optional = true, markers = "extra == \"format\""}, - {version = ">=24.6.0", optional = true, markers = "extra == \"format-nongpl\""}, -] +webcolors = {version = ">=24.6.0", optional = true, markers = "extra == \"format-nongpl\""} [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] @@ -6942,24 +6938,13 @@ idna2008 = ["idna"] name = "rfc3986-validator" version = "0.1.1" description = "Pure python rfc3986 validator" -optional = true +optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ {file = "rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9"}, {file = "rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055"}, ] -[[package]] -name = "rfc3987" -version = "1.3.8" -description = "Parsing and validation of URIs (RFC 3986) and IRIs (RFC 3987)" -optional = false -python-versions = "*" -files = [ - {file = "rfc3987-1.3.8-py2.py3-none-any.whl", hash = "sha256:10702b1e51e5658843460b189b185c0366d2cf4cff716f13111b0ea9fd2dce53"}, - {file = "rfc3987-1.3.8.tar.gz", hash = "sha256:d3c4d257a560d544e9826b38bc81db676890c79ab9d7ac92b39c7a253d5ca733"}, -] - [[package]] name = "rich" version = "13.9.2" @@ -9091,4 +9076,4 @@ vectordb = ["faiss-cpu", "numpy"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "0a897c6c2514dccfa8ef219019c95591719447e3a72c465190b4d8d89b62aa23" +content-hash = "0d7414c61f9bc3d5ca506b5ca6affc72f54377470d390b0e00777eed9d6b630c" From 5b3f2942b17b8e52a8e92d6f3fb90429f4d3994a Mon Sep 17 00:00:00 2001 From: Caleb Courier Date: Fri, 28 Mar 2025 09:36:32 -0500 Subject: [PATCH 08/12] don't check optional dependencies --- .github/workflows/ci.yml | 3 ++- pyproject.toml | 15 +-------------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6338e0ffe..8bff9d62e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,8 @@ jobs: # Setup Virtual Environment python3 -m venv ./.venv source .venv/bin/activate - make full + poetry install + pip install liccheck - name: Check license run: | diff --git a/pyproject.toml b/pyproject.toml index 2d6fe2a20..b244ccdea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -168,21 +168,8 @@ unauthorized_licenses = [ ] level = "Paranoid" dependencies = true # to load [tool.poetry.dependencies] -optional_dependencies = [ - "sql", - "vectordb", - "manifest", - "anthropic", - "huggingface", - "api", - "databricks", - "uv", - "llama" -] # to load extras from [tool.poetry.extras] [tool.liccheck.authorized_packages] aiocache = "0.12.3" # BSD 3-Clause aiohappyeyeballs = "2.4.3" # Python Software Foundation -guardrails-api = "*" # Modified ELSSTIC -jsonformer = "0.12.0" # MIT -pillow = "10.4.0" # Historical Permission Notice and Disclaimer (HPND) \ No newline at end of file +guardrails-api = "*" # Modified ELSSTIC \ No newline at end of file From cf1c51e002de7c88c4e199a9b92404cfe39c58a5 Mon Sep 17 00:00:00 2001 From: Caleb Courier Date: Fri, 28 Mar 2025 09:48:21 -0500 Subject: [PATCH 09/12] remove extraneous install --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8bff9d62e..fa6b7cdfe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,6 @@ jobs: python3 -m venv ./.venv source .venv/bin/activate poetry install - pip install liccheck - name: Check license run: | From ca4d28063ffc8fd13edb077aec7af5559d2ccf18 Mon Sep 17 00:00:00 2001 From: Caleb Courier Date: Fri, 28 Mar 2025 09:53:19 -0500 Subject: [PATCH 10/12] debug greenlet issue --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa6b7cdfe..7e5f3eb91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,6 +42,8 @@ jobs: - name: Check license run: | source .venv/bin/activate + pip show SQLAlchemy + pip show greenlet liccheck Linting: runs-on: ubuntu-latest From a0e3e8cf5f142e8346785f732cba8121b32d4939 Mon Sep 17 00:00:00 2001 From: Caleb Courier Date: Fri, 28 Mar 2025 10:04:28 -0500 Subject: [PATCH 11/12] use command from virtual environment --- .github/workflows/ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7e5f3eb91..1fcf5bffe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,9 +42,7 @@ jobs: - name: Check license run: | source .venv/bin/activate - pip show SQLAlchemy - pip show greenlet - liccheck + .venv/bin/liccheck Linting: runs-on: ubuntu-latest strategy: From 9a53f8a9c4a91272ef3484d0f127bd7b5a12b816 Mon Sep 17 00:00:00 2001 From: Caleb Courier Date: Fri, 28 Mar 2025 10:10:32 -0500 Subject: [PATCH 12/12] explicitly install greenlet --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1fcf5bffe..22c95bd8d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,6 +42,7 @@ jobs: - name: Check license run: | source .venv/bin/activate + .venv/bin/pip install greenlet .venv/bin/liccheck Linting: runs-on: ubuntu-latest