Skip to content

Commit d1d0ce5

Browse files
committed
init
0 parents  commit d1d0ce5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+5593
-0
lines changed

.github/workflows/ci.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
9+
jobs:
10+
test:
11+
runs-on: ${{ matrix.os }}
12+
strategy:
13+
fail-fast: false
14+
matrix:
15+
python-version: ["3.9", "3.10", "3.11", "3.12"]
16+
os: [ubuntu-latest, macos-latest, windows-latest]
17+
18+
steps:
19+
- uses: actions/checkout@v4
20+
21+
- name: Install uv and set Python version
22+
uses: astral-sh/setup-uv@v7
23+
with:
24+
python-version: ${{ matrix.python-version }}
25+
enable-cache: true
26+
27+
- name: Install dependencies
28+
run: uv sync --locked --all-extras --dev
29+
30+
- name: Run linter and static analysis
31+
run: uv run pre-commit run --all-files
32+
33+
- name: Run tests
34+
run: uv run pytest

.github/workflows/docs.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Deploy Documentation
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
pages: write
11+
id-token: write
12+
13+
concurrency:
14+
group: "pages"
15+
cancel-in-progress: false
16+
17+
jobs:
18+
build:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
24+
- name: Install uv and set Python version
25+
uses: astral-sh/setup-uv@v7
26+
with:
27+
python-version: "3.12"
28+
enable-cache: true
29+
30+
- name: Install dependencies
31+
run: uv sync --locked --all-extras --dev
32+
33+
- name: Setup Pages
34+
uses: actions/configure-pages@v5
35+
36+
- name: Build documentation with pdoc
37+
run: |
38+
uv run pdoc src/lsp_client --output-dir dist --docformat google
39+
40+
- name: Upload artifact
41+
uses: actions/upload-pages-artifact@v3
42+
with:
43+
path: ./dist
44+
45+
deploy:
46+
environment:
47+
name: github-pages
48+
url: ${{ steps.deployment.outputs.page_url }}
49+
runs-on: ubuntu-latest
50+
needs: build
51+
steps:
52+
- name: Deploy to GitHub Pages
53+
id: deployment
54+
uses: actions/deploy-pages@v4

.github/workflows/publish.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
permissions:
8+
id-token: write # This is required for trusted publishing
9+
10+
jobs:
11+
build:
12+
name: Build distribution
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
- name: Set up Python
17+
uses: actions/setup-python@v5
18+
with:
19+
python-version: "3.9"
20+
- name: Install build dependencies
21+
run: python -m pip install build
22+
- name: Build sdist and wheel
23+
run: python -m build
24+
- name: Store the distribution packages
25+
uses: actions/upload-artifact@v4
26+
with:
27+
name: python-package-distributions
28+
path: dist/
29+
30+
publish-to-pypi:
31+
name: Publish to PyPI
32+
needs: [build]
33+
runs-on: ubuntu-latest
34+
environment:
35+
name: pypi
36+
url: https://pypi.org/p/lsp-client # Replace with your package name
37+
steps:
38+
- name: Download all the dists
39+
uses: actions/download-artifact@v4
40+
with:
41+
name: python-package-distributions
42+
path: dist/
43+
- name: Publish package to PyPI
44+
uses: pypa/gh-action-pypi-publish@release/v1

.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*.so
5+
*.egg-info/
6+
build/
7+
dist/
8+
9+
# Testing
10+
.coverage
11+
.pytest_cache/
12+
htmlcov/
13+
14+
# Environments
15+
.venv
16+
.env
17+
.python-version
18+
19+
# IDE
20+
.idea/
21+
.vscode/
22+
23+
# OS
24+
.DS_Store
25+
Thumbs.db
26+
27+
# Cache
28+
*_cache

.pre-commit-config.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
repos:
2+
- repo: https://github.com/astral-sh/ruff-pre-commit
3+
rev: v0.14.4
4+
hooks:
5+
- id: ruff
6+
args: [--fix]
7+
- id: ruff-format

