exolot 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
+ /uv.lock binary
@@ -0,0 +1,81 @@
1
+ name: Build
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+
9
+ jobs:
10
+ validate-actions:
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ contents: read
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - name: action-validator
17
+ uses: mpalmer/action-validator@f55349f367686fa1df22f6e07f90f7cf88a9b28b
18
+ with:
19
+ version: 0.8.0
20
+
21
+ build:
22
+ runs-on: ubuntu-latest
23
+ permissions:
24
+ contents: read
25
+
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ with:
29
+ persist-credentials: false
30
+
31
+ - name: Install uv
32
+ uses: astral-sh/setup-uv@v5
33
+
34
+ - name: Run tests
35
+ run: uv run pytest -q
36
+
37
+ - name: Build package
38
+ run: uv build
39
+
40
+ # Tagging and releasing need a write-capable token, so they run in their own
41
+ # job, only for pushes to master, and never alongside pull request code.
42
+ release:
43
+ needs: build
44
+ if: github.event_name == 'push' && github.ref == 'refs/heads/master'
45
+ runs-on: ubuntu-latest
46
+ permissions:
47
+ contents: write
48
+
49
+ steps:
50
+ - uses: actions/checkout@v4
51
+ with:
52
+ token: ${{ secrets.GH_ACTIONS_TOKEN }}
53
+ fetch-depth: 0
54
+ fetch-tags: true
55
+
56
+ - name: Install uv
57
+ uses: astral-sh/setup-uv@v5
58
+
59
+ - name: Tag and release version
60
+ run: |
61
+ VERSION="$(uv version --short)"
62
+ TAG="v${VERSION}"
63
+ if git rev-parse "${TAG}" >/dev/null 2>&1; then
64
+ echo "Tag ${TAG} already exists"
65
+ else
66
+ git config user.name "github-actions[bot]"
67
+ git config user.email "github-actions[bot]@users.noreply.github.com"
68
+ git tag -a "${TAG}" -m "Release ${TAG}"
69
+ git push origin "${TAG}"
70
+ echo "Created and pushed tag ${TAG}"
71
+ fi
72
+ # Checked separately so a rerun creates the release if an earlier run
73
+ # pushed the tag but failed to create it.
74
+ if gh release view "${TAG}" >/dev/null 2>&1; then
75
+ echo "Release ${TAG} already exists"
76
+ else
77
+ gh release create "${TAG}" --title "Release ${TAG}" --generate-notes
78
+ echo "Created GitHub release ${TAG}"
79
+ fi
80
+ env:
81
+ GITHUB_TOKEN: ${{ secrets.GH_ACTIONS_TOKEN }}
@@ -0,0 +1,70 @@
1
+ name: Bump Version
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ bump:
7
+ description: 'Version bump level'
8
+ required: true
9
+ default: 'patch'
10
+ type: choice
11
+ options:
12
+ - patch
13
+ - minor
14
+ - major
15
+
16
+ jobs:
17
+ bump-version:
18
+ runs-on: ubuntu-latest
19
+ permissions:
20
+ contents: write
21
+ pull-requests: write
22
+
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ with:
26
+ token: ${{ secrets.GH_ACTIONS_TOKEN }}
27
+ ref: master
28
+ fetch-depth: 0
29
+
30
+
31
+ - name: Install uv
32
+ uses: astral-sh/setup-uv@v5
33
+
34
+ - name: Bump version
35
+ run: uv version --bump=${{ github.event.inputs.bump }}
36
+
37
+ - name: Get new version
38
+ id: get_version
39
+ run: |
40
+ VERSION="$(uv version --short)"
41
+ echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
42
+
43
+ - name: Create release branch
44
+ run: |
45
+ git config user.name "github-actions[bot]"
46
+ git config user.email "github-actions[bot]@users.noreply.github.com"
47
+ git checkout -b release-version-${{ steps.get_version.outputs.version }}
48
+
49
+ - name: Commit version bump
50
+ run: |
51
+ git add -u
52
+ git commit -m "Bump version to ${{ steps.get_version.outputs.version }}"
53
+
54
+ - name: Push branch
55
+ run: git push origin release-version-${{ steps.get_version.outputs.version }}
56
+
57
+ - name: Create pull request
58
+ run: |
59
+ gh pr create \
60
+ --base master \
61
+ --head release-version-${{ steps.get_version.outputs.version }} \
62
+ --title "Release version ${{ steps.get_version.outputs.version }}" \
63
+ --body "Bumps version to ${{ steps.get_version.outputs.version }} (${{ github.event.inputs.bump }} bump)."
64
+ env:
65
+ GH_TOKEN: ${{ secrets.GH_ACTIONS_TOKEN }}
66
+
67
+ - name: Enable automerge
68
+ run: gh pr merge --auto --squash release-version-${{ steps.get_version.outputs.version }}
69
+ env:
70
+ GH_TOKEN: ${{ secrets.GH_ACTIONS_TOKEN }}
@@ -0,0 +1,37 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ publish:
11
+ runs-on: ubuntu-latest
12
+ environment:
13
+ name: pypi
14
+ url: https://pypi.org/p/exolot
15
+ permissions:
16
+ contents: read
17
+ id-token: write
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@v5
23
+
24
+ - name: Check tag matches version
25
+ if: github.ref_type == 'tag'
26
+ run: |
27
+ VERSION="$(uv version --short)"
28
+ if [ "${GITHUB_REF_NAME}" != "v${VERSION}" ]; then
29
+ echo "Tag ${GITHUB_REF_NAME} does not match pyproject.toml version ${VERSION}"
30
+ exit 1
31
+ fi
32
+
33
+ - name: Build package
34
+ run: uv build
35
+
36
+ - name: Publish to PyPI
37
+ run: uv publish --verbose
@@ -0,0 +1,37 @@
1
+ name: Publish to TestPyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ publish:
11
+ runs-on: ubuntu-latest
12
+ environment:
13
+ name: testpypi
14
+ url: https://test.pypi.org/p/exolot
15
+ permissions:
16
+ contents: read
17
+ id-token: write
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@v5
23
+
24
+ - name: Check tag matches version
25
+ if: github.ref_type == 'tag'
26
+ run: |
27
+ VERSION="$(uv version --short)"
28
+ if [ "${GITHUB_REF_NAME}" != "v${VERSION}" ]; then
29
+ echo "Tag ${GITHUB_REF_NAME} does not match pyproject.toml version ${VERSION}"
30
+ exit 1
31
+ fi
32
+
33
+ - name: Build package
34
+ run: uv build
35
+
36
+ - name: Publish to TestPyPI
37
+ run: uv publish --verbose --publish-url=https://test.pypi.org/legacy/
@@ -0,0 +1,5 @@
1
+ dist/
2
+ *.egg-info/
3
+ __pycache__/
4
+ *.pyc
5
+ .venv/
@@ -0,0 +1 @@
1
+ 3.13
exolot-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 The exolot authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
exolot-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.5
2
+ Name: exolot
3
+ Version: 0.1.0
4
+ Summary: Analyze code locally from the command line with the SonarQube for IDE language server
5
+ Project-URL: Repository, https://github.com/skissane/exolot
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: Console
10
+ Classifier: Natural Language :: English
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Software Development :: Quality Assurance
13
+ Requires-Python: >=3.11
14
+ Description-Content-Type: text/markdown
15
+
16
+ # exolot
17
+
18
+ Analyze code locally from the command line with the language server from
19
+ SonarQube for IDE (formerly SonarLint). No SonarQube account or server needed.
20
+
21
+ > exolot is an independent project. It is not affiliated with or endorsed by
22
+ > SonarSource. "SonarQube" and "SonarLint" are trademarks of SonarSource.
23
+
24
+ ## Why
25
+
26
+ The old `sonarlint-cli` was discontinued years ago. SonarSource's current
27
+ SonarQube CLI needs a SonarQube Cloud or Server account, and its code analysis
28
+ runs on the server. exolot fills the gap: account-free analysis that runs
29
+ entirely on your own machine. It needs network access only to download the
30
+ language server the first time (and see the note on C/C++ and C# below).
31
+
32
+ ## How it works
33
+
34
+ exolot downloads the SonarQube for IDE extension for VS Code (a `.vsix` file,
35
+ which is a zip) from the
36
+ [sonarlint-vscode GitHub releases](https://github.com/SonarSource/sonarlint-vscode/releases),
37
+ checks its sha256 digest, and unpacks the language server, the language
38
+ analyzers and the bundled Java runtime into a cache directory. It then runs the
39
+ language server headlessly, opens each file you ask it to analyze, and prints
40
+ the issues the server reports.
41
+
42
+ The idea comes from [sonarqube.nvim](https://github.com/iamkarasik/sonarqube.nvim),
43
+ which does the same thing for Neovim.
44
+
45
+ ## Usage
46
+
47
+ ```sh
48
+ uvx exolot # analyze the current directory
49
+ uvx exolot src/ tests/foo.py # analyze specific files or directories
50
+ uvx exolot --format json . # machine-readable output
51
+ uvx exolot install # just download and unpack the server
52
+ uvx exolot cache-dir # show where the server is cached
53
+ ```
54
+
55
+ Directories are expanded with `git ls-files` when inside a git repository (so
56
+ `.gitignore` is respected), and by walking the tree otherwise. Binary files and
57
+ files over 2 MiB are skipped.
58
+
59
+ Exit status is 0 when no issues are found, 1 when issues are found, and 2 on
60
+ errors.
61
+
62
+ ### Options
63
+
64
+ - `--server-version TAG` picks a sonarlint-vscode release (default: the
65
+ version exolot was tested with). Unknown versions are downloaded without
66
+ digest verification, with a warning.
67
+ - `--platform PLATFORM` overrides the detected VSIX platform (`linux-x64`,
68
+ `darwin-arm64`, `darwin-x64`, `win32-x64`, or `universal`).
69
+ - `--java PATH` uses a different Java executable.
70
+ - `--node PATH` sets the Node.js used for JavaScript/TypeScript analysis
71
+ (otherwise the server looks for `node` on the `PATH`).
72
+ - `--rules FILE` reads rule settings from a JSON file, in the same format as
73
+ VS Code's `sonarlint.rules` setting, e.g.
74
+ `{"python:S1764": {"level": "off"}}`.
75
+ - `-v` / `--verbose` shows the server's logs.
76
+
77
+ ## Platforms
78
+
79
+ Platform-specific builds with a bundled Java runtime exist for `linux-x64`,
80
+ `darwin-arm64`, `darwin-x64` and `win32-x64`. On other platforms (such as
81
+ Linux on ARM) exolot uses the universal build, which needs Java 17 or later
82
+ from `JAVA_HOME`, the `PATH`, or `--java`.
83
+
84
+ ## Notes
85
+
86
+ - The language server keeps its own state in `~/.sonarlint`, shared with any
87
+ SonarQube for IDE installation you have.
88
+ - Telemetry is disabled.
89
+ - C/C++ and C# analyzers are not included in the VSIX; the server tries to
90
+ download them from `binaries.sonarsource.com` when it starts.
91
+ - Each run starts a fresh JVM and loads every analyzer, so even a single file
92
+ takes around 15 seconds.
93
+ - The bundled analyzers are licensed by SonarSource under their own terms. exolot
94
+ downloads them from SonarSource's releases at run time and does not
95
+ redistribute them.
96
+
97
+ ## Development
98
+
99
+ ```sh
100
+ uv sync
101
+ uv run exolot --help
102
+ uv run pytest
103
+ ```
exolot-0.1.0/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # exolot
2
+
3
+ Analyze code locally from the command line with the language server from
4
+ SonarQube for IDE (formerly SonarLint). No SonarQube account or server needed.
5
+
6
+ > exolot is an independent project. It is not affiliated with or endorsed by
7
+ > SonarSource. "SonarQube" and "SonarLint" are trademarks of SonarSource.
8
+
9
+ ## Why
10
+
11
+ The old `sonarlint-cli` was discontinued years ago. SonarSource's current
12
+ SonarQube CLI needs a SonarQube Cloud or Server account, and its code analysis
13
+ runs on the server. exolot fills the gap: account-free analysis that runs
14
+ entirely on your own machine. It needs network access only to download the
15
+ language server the first time (and see the note on C/C++ and C# below).
16
+
17
+ ## How it works
18
+
19
+ exolot downloads the SonarQube for IDE extension for VS Code (a `.vsix` file,
20
+ which is a zip) from the
21
+ [sonarlint-vscode GitHub releases](https://github.com/SonarSource/sonarlint-vscode/releases),
22
+ checks its sha256 digest, and unpacks the language server, the language
23
+ analyzers and the bundled Java runtime into a cache directory. It then runs the
24
+ language server headlessly, opens each file you ask it to analyze, and prints
25
+ the issues the server reports.
26
+
27
+ The idea comes from [sonarqube.nvim](https://github.com/iamkarasik/sonarqube.nvim),
28
+ which does the same thing for Neovim.
29
+
30
+ ## Usage
31
+
32
+ ```sh
33
+ uvx exolot # analyze the current directory
34
+ uvx exolot src/ tests/foo.py # analyze specific files or directories
35
+ uvx exolot --format json . # machine-readable output
36
+ uvx exolot install # just download and unpack the server
37
+ uvx exolot cache-dir # show where the server is cached
38
+ ```
39
+
40
+ Directories are expanded with `git ls-files` when inside a git repository (so
41
+ `.gitignore` is respected), and by walking the tree otherwise. Binary files and
42
+ files over 2 MiB are skipped.
43
+
44
+ Exit status is 0 when no issues are found, 1 when issues are found, and 2 on
45
+ errors.
46
+
47
+ ### Options
48
+
49
+ - `--server-version TAG` picks a sonarlint-vscode release (default: the
50
+ version exolot was tested with). Unknown versions are downloaded without
51
+ digest verification, with a warning.
52
+ - `--platform PLATFORM` overrides the detected VSIX platform (`linux-x64`,
53
+ `darwin-arm64`, `darwin-x64`, `win32-x64`, or `universal`).
54
+ - `--java PATH` uses a different Java executable.
55
+ - `--node PATH` sets the Node.js used for JavaScript/TypeScript analysis
56
+ (otherwise the server looks for `node` on the `PATH`).
57
+ - `--rules FILE` reads rule settings from a JSON file, in the same format as
58
+ VS Code's `sonarlint.rules` setting, e.g.
59
+ `{"python:S1764": {"level": "off"}}`.
60
+ - `-v` / `--verbose` shows the server's logs.
61
+
62
+ ## Platforms
63
+
64
+ Platform-specific builds with a bundled Java runtime exist for `linux-x64`,
65
+ `darwin-arm64`, `darwin-x64` and `win32-x64`. On other platforms (such as
66
+ Linux on ARM) exolot uses the universal build, which needs Java 17 or later
67
+ from `JAVA_HOME`, the `PATH`, or `--java`.
68
+
69
+ ## Notes
70
+
71
+ - The language server keeps its own state in `~/.sonarlint`, shared with any
72
+ SonarQube for IDE installation you have.
73
+ - Telemetry is disabled.
74
+ - C/C++ and C# analyzers are not included in the VSIX; the server tries to
75
+ download them from `binaries.sonarsource.com` when it starts.
76
+ - Each run starts a fresh JVM and loads every analyzer, so even a single file
77
+ takes around 15 seconds.
78
+ - The bundled analyzers are licensed by SonarSource under their own terms. exolot
79
+ downloads them from SonarSource's releases at run time and does not
80
+ redistribute them.
81
+
82
+ ## Development
83
+
84
+ ```sh
85
+ uv sync
86
+ uv run exolot --help
87
+ uv run pytest
88
+ ```
@@ -0,0 +1,28 @@
1
+ [project]
2
+ name = "exolot"
3
+ version = "0.1.0"
4
+ description = "Analyze code locally from the command line with the SonarQube for IDE language server"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ license = "MIT"
8
+ dependencies = []
9
+ classifiers = [
10
+ "Natural Language :: English",
11
+ "Programming Language :: Python :: 3",
12
+ "Development Status :: 3 - Alpha",
13
+ "Environment :: Console",
14
+ "Topic :: Software Development :: Quality Assurance",
15
+ ]
16
+
17
+ [project.urls]
18
+ Repository = "https://github.com/skissane/exolot"
19
+
20
+ [project.scripts]
21
+ exolot = "exolot.cli:main"
22
+
23
+ [build-system]
24
+ requires = ["hatchling"]
25
+ build-backend = "hatchling.build"
26
+
27
+ [dependency-groups]
28
+ dev = ["pytest>=8"]
@@ -0,0 +1,8 @@
1
+ """Run SonarQube for IDE's language server from the command line."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ try:
6
+ __version__ = version("exolot")
7
+ except PackageNotFoundError:
8
+ __version__ = "0.0.0"
@@ -0,0 +1,3 @@
1
+ from .cli import main
2
+
3
+ raise SystemExit(main())