licenseid 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ AGENTS.md
@@ -0,0 +1,48 @@
1
+ # SPDX-FileCopyrightText: 2026-present Arthit Suriyawongkul
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ name: Build wheels
5
+
6
+ on:
7
+ push:
8
+ branches: [ main, develop ]
9
+ pull_request:
10
+ branches: [ main, develop ]
11
+
12
+ jobs:
13
+ build-wheel:
14
+ name: Python ${{ matrix.python-version }} on ${{ matrix.os }}
15
+ runs-on: ${{ matrix.os }}
16
+ permissions:
17
+ contents: read
18
+ defaults:
19
+ run:
20
+ shell: bash
21
+ strategy:
22
+ matrix:
23
+ os: [ ubuntu-latest ]
24
+ python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ]
25
+ #include:
26
+ # - os: windows-latest
27
+ # python-version: "3.10"
28
+ # - os: macos-latest
29
+ # python-version: "3.10"
30
+ fail-fast: true
31
+
32
+ steps:
33
+ - uses: actions/checkout@v6
34
+
35
+ - name: Set up Python ${{ matrix.python-version }}
36
+ uses: actions/setup-python@v6
37
+ with:
38
+ python-version: ${{ matrix.python-version }}
39
+
40
+ - name: Install build dependencies
41
+ run: |
42
+ pip install --upgrade build pip
43
+ pip install .
44
+
45
+ - name: Build wheel
46
+ id: build
47
+ run: |
48
+ python -m build
@@ -0,0 +1,44 @@
1
+ # SPDX-FileCopyrightText: 2026-present Arthit Suriyawongkul
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ name: Lint and format
5
+
6
+ on:
7
+ push:
8
+ branches: [ main, develop ]
9
+ pull_request:
10
+ branches: [ main, develop ]
11
+
12
+ jobs:
13
+ ruff:
14
+ name: Lint
15
+ runs-on: ubuntu-latest
16
+
17
+ steps:
18
+ - uses: actions/checkout@v6
19
+
20
+ - name: Set up Python
21
+ uses: actions/setup-python@v6
22
+ with:
23
+ python-version: "3.10"
24
+
25
+ - name: Install Ruff
26
+ run: |
27
+ pip install --upgrade pip
28
+ pip install ".[dev,java]"
29
+
30
+ - name: Ruff linter
31
+ run: |
32
+ ruff check src/ tests/
33
+
34
+ - name: Pylint
35
+ run: |
36
+ pylint src/ tests/
37
+
38
+ - name: Flake8
39
+ run: |
40
+ flake8 src/ tests/
41
+
42
+ - name: Ruff formatter check
43
+ run: |
44
+ ruff format --check src/ tests/
@@ -0,0 +1,57 @@
1
+ # SPDX-FileCopyrightText: 2026-present Arthit Suriyawongkul
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ name: Publish to PyPI
5
+
6
+ on:
7
+ release:
8
+ types: [ published ]
9
+
10
+ jobs:
11
+ build:
12
+ name: Build distribution
13
+ runs-on: ubuntu-latest
14
+ permissions:
15
+ contents: read
16
+
17
+ steps:
18
+ - uses: actions/checkout@v6
19
+
20
+ - name: Set up Python
21
+ uses: actions/setup-python@v6
22
+ with:
23
+ python-version: "3.14"
24
+
25
+ - name: Install build dependencies
26
+ run: |
27
+ pip install --upgrade build pip
28
+ pip install -e .
29
+
30
+ - name: Build sdist and wheel
31
+ run: |
32
+ python -m build
33
+
34
+ - name: Upload distribution artifacts
35
+ uses: actions/upload-artifact@v7
36
+ with:
37
+ name: dist
38
+ path: dist/
39
+ retention-days: 3
40
+
41
+ publish:
42
+ name: Publish to PyPI
43
+ needs: build
44
+ runs-on: ubuntu-latest
45
+ environment: pypi
46
+ permissions:
47
+ id-token: write # required for trusted publishing (OIDC)
48
+
49
+ steps:
50
+ - name: Download distribution artifacts
51
+ uses: actions/download-artifact@v8
52
+ with:
53
+ name: dist
54
+ path: dist/
55
+
56
+ - name: Publish to PyPI
57
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,41 @@
1
+ # SPDX-FileCopyrightText: 2026-present Arthit Suriyawongkul
2
+ # SPDX-License-Identifier: Apache-2.0
3
+
4
+ name: Unit tests
5
+
6
+ on:
7
+ push:
8
+ branches: [ main, develop ]
9
+ pull_request:
10
+ branches: [ main, develop ]
11
+
12
+ jobs:
13
+ test:
14
+ name: Test on Python ${{ matrix.python-version }}
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ matrix:
18
+ python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ]
19
+ fail-fast: true
20
+
21
+ steps:
22
+ - uses: actions/checkout@v6
23
+
24
+ - name: Set up Python ${{ matrix.python-version }}
25
+ uses: actions/setup-python@v6
26
+ with:
27
+ python-version: ${{ matrix.python-version }}
28
+
29
+ - name: Install dependencies
30
+ run: |
31
+ pip install --upgrade pip
32
+ pip install ".[dev,java]"
33
+
34
+ - name: Run tests
35
+ run: |
36
+ pytest tests/ -v --tb=short
37
+
38
+ - name: Upload coverage reports
39
+ if: matrix.python-version == '3.14'
40
+ uses: codecov/codecov-action@v5
41
+ continue-on-error: true
@@ -0,0 +1,138 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ *.manifest
31
+ *.spec
32
+
33
+ # Installer logs
34
+ pip-log.txt
35
+ pip-delete-this-directory.txt
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .nox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *.cover
47
+ *.py.cover
48
+ .hypothesis/
49
+ .pytest_cache/
50
+ cover/
51
+
52
+ # Translations
53
+ *.mo
54
+ *.pot
55
+
56
+ # Django stuff:
57
+ *.log
58
+ local_settings.py
59
+ db.sqlite3
60
+ db.sqlite3-journal
61
+
62
+ # Flask stuff:
63
+ instance/
64
+ .webassets-cache
65
+
66
+ # Scrapy stuff:
67
+ .scrapy
68
+
69
+ # Sphinx documentation
70
+ docs/_build/
71
+
72
+ # PyBuilder
73
+ target/
74
+
75
+ # Jupyter Notebook
76
+ .ipynb_checkpoints
77
+
78
+ # IPython
79
+ profile_default/
80
+ ipython_config.py
81
+
82
+ # pyenv
83
+ .python-version
84
+
85
+ # pipenv
86
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
87
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
88
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
89
+ # install all needed dependencies.
90
+ #Pipfile.lock
91
+
92
+ # celery beat schedule file
93
+ celerybeat-schedule
94
+
95
+ # SageMath parsed files
96
+ *.sage.py
97
+
98
+ # Environments
99
+ .env
100
+ .venv
101
+ env/
102
+ venv/
103
+ ENV/
104
+ env.bak/
105
+ venv.bak/
106
+
107
+ # Spyder project settings
108
+ .spyderproject
109
+ .spyproject
110
+
111
+ # Rope project settings
112
+ .ropeproject
113
+
114
+ # mkdocs documentation
115
+ /site
116
+
117
+ # mypy
118
+ .mypy_cache/
119
+ .dmypy.json
120
+ dmypy.json
121
+
122
+ # Pyre type checker
123
+ .pyre/
124
+
125
+ # IDEs
126
+ .project
127
+ .pydevproject
128
+ .idea
129
+ org.eclipse.core.resources.prefs
130
+ .vscode
131
+
132
+ .DS_Store
133
+ .ruff_cache/
134
+ .pytest_cache/
135
+
136
+ # Local testing files
137
+ dummy.db
138
+ tests/tool.jar
@@ -0,0 +1,15 @@
1
+ Apache Software License 2.0
2
+
3
+ Copyright (c) 2026, Arthit Suriyawongkul
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
@@ -0,0 +1,114 @@
1
+ Metadata-Version: 2.4
2
+ Name: licenseid
3
+ Version: 0.1.0
4
+ Summary: Get the SPDX License ID from license text
5
+ Author-email: Arthit Suriyawongkul <suriyawa@tcd.ie>
6
+ License-Expression: Apache-2.0
7
+ License-File: LICENSE
8
+ Keywords: license,license-matcher,licenseid,matcher,opensource,spdx
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Requires-Python: >=3.10
18
+ Requires-Dist: beautifulsoup4>=4.10.0
19
+ Requires-Dist: click>=8.0.0
20
+ Requires-Dist: rapidfuzz>=3.0.0
21
+ Requires-Dist: requests>=2.28.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: flake8; extra == 'dev'
24
+ Requires-Dist: mypy; extra == 'dev'
25
+ Requires-Dist: pylint; extra == 'dev'
26
+ Requires-Dist: pytest; extra == 'dev'
27
+ Requires-Dist: pytest-cov; extra == 'dev'
28
+ Requires-Dist: ruff; extra == 'dev'
29
+ Provides-Extra: java
30
+ Requires-Dist: jpype1>=1.7.0; extra == 'java'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # LicenseID
34
+
35
+ A portable SPDX License ID matcher.
36
+
37
+ `licenseid` takes license text as input and identifies the closest matched SPDX License ID using a hybrid search strategy (SQLite FTS5 trigram + RapidFuzz ranking + optional Java validation).
38
+
39
+ ## Features
40
+
41
+ - **Hybrid strategy**:
42
+ - **Tier 1**: Broad recall using SQLite FTS5 with trigram tokenization.
43
+ - **Tier 2**: Precision ranking using RapidFuzz (token set ratio) + Popularity weighting.
44
+ - **Tier 3**: Optional final validation via `tools-java` if available.
45
+ - **Unix philosophy**: Parseable CLI output.
46
+
47
+ ## Installation
48
+
49
+ Install with `pipx`:
50
+
51
+ ```bash
52
+ pipx install licenseid
53
+ ```
54
+
55
+ Or using `uv`:
56
+
57
+ ```bash
58
+ uv tool install licenseid
59
+ ```
60
+
61
+ ## Usage
62
+
63
+ ### 1. Update the license database
64
+
65
+ Before matching, you need to build the local license index:
66
+
67
+ ```bash
68
+ licenseid update
69
+ ```
70
+
71
+ ### 2. Match a license
72
+
73
+ Match text from a file:
74
+
75
+ ```bash
76
+ licenseid match LICENSE.txt
77
+ ```
78
+
79
+ Match with Java validation enabled:
80
+
81
+ ```bash
82
+ licenseid match LICENSE.txt --java
83
+ ```
84
+
85
+ Match with popularity tie-breaker enabled:
86
+
87
+ ```bash
88
+ licenseid match LICENSE.txt --pop
89
+ ```
90
+
91
+ The tie-breaker is triggered only when candidate similarity scores
92
+ differ by less than 0.02%.
93
+
94
+ ### 3. Output formats
95
+
96
+ Default (Unix-friendly):
97
+
98
+ ```text
99
+ LICENSE_ID=Apache-2.0 SCORE=0.9850
100
+ ```
101
+
102
+ JSON:
103
+
104
+ ```bash
105
+ licenseid match LICENSE.txt --json
106
+ ```
107
+
108
+ ## Configuration
109
+
110
+ - `SPDX_TOOLS_JAR`: Path to the `tools-java` jar for Tier 3 validation.
111
+
112
+ ## License
113
+
114
+ Apache-2.0
@@ -0,0 +1,82 @@
1
+ # LicenseID
2
+
3
+ A portable SPDX License ID matcher.
4
+
5
+ `licenseid` takes license text as input and identifies the closest matched SPDX License ID using a hybrid search strategy (SQLite FTS5 trigram + RapidFuzz ranking + optional Java validation).
6
+
7
+ ## Features
8
+
9
+ - **Hybrid strategy**:
10
+ - **Tier 1**: Broad recall using SQLite FTS5 with trigram tokenization.
11
+ - **Tier 2**: Precision ranking using RapidFuzz (token set ratio) + Popularity weighting.
12
+ - **Tier 3**: Optional final validation via `tools-java` if available.
13
+ - **Unix philosophy**: Parseable CLI output.
14
+
15
+ ## Installation
16
+
17
+ Install with `pipx`:
18
+
19
+ ```bash
20
+ pipx install licenseid
21
+ ```
22
+
23
+ Or using `uv`:
24
+
25
+ ```bash
26
+ uv tool install licenseid
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ### 1. Update the license database
32
+
33
+ Before matching, you need to build the local license index:
34
+
35
+ ```bash
36
+ licenseid update
37
+ ```
38
+
39
+ ### 2. Match a license
40
+
41
+ Match text from a file:
42
+
43
+ ```bash
44
+ licenseid match LICENSE.txt
45
+ ```
46
+
47
+ Match with Java validation enabled:
48
+
49
+ ```bash
50
+ licenseid match LICENSE.txt --java
51
+ ```
52
+
53
+ Match with popularity tie-breaker enabled:
54
+
55
+ ```bash
56
+ licenseid match LICENSE.txt --pop
57
+ ```
58
+
59
+ The tie-breaker is triggered only when candidate similarity scores
60
+ differ by less than 0.02%.
61
+
62
+ ### 3. Output formats
63
+
64
+ Default (Unix-friendly):
65
+
66
+ ```text
67
+ LICENSE_ID=Apache-2.0 SCORE=0.9850
68
+ ```
69
+
70
+ JSON:
71
+
72
+ ```bash
73
+ licenseid match LICENSE.txt --json
74
+ ```
75
+
76
+ ## Configuration
77
+
78
+ - `SPDX_TOOLS_JAR`: Path to the `tools-java` jar for Tier 3 validation.
79
+
80
+ ## License
81
+
82
+ Apache-2.0
@@ -0,0 +1,62 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "licenseid"
7
+ version = "0.1.0"
8
+ description = "Get the SPDX License ID from license text"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "Apache-2.0"
12
+ authors = [{ name = "Arthit Suriyawongkul", email = "suriyawa@tcd.ie" }]
13
+ keywords = [
14
+ "license",
15
+ "matcher",
16
+ "spdx",
17
+ "license-matcher",
18
+ "opensource",
19
+ "licenseid",
20
+ ]
21
+ classifiers = [
22
+ "Development Status :: 3 - Alpha",
23
+ "Intended Audience :: Developers",
24
+ "Programming Language :: Python :: 3",
25
+ "Programming Language :: Python :: 3.10",
26
+ "Programming Language :: Python :: 3.11",
27
+ "Programming Language :: Python :: 3.12",
28
+ "Programming Language :: Python :: 3.13",
29
+ "Programming Language :: Python :: 3.14",
30
+ ]
31
+ dependencies = [
32
+ "beautifulsoup4>=4.10.0",
33
+ "click>=8.0.0",
34
+ "rapidfuzz>=3.0.0",
35
+ "requests>=2.28.0",
36
+ ]
37
+
38
+ [project.optional-dependencies]
39
+ dev = ["flake8", "mypy", "pylint", "pytest", "pytest-cov", "ruff"]
40
+ java = ["jpype1>=1.7.0"]
41
+
42
+ [project.scripts]
43
+ licenseid = "licenseid.cli:main"
44
+
45
+ [tool.hatch.build.targets.sdist]
46
+ exclude = ["AGENTS.md", "GEMINI.md", "tests/fixtures/**", "scripts/**"]
47
+
48
+ [tool.hatch.build.targets.wheel]
49
+ packages = ["src/licenseid"]
50
+
51
+ [tool.ruff]
52
+ line-length = 88
53
+ target-version = "py310"
54
+
55
+ [tool.mypy]
56
+ strict = true
57
+ python_version = "3.10"
58
+
59
+ [tool.pytest.ini_options]
60
+ markers = [
61
+ "benchmark: marks tests as slow benchmark (deselect with '-m \"not benchmark\"')",
62
+ ]
@@ -0,0 +1,14 @@
1
+ # SPDX-FileCopyrightText: 2026-present Arthit Suriyawongkul
2
+ # SPDX-FileType: SOURCE
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ __version__ = "0.1.0"
6
+
7
+ from licenseid.matcher import AggregatedLicenseMatcher
8
+ from licenseid.database import LicenseDatabase, normalize_text
9
+
10
+ __all__ = [
11
+ "AggregatedLicenseMatcher",
12
+ "LicenseDatabase",
13
+ "normalize_text",
14
+ ]