AGENTS.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# AGENTS.md
2+
3+
## Development Commands
4+
5+
- Lint & format: `ruff check --fix && ruff format`
6+
- Type checking: `mypy src/`
7+
- Run all tests: `pytest`
8+
- Run single test: `pytest path/to/test.py::test_function`
9+
- Run integration tests: `pytest -m integration`
10+
- Run pyright tests: `pytest -m pyright`
11+
12+
## Code Style Guidelines
13+
14+
- Python: 3.12+ required, use `from __future__ import annotations`
15+
- Imports: Use isort (handled by ruff), group stdlib, third-party, local imports
16+
- Formatting: Double quotes, space indentation (handled by ruff format)
17+
- Types: Full type annotations required, use `lsp_type` alias for LSP types
18+
- Naming: snake_case for variables/functions, PascalCase for classes
19+
- Error handling: Use tenacity for retries, anyio.fail_after for timeouts
20+
- Async: Use async/await, asyncer.TaskGroup for concurrency
21+
- Structure: Follow capability-based protocol pattern in capability/ module

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Wang Bowei
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.

README.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# LSP Client
2+
3+
[![Python](https://img.shields.io/badge/Python-3.12+-blue.svg)](https://python.org)
4+
[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
5+
6+
A full-featured, well-typed, and easy-to-use Python client for the Language Server Protocol (LSP). This library provides a clean, async-first interface for interacting with language servers, supporting both local and Docker-based runtimes.
7+
8+
## Features
9+
10+
- **🚀 Async-first Design**: Built for high-performance concurrent operations
11+
- **🔧 Full LSP Support**: Comprehensive implementation of LSP 3.17 specification
12+
- **🐳 Docker Support**: Run language servers in isolated containers
13+
- **📝 Type Safety**: Full type annotations with Pydantic validation
14+
- **🧩 Modular Architecture**: Mixin-based capability system for easy extension
15+
- **🎯 Production Ready**: Robust error handling with tenacity retries
16+
- **📚 Well Documented**: Extensive documentation and examples
17+
18+
## Quick Start
19+
20+
### Installation
21+
22+
```bash
23+
uv add lsp-client
24+
```
25+
26+
### Basic Usage
27+
28+
```python
29+
from pathlib import Path
30+
import anyio
31+
from lsp_client import Position
32+
from lsp_client.clients.pyright import PyrightClient
33+
34+
async def main():
35+
# Use current directory as workspace
36+
async with PyrightClient(workspace=Path.cwd()) as client:
37+
# Find definition of something at line 11, character 28 in a file
38+
refs = await client.request_definition_locations(
39+
file_path="src/main.py",
40+
position=Position(11, 28) # line 12, character 29 (1-indexed)
41+
)
42+
43+
if not refs:
44+
print("No definition found.")
45+
return
46+
47+
for ref in refs:
48+
print(f"Found definition at: {ref.uri}")
49+
50+
if __name__ == "__main__":
51+
anyio.run(main)
52+
```
53+
54+
### Docker-based Language Server
55+
56+
```python
57+
from pathlib import Path
58+
import anyio
59+
from lsp_client.clients.pyright import PyrightClient, PyrightServer, PyrightDockerRuntime
60+
61+
async def main():
62+
workspace = Path.cwd()
63+
async with PyrightClient(
64+
workspace=workspace,
65+
server=PyrightServer(
66+
runtime=PyrightDockerRuntime(mounts=[workspace]),
67+
),
68+
) as client:
69+
# Find definition of something at line 11, character 28 in a file
70+
refs = await client.request_definition_locations(
71+
file_path="src/main.py",
72+
position=Position(11, 28)
73+
)
74+
75+
if not refs:
76+
print("No definition found.")
77+
return
78+
79+
for ref in refs:
80+
print(f"Found definition at: {ref.uri}")
81+
82+
if __name__ == "__main__":
83+
anyio.run(main)
84+
```
85+
86+
## Supported Language Servers
87+
88+
The library includes pre-configured clients for popular language servers:
89+
90+
| Language Server | Module Path | Language |
91+
| --------------- | ---------------------------------- | --------------------- |
92+
| Pyright | `lsp_client.clients.pyright` | Python |
93+
| Pyrefly | `lsp_client.clients.pyrefly` | Python |
94+
| Rust Analyzer | `lsp_client.clients.rust_analyzer` | Rust |
95+
| Deno | `lsp_client.clients.deno` | TypeScript/JavaScript |
96+
97+
## Contributing
98+
99+
We welcome contributions! Please see our [Contributing Guide](docs/contribution/) for details.
100+
101+
## License
102+
103+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
104+
105+
## Acknowledgments
106+
107+
- Built on the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) specification
108+
- Uses [lsprotocol](https://github.com/microsoft/lsprotocol) for LSP type definitions
109+
- Inspired by [multilspy](https://github.com/microsoft/multilspy) and other LSP clients

0 commit comments

Comments
 (0)