errlens-cli 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.
- errlens_cli-0.1.0/.github/workflows/publish.yml +109 -0
- errlens_cli-0.1.0/.github/workflows/tests-macos.yml +27 -0
- errlens_cli-0.1.0/.github/workflows/tests.yml +61 -0
- errlens_cli-0.1.0/.gitignore +23 -0
- errlens_cli-0.1.0/CHANGELOG.md +40 -0
- errlens_cli-0.1.0/CONTRIBUTING.md +26 -0
- errlens_cli-0.1.0/LICENSE +21 -0
- errlens_cli-0.1.0/MANIFEST.in +7 -0
- errlens_cli-0.1.0/PKG-INFO +233 -0
- errlens_cli-0.1.0/README.md +208 -0
- errlens_cli-0.1.0/docs/actions4-diagnosis.md +69 -0
- errlens_cli-0.1.0/docs/manual-acceptance.md +607 -0
- errlens_cli-0.1.0/docs/release-notes-0.1.0.md +24 -0
- errlens_cli-0.1.0/docs/releasing.md +186 -0
- errlens_cli-0.1.0/docs/terminal-design.md +245 -0
- errlens_cli-0.1.0/docs/windows-conpty.md +160 -0
- errlens_cli-0.1.0/experiments/manual_acceptance.py +75 -0
- errlens_cli-0.1.0/experiments/terminal_probe.py +81 -0
- errlens_cli-0.1.0/pyproject.toml +47 -0
- errlens_cli-0.1.0/setup.cfg +4 -0
- errlens_cli-0.1.0/src/errlens/__init__.py +7 -0
- errlens_cli-0.1.0/src/errlens/__main__.py +6 -0
- errlens_cli-0.1.0/src/errlens/_conpty.py +236 -0
- errlens_cli-0.1.0/src/errlens/_conpty_worker.py +158 -0
- errlens_cli-0.1.0/src/errlens/_pty_child.py +25 -0
- errlens_cli-0.1.0/src/errlens/analyzers/__init__.py +1 -0
- errlens_cli-0.1.0/src/errlens/analyzers/base.py +45 -0
- errlens_cli-0.1.0/src/errlens/analyzers/python.py +362 -0
- errlens_cli-0.1.0/src/errlens/capture.py +92 -0
- errlens_cli-0.1.0/src/errlens/cli.py +177 -0
- errlens_cli-0.1.0/src/errlens/conpty_runner.py +269 -0
- errlens_cli-0.1.0/src/errlens/i18n.py +61 -0
- errlens_cli-0.1.0/src/errlens/locales/en.json +96 -0
- errlens_cli-0.1.0/src/errlens/locales/ru.json +96 -0
- errlens_cli-0.1.0/src/errlens/models.py +120 -0
- errlens_cli-0.1.0/src/errlens/posix_shell.py +71 -0
- errlens_cli-0.1.0/src/errlens/powershell.py +77 -0
- errlens_cli-0.1.0/src/errlens/pty_runner.py +172 -0
- errlens_cli-0.1.0/src/errlens/py.typed +0 -0
- errlens_cli-0.1.0/src/errlens/render.py +96 -0
- errlens_cli-0.1.0/src/errlens/rules/__init__.py +1 -0
- errlens_cli-0.1.0/src/errlens/rules/python.py +84 -0
- errlens_cli-0.1.0/src/errlens/runner.py +241 -0
- errlens_cli-0.1.0/src/errlens/service.py +58 -0
- errlens_cli-0.1.0/src/errlens_cli.egg-info/PKG-INFO +233 -0
- errlens_cli-0.1.0/src/errlens_cli.egg-info/SOURCES.txt +73 -0
- errlens_cli-0.1.0/src/errlens_cli.egg-info/dependency_links.txt +1 -0
- errlens_cli-0.1.0/src/errlens_cli.egg-info/entry_points.txt +2 -0
- errlens_cli-0.1.0/src/errlens_cli.egg-info/requires.txt +7 -0
- errlens_cli-0.1.0/src/errlens_cli.egg-info/top_level.txt +1 -0
- errlens_cli-0.1.0/tests/fixtures/README.md +25 -0
- errlens_cli-0.1.0/tests/fixtures/conpty_python313.json +10 -0
- errlens_cli-0.1.0/tests/fixtures/python_diagnostics.json +351 -0
- errlens_cli-0.1.0/tests/fixtures/recorded_python313.json +26 -0
- errlens_cli-0.1.0/tests/integration/test_conpty.py +322 -0
- errlens_cli-0.1.0/tests/integration/test_execution.py +151 -0
- errlens_cli-0.1.0/tests/integration/test_explanation_cli.py +163 -0
- errlens_cli-0.1.0/tests/integration/test_installed_package.py +45 -0
- errlens_cli-0.1.0/tests/integration/test_interrupt_pid.py +108 -0
- errlens_cli-0.1.0/tests/integration/test_posix_shell.py +173 -0
- errlens_cli-0.1.0/tests/integration/test_powershell.py +112 -0
- errlens_cli-0.1.0/tests/integration/test_pty.py +221 -0
- errlens_cli-0.1.0/tests/integration/test_python_analysis.py +95 -0
- errlens_cli-0.1.0/tests/integration/test_vt_forwarding.py +20 -0
- errlens_cli-0.1.0/tests/integration/test_windows_encoding.py +36 -0
- errlens_cli-0.1.0/tests/unit/test_analyzers.py +38 -0
- errlens_cli-0.1.0/tests/unit/test_capture.py +65 -0
- errlens_cli-0.1.0/tests/unit/test_cli.py +78 -0
- errlens_cli-0.1.0/tests/unit/test_explanations.py +100 -0
- errlens_cli-0.1.0/tests/unit/test_i18n.py +61 -0
- errlens_cli-0.1.0/tests/unit/test_models.py +56 -0
- errlens_cli-0.1.0/tests/unit/test_python_analyzer.py +166 -0
- errlens_cli-0.1.0/tests/unit/test_render.py +65 -0
- errlens_cli-0.1.0/tests/unit/test_runner.py +100 -0
- errlens_cli-0.1.0/tests/unit/test_vt_diagnostics.py +85 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
name: Release candidate and Trusted Publishing
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
publish:
|
|
7
|
+
description: Publish approved v0.1.0 to PyPI (false builds artifacts only)
|
|
8
|
+
required: true
|
|
9
|
+
type: boolean
|
|
10
|
+
default: false
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: pypi-${{ github.ref }}
|
|
17
|
+
cancel-in-progress: false
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
build:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
actions: read
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
- uses: actions/setup-python@v5
|
|
28
|
+
with:
|
|
29
|
+
python-version: '3.12'
|
|
30
|
+
- name: Verify distribution identity
|
|
31
|
+
run: |
|
|
32
|
+
python - <<'PY'
|
|
33
|
+
import tomllib
|
|
34
|
+
from pathlib import Path
|
|
35
|
+
project = tomllib.loads(Path('pyproject.toml').read_text())['project']
|
|
36
|
+
assert project['name'] == 'errlens-cli'
|
|
37
|
+
assert project['version'] == '0.1.0'
|
|
38
|
+
assert project['scripts']['errlens'] == 'errlens.cli:main_entry'
|
|
39
|
+
PY
|
|
40
|
+
- name: Require approved tag and successful Tests for publication
|
|
41
|
+
if: inputs.publish
|
|
42
|
+
env:
|
|
43
|
+
GH_TOKEN: ${{ github.token }}
|
|
44
|
+
run: |
|
|
45
|
+
test "$GITHUB_REPOSITORY" = 'ErrLens/errlens-cli'
|
|
46
|
+
test "$GITHUB_REF" = 'refs/tags/v0.1.0'
|
|
47
|
+
gh run list --repo "$GITHUB_REPOSITORY" --workflow tests.yml --commit "$GITHUB_SHA" --limit 20 --json headSha,status,conclusion > tests-runs.json
|
|
48
|
+
python - <<'PY'
|
|
49
|
+
import json, os
|
|
50
|
+
from pathlib import Path
|
|
51
|
+
runs = json.loads(Path('tests-runs.json').read_text())
|
|
52
|
+
assert runs, 'No Tests run exists for the selected commit'
|
|
53
|
+
latest = runs[0]
|
|
54
|
+
assert latest['headSha'] == os.environ['GITHUB_SHA']
|
|
55
|
+
assert latest['status'] == 'completed' and latest['conclusion'] == 'success', latest
|
|
56
|
+
PY
|
|
57
|
+
- name: Build and check archives
|
|
58
|
+
run: |
|
|
59
|
+
python -m pip install build twine
|
|
60
|
+
python -m build
|
|
61
|
+
python -m twine check --strict dist/*
|
|
62
|
+
python - <<'PY'
|
|
63
|
+
import email, zipfile
|
|
64
|
+
from pathlib import Path
|
|
65
|
+
assert {p.name for p in Path('dist').iterdir()} == {
|
|
66
|
+
'errlens_cli-0.1.0-py3-none-any.whl', 'errlens_cli-0.1.0.tar.gz'}
|
|
67
|
+
with zipfile.ZipFile('dist/errlens_cli-0.1.0-py3-none-any.whl') as z:
|
|
68
|
+
metadata = email.message_from_bytes(z.read('errlens_cli-0.1.0.dist-info/METADATA'))
|
|
69
|
+
assert metadata['Name'] == 'errlens-cli' and metadata['Version'] == '0.1.0'
|
|
70
|
+
PY
|
|
71
|
+
- name: Smoke-test installed wheel outside checkout
|
|
72
|
+
run: |
|
|
73
|
+
python -m venv .wheel-check
|
|
74
|
+
.wheel-check/bin/python -m pip install dist/*.whl pytest
|
|
75
|
+
.wheel-check/bin/python -m pip check
|
|
76
|
+
.wheel-check/bin/python -m pytest tests/integration/test_installed_package.py tests/integration/test_vt_forwarding.py tests/unit/test_cli.py
|
|
77
|
+
- name: Stage canonical artifacts and hashes
|
|
78
|
+
run: |
|
|
79
|
+
mkdir -p release-artifact/dist
|
|
80
|
+
cp dist/* release-artifact/dist/
|
|
81
|
+
cd release-artifact
|
|
82
|
+
sha256sum dist/* > SHA256SUMS
|
|
83
|
+
- uses: actions/upload-artifact@v4
|
|
84
|
+
with:
|
|
85
|
+
name: release-dist
|
|
86
|
+
path: release-artifact/
|
|
87
|
+
if-no-files-found: error
|
|
88
|
+
retention-days: 30
|
|
89
|
+
|
|
90
|
+
publish:
|
|
91
|
+
if: inputs.publish
|
|
92
|
+
needs: build
|
|
93
|
+
runs-on: ubuntu-latest
|
|
94
|
+
environment:
|
|
95
|
+
name: pypi
|
|
96
|
+
url: https://pypi.org/p/errlens-cli
|
|
97
|
+
permissions:
|
|
98
|
+
id-token: write
|
|
99
|
+
contents: read
|
|
100
|
+
steps:
|
|
101
|
+
- uses: actions/download-artifact@v4
|
|
102
|
+
with:
|
|
103
|
+
name: release-dist
|
|
104
|
+
path: candidate
|
|
105
|
+
- name: Verify retained bytes
|
|
106
|
+
run: cd candidate && sha256sum --check SHA256SUMS
|
|
107
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
108
|
+
with:
|
|
109
|
+
packages-dir: candidate/dist/
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Tests (macOS manual)
|
|
2
|
+
|
|
3
|
+
on: workflow_dispatch
|
|
4
|
+
|
|
5
|
+
permissions:
|
|
6
|
+
contents: read
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
strategy:
|
|
11
|
+
fail-fast: false
|
|
12
|
+
matrix:
|
|
13
|
+
python: ['3.11', '3.12', '3.13']
|
|
14
|
+
runs-on: ${{ matrix.python == '3.11' && 'macos-15' || 'macos-latest' }}
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: ${{ matrix.python }}
|
|
20
|
+
- name: Verify shell prerequisites
|
|
21
|
+
run: command -v bash && command -v zsh
|
|
22
|
+
- name: Install development package
|
|
23
|
+
run: python -m pip install -e ".[dev]"
|
|
24
|
+
- name: Check types
|
|
25
|
+
run: python -m mypy
|
|
26
|
+
- name: Test editable package
|
|
27
|
+
run: python -m pytest
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on: [push, pull_request]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
test:
|
|
7
|
+
strategy:
|
|
8
|
+
fail-fast: false
|
|
9
|
+
matrix:
|
|
10
|
+
os: [ubuntu-latest, windows-latest]
|
|
11
|
+
python: ['3.11', '3.12', '3.13']
|
|
12
|
+
runs-on: ${{ matrix.os }}
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: ${{ matrix.python }}
|
|
18
|
+
- name: Install Zsh on Ubuntu
|
|
19
|
+
if: runner.os == 'Linux'
|
|
20
|
+
run: sudo apt-get update && sudo apt-get install -y zsh
|
|
21
|
+
- name: Verify shell prerequisites
|
|
22
|
+
if: runner.os != 'Windows'
|
|
23
|
+
run: command -v bash && command -v zsh
|
|
24
|
+
- name: Verify PowerShell prerequisite
|
|
25
|
+
if: runner.os == 'Windows'
|
|
26
|
+
shell: pwsh
|
|
27
|
+
run: if ($PSVersionTable.PSVersion.Major -lt 7) { exit 1 }
|
|
28
|
+
- name: Install development package
|
|
29
|
+
run: python -m pip install -e ".[dev]"
|
|
30
|
+
- name: Check types
|
|
31
|
+
run: python -m mypy
|
|
32
|
+
- name: Test editable package
|
|
33
|
+
run: python -m pytest
|
|
34
|
+
package:
|
|
35
|
+
strategy:
|
|
36
|
+
fail-fast: false
|
|
37
|
+
matrix:
|
|
38
|
+
os: [ubuntu-latest, windows-latest]
|
|
39
|
+
runs-on: ${{ matrix.os }}
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@v4
|
|
42
|
+
- uses: actions/setup-python@v5
|
|
43
|
+
with:
|
|
44
|
+
python-version: '3.12'
|
|
45
|
+
- name: Install build tools
|
|
46
|
+
run: python -m pip install build
|
|
47
|
+
- name: Build wheel and sdist
|
|
48
|
+
run: python -m build
|
|
49
|
+
- name: Create clean wheel environment
|
|
50
|
+
run: python -m venv .venv-wheel
|
|
51
|
+
- name: Test installed wheel outside editable environment
|
|
52
|
+
shell: python
|
|
53
|
+
run: |
|
|
54
|
+
import os
|
|
55
|
+
from pathlib import Path
|
|
56
|
+
import subprocess
|
|
57
|
+
python = Path('.venv-wheel') / ('Scripts/python.exe' if os.name == 'nt' else 'bin/python')
|
|
58
|
+
wheel = next(Path('dist').glob('*.whl'))
|
|
59
|
+
subprocess.run([str(python), '-m', 'pip', 'install', str(wheel), 'pytest'], check=True)
|
|
60
|
+
subprocess.run([str(python), '-m', 'pip', 'check'], check=True)
|
|
61
|
+
subprocess.run([str(python), '-m', 'pytest'], check=True)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
.venv/
|
|
2
|
+
.venv-wheel/
|
|
3
|
+
.venv-release/
|
|
4
|
+
.venv-linux/
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*.egg-info/
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
.mypy_cache/
|
|
10
|
+
build/
|
|
11
|
+
dist/
|
|
12
|
+
.coverage
|
|
13
|
+
htmlcov/
|
|
14
|
+
venv/
|
|
15
|
+
.ruff_cache/
|
|
16
|
+
.env
|
|
17
|
+
.env.*
|
|
18
|
+
!.env.example
|
|
19
|
+
*.log
|
|
20
|
+
*.tmp
|
|
21
|
+
*.bak
|
|
22
|
+
.idea/
|
|
23
|
+
.vscode/
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 — release candidate (unreleased)
|
|
4
|
+
|
|
5
|
+
Initial CLI candidate. The package metadata remains `0.1.0`; no tag, release date
|
|
6
|
+
or PyPI publication is implied by this entry.
|
|
7
|
+
Distribution: `errlens-cli`; Python import: `errlens`; command: `errlens`.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `errlens run` with streaming stdout/stderr, bounded diagnostic capture and
|
|
12
|
+
child exit-status propagation. Pipe is the default.
|
|
13
|
+
- Rule-based offline explanations in Russian and English for recognized CPython
|
|
14
|
+
tracebacks, with conservative handling of incomplete diagnostics and chains.
|
|
15
|
+
- Rich terminal cards and plain redirected explanations; `--lang` and `--no-explain`.
|
|
16
|
+
- Explicit `--terminal-mode pty`: POSIX PTY on Linux/macOS and native ConPTY on Windows.
|
|
17
|
+
- Opt-in PowerShell 7, Bash and Zsh integration for `python`, with explicit
|
|
18
|
+
install/status/uninstall, temporary bypass and profile backup/preservation.
|
|
19
|
+
- MIT licensing, packaged translations, CI across Python 3.11–3.13 on three OSes,
|
|
20
|
+
wheel/sdist checks and recorded terminal acceptance evidence.
|
|
21
|
+
|
|
22
|
+
### Fixed during candidate stabilization
|
|
23
|
+
|
|
24
|
+
- Windows localized Unicode output with non-UTF-8 host text wrappers.
|
|
25
|
+
- Darwin termios assertions account only for kernel-managed PENDIN state.
|
|
26
|
+
- Diagnostic-only VT normalization preserves horizontal traceback indentation,
|
|
27
|
+
with bounded cursor/text expansion and conservative incomplete flags.
|
|
28
|
+
|
|
29
|
+
### Limitations
|
|
30
|
+
|
|
31
|
+
- Terminal mode merges child output and does not preserve binary identity.
|
|
32
|
+
- Full-screen emulation, complex redraw/grapheme reconstruction, transparent
|
|
33
|
+
pipelines and automatic exception cards inside a successful REPL are not provided.
|
|
34
|
+
- Shell integration is explicit and wraps only `python`; it does not intercept
|
|
35
|
+
arbitrary commands. No fixes or recommended commands are executed automatically.
|
|
36
|
+
- Some physical host combinations remain NOT TESTED. The historical Zsh prompt
|
|
37
|
+
observation has no established root cause; a clean Zsh session was successful.
|
|
38
|
+
- The original PyPI name `errlens` conflicts with an existing distribution.
|
|
39
|
+
The maintainer selected `errlens-cli` instead; publication still requires
|
|
40
|
+
Trusted Publisher setup and approval. See `docs/releasing.md`.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Участие в ErrLens
|
|
2
|
+
|
|
3
|
+
Используйте Python 3.11+ и локальное виртуальное окружение. Инструкция установки
|
|
4
|
+
находится в README. Перед предложением изменений запустите:
|
|
5
|
+
|
|
6
|
+
```console
|
|
7
|
+
python -m pytest
|
|
8
|
+
python -m mypy
|
|
9
|
+
python -m build
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Описывайте проблему, область изменений и выполненные проверки. Добавляйте
|
|
13
|
+
регрессионные тесты для исправляемого поведения. Не заявляйте проверку ОС,
|
|
14
|
+
на которой тесты не выполнялись. Не включайте секреты или личные данные в fixtures.
|
|
15
|
+
|
|
16
|
+
Сохраняйте независимость анализаторов от CLI, переводов и ввода-вывода.
|
|
17
|
+
Не выполняйте рекомендации автоматически. Новые переводы должны иметь те же
|
|
18
|
+
ключи и именованные параметры, что и русская локаль. Сторонние плагины и сетевые
|
|
19
|
+
запросы не должны загружаться или запускаться неявно.
|
|
20
|
+
|
|
21
|
+
Текущий CLI включает объяснения, shell-интеграции и явный PTY/ConPTY-режим.
|
|
22
|
+
Команды рекомендаций должны оставаться display-only argv из доверенных правил;
|
|
23
|
+
не подставляйте произвольные имена из traceback в shell-строки. Проверяйте plain
|
|
24
|
+
text, узкие терминалы и буквальный вывод разметки/управляющих символов.
|
|
25
|
+
Следующие возможности реализуются
|
|
26
|
+
отдельно. Изменения распространяются на условиях MIT License проекта.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ErrLens contributors
|
|
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.
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: errlens-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Local Python error explanations with opt-in terminal and shell integration.
|
|
5
|
+
Author: ErrLens contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/ErrLens/errlens-cli
|
|
8
|
+
Project-URL: Source, https://github.com/ErrLens/errlens-cli
|
|
9
|
+
Project-URL: Documentation, https://github.com/ErrLens/errlens-cli/blob/main/README.md
|
|
10
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Requires-Python: >=3.11
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: typer<1,>=0.16
|
|
19
|
+
Requires-Dist: rich<15,>=14
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: pytest<10,>=8; extra == "dev"
|
|
22
|
+
Requires-Dist: build<2,>=1.2; extra == "dev"
|
|
23
|
+
Requires-Dist: mypy<2,>=1.15; extra == "dev"
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# ErrLens
|
|
27
|
+
|
|
28
|
+
ErrLens is a local, open-source CLI that adds readable Russian or English explanations to recognized Python errors. It helps developers understand tracebacks without copying them to an external service. Explanations are rule-based and work offline after installation; no API key or AI model is required.
|
|
29
|
+
|
|
30
|
+
ErrLens runs a command through `errlens run`. Its default pipe mode forwards the original stdout and stderr, then appends an explanation to stderr when an error is recognized. Optional shell wrappers intercept only `python`; explicit terminal mode uses merged terminal output.
|
|
31
|
+
|
|
32
|
+
## Requirements and installation
|
|
33
|
+
|
|
34
|
+
Python 3.11 or newer is required. On Windows, Linux or macOS, install from a local checkout:
|
|
35
|
+
|
|
36
|
+
```console
|
|
37
|
+
python -m pip install .
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
For development, use a virtual environment and install `python -m pip install -e ".[dev]"`. Installing dependencies requires an available package index or local wheels.
|
|
41
|
+
|
|
42
|
+
The PyPI distribution name is **errlens-cli**; the Python import and executable
|
|
43
|
+
are both **errlens**. This candidate has not been uploaded. After publication,
|
|
44
|
+
install with `python -m pip install errlens-cli==0.1.0`, then run `errlens --version`.
|
|
45
|
+
Until then use this checkout or a verified supplied wheel:
|
|
46
|
+
`python -m pip install /path/to/errlens_cli-0.1.0-py3-none-any.whl`.
|
|
47
|
+
The existing PyPI package named `errlens` is not the distribution selected for
|
|
48
|
+
this repository. See [release preparation](https://github.com/ErrLens/errlens-cli/blob/main/docs/releasing.md).
|
|
49
|
+
CI covers CPython 3.11–3.13; newer Python versions are not yet qualified.
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
```console
|
|
54
|
+
errlens --help
|
|
55
|
+
errlens --version
|
|
56
|
+
errlens run python main.py
|
|
57
|
+
errlens run --lang en -- python main.py
|
|
58
|
+
errlens run --no-explain -- python main.py
|
|
59
|
+
errlens run python -c "print(undefined_variable)"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Russian is the default; `--lang en` selects English. Place ErrLens options before the executable; arguments after the executable belong to the child process. `--no-explain` skips analysis. The optional `--` makes the boundary explicit.
|
|
63
|
+
|
|
64
|
+
The original traceback remains visible. For example, a `NameError` can be followed by an explanation that the name is unavailable in the current scope and suggestions to check its spelling and definition. Causes are described as possibilities, not established facts. Successful commands and nonzero exits without recognized diagnostics do not produce an explanation.
|
|
65
|
+
|
|
66
|
+
## Supported diagnostics
|
|
67
|
+
|
|
68
|
+
Rules cover `ModuleNotFoundError`, `ImportError`, `SyntaxError`, `IndentationError`, `TabError`, `NameError`, `TypeError`, `AttributeError`, `KeyError`, `FileNotFoundError` and `PermissionError`. Other structured exceptions receive a neutral notice. Incomplete diagnostics are marked as such; `ExceptionGroup` is summarized at its outer level. For a chain of exceptions, the final diagnostic is explained and linked predecessors are noted.
|
|
69
|
+
|
|
70
|
+
Suggested commands are never executed. A pip command is shown only for the exact `requests` import and an explicitly specified absolute Python executable path, with a condition to confirm that the distribution is actually needed in that environment. Import names do not generally identify package names, and a missing module may be local.
|
|
71
|
+
|
|
72
|
+
## Behavior and limitations
|
|
73
|
+
|
|
74
|
+
- ErrLens launches argument sequences without `shell=True`. Shell pipelines and builtins are interpreted by the invoking shell, not by ErrLens. On Windows, the operating system may invoke a command interpreter for `.bat` or `.cmd` files even with `shell=False`.
|
|
75
|
+
- Separate bounded buffers retain up to 1 MiB per stream for analysis. Original bytes are forwarded as they arrive; the diagnostic copy may be truncated. No output logs are saved to disk.
|
|
76
|
+
- Pipes change `isatty()` and may affect child buffering and colors. Interactive programs, job control and full-screen applications are not guaranteed to work. The relative ordering of stdout and stderr cannot be reconstructed.
|
|
77
|
+
- The child exit code is preserved for normal exits. On POSIX, signal termination becomes `128 + signal`; user interruption returns 130. Runner failures have their own codes: 125 for internal failures, 126 for permission errors, 127 for missing executables and 141 for broken pipes. Child programs can also use these codes; ErrLens identifies its own failures in stderr when possible.
|
|
78
|
+
- In pipe mode, Ctrl+C handling uses a separate process group. Windows pipe cleanup does not guarantee termination of an arbitrary descendant tree. After the child exits, pipes held open by descendants are subject to a one-second drain timeout. ConPTY uses the Job Object cleanup described below.
|
|
79
|
+
- Recognition targets standard CPython traceback formatting; IPython/Jupyter and logger-prefixed tracebacks are not supported. A traceback-like log can be ambiguous. Stdout diagnostics require a failed Python command. Unknown or incomplete data is not presented as a certain cause.
|
|
80
|
+
- Rich markup and terminal control characters from diagnostic data are rendered literally or escaped in the ErrLens block. Redirected explanations are plain text without ANSI. Original child output is not sanitized.
|
|
81
|
+
- Explanation fields are capped at 2,048 characters; linked exception messages at 256 characters. The forwarded traceback is not shortened by this limit.
|
|
82
|
+
- ErrLens does not fix code, install packages, collect telemetry or contact a service. Shell wrappers and terminal mode are explicit opt-ins; VS Code extension support remains future work.
|
|
83
|
+
|
|
84
|
+
## Opt-in PowerShell 7 integration (Windows)
|
|
85
|
+
|
|
86
|
+
```powershell
|
|
87
|
+
errlens shell install powershell
|
|
88
|
+
errlens shell status powershell
|
|
89
|
+
errlens shell uninstall powershell
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Installation explicitly edits the current user's **all-hosts PowerShell 7 profile**
|
|
93
|
+
(shared with VS Code), discovered using `pwsh -NoProfile`. Restart PowerShell after
|
|
94
|
+
installation/removal. ExecutionPolicy is never changed; your policy must allow
|
|
95
|
+
loading the profile and the integration script. No administrator access is needed.
|
|
96
|
+
For an isolated trial or a custom host profile use `--profile 'path/to/profile.ps1'`
|
|
97
|
+
on each management command, then dot-source that profile manually.
|
|
98
|
+
|
|
99
|
+
An owned script is placed in an `ErrLens` subdirectory next to the selected profile.
|
|
100
|
+
Only one guarded dot-source line is appended. Existing profile bytes are preserved;
|
|
101
|
+
each modification of an existing profile creates a uniquely named backup alongside
|
|
102
|
+
it. Backups are retained on removal. Edited connection lines and unowned integration
|
|
103
|
+
files are refused rather than overwritten. A newly created profile is left empty
|
|
104
|
+
after removal. Existing `python` aliases/functions are preserved with a warning.
|
|
105
|
+
|
|
106
|
+
After loading, plain `python main.py`, `python -c "print(undefined_variable)"` and
|
|
107
|
+
`python --version` delegate to `errlens run`. Only the command name `python` is
|
|
108
|
+
wrapped. Absolute executable paths, `py`, pip and other commands bypass it.
|
|
109
|
+
The native Python application is resolved from PATH on every invocation, so venv
|
|
110
|
+
activation is respected. The ErrLens runtime is bound to the absolute Python path
|
|
111
|
+
used during installation; `errlens` need not be in PATH. Keep that environment
|
|
112
|
+
installed. To migrate it, uninstall the integration and reinstall from the new runtime.
|
|
113
|
+
|
|
114
|
+
Temporarily bypass analysis with `$env:ERRLENS_DISABLE='1'`; restore it with
|
|
115
|
+
`Remove-Item Env:ERRLENS_DISABLE`. To remove the wrapper from the current session,
|
|
116
|
+
use `Remove-Item Function:python`. Persistent removal takes effect in new sessions.
|
|
117
|
+
|
|
118
|
+
This is a PowerShell function calling a native program, not transparent terminal
|
|
119
|
+
capture. `$LASTEXITCODE` is explicitly propagated. `$?` may report function success
|
|
120
|
+
even when Python fails; inspect `$LASTEXITCODE`. PowerShell 7.3+ uses Standard
|
|
121
|
+
native argument passing locally inside the wrapper; 7.0–7.2 retain their legacy
|
|
122
|
+
quoting/empty-argument limitations. Global preferences are not changed.
|
|
123
|
+
Pipeline output and `>` pass through PowerShell's object/text conversion and do
|
|
124
|
+
not guarantee byte identity (including PowerShell 7.4 native redirection behavior).
|
|
125
|
+
Pipeline input is not forwarded by this wrapper. Avoid binary pipelines, REPLs,
|
|
126
|
+
interactive and full-screen applications; use an absolute Python executable when
|
|
127
|
+
native semantics are needed. ExecutionPolicy, host-specific profile loading and
|
|
128
|
+
VS Code itself require manual verification on the target machine.
|
|
129
|
+
|
|
130
|
+
## Opt-in Bash and Zsh integration
|
|
131
|
+
|
|
132
|
+
On Linux/macOS, explicitly install with `errlens shell install bash` or
|
|
133
|
+
`errlens shell install zsh`; use `status` or `uninstall` in place of `install`.
|
|
134
|
+
Bash uses `~/.bashrc`; Zsh uses `${ZDOTDIR:-$HOME}/.zshrc`. Bash login shells
|
|
135
|
+
do not necessarily load `.bashrc`: configure your login profile to source it
|
|
136
|
+
yourself if needed. These are interactive startup files; noninteractive shells
|
|
137
|
+
do not automatically load them. `--profile PATH` selects an isolated/custom file.
|
|
138
|
+
|
|
139
|
+
An owned script in `.errlens` beside the profile is sourced by one guarded line.
|
|
140
|
+
Existing profile bytes are retained, changes receive unique backups, repeated
|
|
141
|
+
installation is idempotent, and removal removes only the exact owned line and script.
|
|
142
|
+
Edited lines and unowned scripts are refused. Backups remain after removal.
|
|
143
|
+
Existing `python` functions and aliases take precedence and are preserved.
|
|
144
|
+
|
|
145
|
+
The `python` function resolves the external interpreter and `errlens` on each
|
|
146
|
+
invocation, forwards `"$@"`, working directory and exit status, and respects an
|
|
147
|
+
activated virtual environment. `ERRLENS_DISABLE=1 python ...` bypasses analysis;
|
|
148
|
+
if ErrLens is absent from PATH, the native Python is run directly. Use `unset -f
|
|
149
|
+
python` to disable the wrapper in the current shell. `command python`, an absolute
|
|
150
|
+
path, `python3`, pip and other commands bypass it. Restart or source the profile
|
|
151
|
+
after installation; restart or unset the function after uninstallation.
|
|
152
|
+
|
|
153
|
+
When starting Zsh from Bash with an active virtual environment, the Bash
|
|
154
|
+
activation script may have modified and exported prompt variables. Bash prompt
|
|
155
|
+
escapes are not Zsh prompt syntax and may appear literally. Start a clean Zsh,
|
|
156
|
+
then run `source /path/to/venv/bin/activate` within Zsh. The ErrLens integration
|
|
157
|
+
does not change `PS1` or `PROMPT`; your Zsh configuration can define its own prompt.
|
|
158
|
+
Manual reports of Windows 11/PowerShell and Ubuntu 24.04/WSL Bash and Zsh are
|
|
159
|
+
distinct from the automated CI checks; consult CI results for verified runs.
|
|
160
|
+
|
|
161
|
+
Redirection and pipelines follow the shell and `errlens run` pipe semantics.
|
|
162
|
+
Input is inherited, but interactive/terminal-dependent programs and exact stdout/
|
|
163
|
+
stderr interleaving are not guaranteed. Ctrl+C follows Runner process-group handling;
|
|
164
|
+
PTY and job-control equivalence are not guaranteed. Paths with spaces and Unicode
|
|
165
|
+
are quoted without `eval`. No system profiles or shell settings are modified.
|
|
166
|
+
|
|
167
|
+
## Explicit terminal mode
|
|
168
|
+
|
|
169
|
+
Use `errlens run --terminal-mode pty -- python script.py` when terminal stdin
|
|
170
|
+
and stdout are available. Linux/macOS use POSIX PTY; Windows 10 1809+ and Windows
|
|
171
|
+
11 use native ConPTY. Pipe remains the default, including all shell wrappers.
|
|
172
|
+
A transport error never triggers an automatic second run. Windows requires
|
|
173
|
+
actual console handles and a native executable (.exe or .com), with no batch
|
|
174
|
+
file or legacy winpty fallback. No extra runtime dependency or compiler is needed.
|
|
175
|
+
|
|
176
|
+
Terminal mode supplies a terminal, input, window-size propagation and terminal
|
|
177
|
+
Ctrl+C handling. stdout and stderr merge onto ErrLens stdout; echo and LF-to-CRLF
|
|
178
|
+
conversion are normal terminal behavior. Binary identity and original stream
|
|
179
|
+
separation are not guaranteed. Redirected host stdin/stdout are rejected; use
|
|
180
|
+
pipe mode for pipelines. The combined diagnostic tail is limited to 1 MiB.
|
|
181
|
+
Recognized failed Python commands receive one explanation on stderr after terminal
|
|
182
|
+
restoration. Interactive REPL exceptions followed by a successful exit do not
|
|
183
|
+
produce cards. ANSI forwarding is supported, but screen reconstruction, job-control
|
|
184
|
+
transparency, suspended children and arbitrary full-screen applications are not
|
|
185
|
+
guaranteed. A permanently blocked output sink can still block forwarding.
|
|
186
|
+
|
|
187
|
+
The host terminal modes and signal handlers are saved and restored on ordinary
|
|
188
|
+
exit, cancellation and transport errors. SIGKILL or a host crash cannot provide
|
|
189
|
+
that guarantee. POSIX processes that deliberately detach from the session may
|
|
190
|
+
outlive cleanup. ConPTY clients belong to a kill-on-close Windows Job Object:
|
|
191
|
+
remaining descendants are terminated when the main client ends or transport fails.
|
|
192
|
+
Windows uses a separate, short-lived owner process to bound ConPTY shutdown on
|
|
193
|
+
older Windows builds. Input/output are UTF-8/VT text, so invalid bytes, NUL, cursor
|
|
194
|
+
movement, wrapping and screen redraws need not survive as original log bytes.
|
|
195
|
+
The analyzer strips ANSI but does not reconstruct a screen; complex redraws can
|
|
196
|
+
produce incomplete or unrecognized diagnostics.
|
|
197
|
+
|
|
198
|
+
Automated tests use isolated real ConPTY sessions and nested console handles on
|
|
199
|
+
Windows, and nested POSIX PTYs on Linux and in the manual macOS workflow. User-reported manual checks
|
|
200
|
+
cover Windows Terminal and VS Code ConPTY plus selected WSL Bash/Zsh sessions;
|
|
201
|
+
the [acceptance record](https://github.com/ErrLens/errlens-cli/blob/main/docs/manual-acceptance.md) preserves untested combinations.
|
|
202
|
+
Legacy console hosts, detailed REPL editing, Windows 10 lifecycle behavior and
|
|
203
|
+
physical macOS hosts are not fully manually qualified. See
|
|
204
|
+
[Windows ConPTY notes](https://github.com/ErrLens/errlens-cli/blob/main/docs/windows-conpty.md) for lifecycle details.
|
|
205
|
+
|
|
206
|
+
## Development and checks
|
|
207
|
+
|
|
208
|
+
```console
|
|
209
|
+
python -m pytest
|
|
210
|
+
python -m mypy
|
|
211
|
+
python -m pip check
|
|
212
|
+
python -m build
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
The build creates a wheel and source distribution in `dist/`. GitHub Actions #6
|
|
216
|
+
passed all 11 jobs for `84dbb9c927b1b0eaf3ac6efc50863b9f0ef72836`, covering
|
|
217
|
+
Windows, Ubuntu and macOS on Python 3.11–3.13 plus Windows/Ubuntu wheel installation.
|
|
218
|
+
Hosted macOS runners were unavailable in [CI #8](https://github.com/ErrLens/errlens-cli/actions/runs/43235376928).
|
|
219
|
+
The required Tests workflow temporarily runs Linux and Windows on Python 3.11–3.13
|
|
220
|
+
and both packaging jobs. macOS tests remain available through a separate manual
|
|
221
|
+
workflow. Earlier macOS passes apply to their tested commits. The release candidate
|
|
222
|
+
has yet to be tested on macOS. The [release guide](https://github.com/ErrLens/errlens-cli/blob/main/docs/releasing.md)
|
|
223
|
+
records when to restore macOS to the required matrix. The manual publishing workflow
|
|
224
|
+
can retain candidate artifacts for review.
|
|
225
|
+
|
|
226
|
+
See [CONTRIBUTING.md](https://github.com/ErrLens/errlens-cli/blob/main/CONTRIBUTING.md) for contribution guidance. ErrLens is distributed under the [MIT License](https://github.com/ErrLens/errlens-cli/blob/main/LICENSE).
|
|
227
|
+
|
|
228
|
+
## Roadmap
|
|
229
|
+
|
|
230
|
+
The current CLI focuses on local Python diagnostics, localized explanations,
|
|
231
|
+
opt-in shell wrappers and explicit terminal sessions. Future stages may improve
|
|
232
|
+
terminal compatibility and add VS Code integration, additional analyzers and
|
|
233
|
+
optional AI providers. Those future features are not part of the current CLI.
|