pytest-language-server 0.17.3__py3-none-win_amd64.whl
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.
- pytest_language_server-0.17.3.data/scripts/pytest-language-server.exe +0 -0
- pytest_language_server-0.17.3.dist-info/METADATA +743 -0
- pytest_language_server-0.17.3.dist-info/RECORD +5 -0
- pytest_language_server-0.17.3.dist-info/WHEEL +4 -0
- pytest_language_server-0.17.3.dist-info/licenses/LICENSE +21 -0
|
Binary file
|
|
@@ -0,0 +1,743 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pytest-language-server
|
|
3
|
+
Version: 0.17.3
|
|
4
|
+
Classifier: Development Status :: 4 - Beta
|
|
5
|
+
Classifier: Intended Audience :: Developers
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
13
|
+
Classifier: Programming Language :: Rust
|
|
14
|
+
Classifier: Topic :: Software Development :: Testing
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Summary: A blazingly fast Language Server Protocol implementation for pytest
|
|
18
|
+
Keywords: pytest,lsp,language-server,testing
|
|
19
|
+
Author-email: Thiago Bellini Ribeiro <hackedbellini@gmail.com>
|
|
20
|
+
License: MIT
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
23
|
+
Project-URL: Homepage, https://github.com/bellini666/pytest-language-server
|
|
24
|
+
Project-URL: Repository, https://github.com/bellini666/pytest-language-server
|
|
25
|
+
Project-URL: Issues, https://github.com/bellini666/pytest-language-server/issues
|
|
26
|
+
|
|
27
|
+
# pytest-language-server 🔥
|
|
28
|
+
|
|
29
|
+
[](https://github.com/bellini666/pytest-language-server/actions/workflows/ci.yml)
|
|
30
|
+
[](https://github.com/bellini666/pytest-language-server/actions/workflows/security.yml)
|
|
31
|
+
[](https://badge.fury.io/py/pytest-language-server)
|
|
32
|
+
[](https://pepy.tech/project/pytest-language-server)
|
|
33
|
+
[](https://crates.io/crates/pytest-language-server)
|
|
34
|
+
[](https://opensource.org/licenses/MIT)
|
|
35
|
+
[](https://pypi.org/project/pytest-language-server/)
|
|
36
|
+
|
|
37
|
+
A blazingly fast Language Server Protocol (LSP) implementation for pytest, built with Rust, with
|
|
38
|
+
full support for fixture discovery, go to definition, code completion, find references, hover
|
|
39
|
+
documentation, diagnostics, and more!
|
|
40
|
+
|
|
41
|
+
[](demo/demo.mp4)
|
|
42
|
+
|
|
43
|
+
## Table of Contents
|
|
44
|
+
|
|
45
|
+
- [Features](#features)
|
|
46
|
+
- [Go to Definition](#-go-to-definition)
|
|
47
|
+
- [Go to Implementation](#-go-to-implementation)
|
|
48
|
+
- [Call Hierarchy](#-call-hierarchy)
|
|
49
|
+
- [Code Completion](#-code-completion)
|
|
50
|
+
- [Find References](#-find-references)
|
|
51
|
+
- [Hover Documentation](#-hover-documentation)
|
|
52
|
+
- [Document Symbols](#-document-symbols)
|
|
53
|
+
- [Workspace Symbols](#-workspace-symbols)
|
|
54
|
+
- [Code Lens](#-code-lens)
|
|
55
|
+
- [Code Actions (Quick Fixes)](#-code-actions-quick-fixes)
|
|
56
|
+
- [Diagnostics & Quick Fixes](#️-diagnostics--quick-fixes)
|
|
57
|
+
- [Performance](#️-performance)
|
|
58
|
+
- [Installation](#installation)
|
|
59
|
+
- [Setup](#setup)
|
|
60
|
+
- [Neovim](#neovim)
|
|
61
|
+
- [Zed](#zed)
|
|
62
|
+
- [VS Code](#vs-code)
|
|
63
|
+
- [IntelliJ IDEA / PyCharm](#intellij-idea--pycharm)
|
|
64
|
+
- [Other Editors](#other-editors)
|
|
65
|
+
- [Configuration](#configuration)
|
|
66
|
+
- [CLI Commands](#cli-commands)
|
|
67
|
+
- [Supported Fixture Patterns](#supported-fixture-patterns)
|
|
68
|
+
- [Fixture Priority Rules](#fixture-priority-rules)
|
|
69
|
+
- [Supported Third-Party Fixtures](#supported-third-party-fixtures)
|
|
70
|
+
- [Architecture](#architecture)
|
|
71
|
+
- [Development](#development)
|
|
72
|
+
- [Security](#security)
|
|
73
|
+
- [Contributing](#contributing)
|
|
74
|
+
- [License](#license)
|
|
75
|
+
- [Acknowledgments](#acknowledgments)
|
|
76
|
+
|
|
77
|
+
## Features
|
|
78
|
+
|
|
79
|
+
> **Built with AI, maintained with care** 🤖
|
|
80
|
+
>
|
|
81
|
+
> This project was built with the help of AI coding agents, but carefully reviewed to ensure
|
|
82
|
+
> correctness, reliability, security and performance. If you find any issues, please open an issue
|
|
83
|
+
> or submit a pull request!
|
|
84
|
+
|
|
85
|
+
### 🎯 Go to Definition
|
|
86
|
+
Jump directly to fixture definitions from anywhere they're used:
|
|
87
|
+
- Local fixtures in the same file
|
|
88
|
+
- Fixtures in `conftest.py` files
|
|
89
|
+
- Third-party fixtures from pytest plugins (pytest-mock, pytest-asyncio, etc.)
|
|
90
|
+
- Respects pytest's fixture shadowing/priority rules
|
|
91
|
+
|
|
92
|
+
### 🔧 Go to Implementation
|
|
93
|
+
Jump to the yield statement in generator fixtures:
|
|
94
|
+
- **Generator fixtures**: Navigates to where `yield` produces the fixture value
|
|
95
|
+
- **Teardown navigation**: Useful for reviewing fixture cleanup logic
|
|
96
|
+
- **Non-generator fallback**: Falls back to definition for simple return-based fixtures
|
|
97
|
+
|
|
98
|
+
Example:
|
|
99
|
+
```python
|
|
100
|
+
@pytest.fixture
|
|
101
|
+
def database():
|
|
102
|
+
conn = connect()
|
|
103
|
+
yield conn # <-- Go to Implementation jumps here
|
|
104
|
+
conn.close() # Teardown code after yield
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 🔗 Call Hierarchy
|
|
108
|
+
Explore fixture dependencies with Call Hierarchy support:
|
|
109
|
+
- **Incoming Calls**: See which tests and fixtures depend on a fixture
|
|
110
|
+
- **Outgoing Calls**: See which fixtures a fixture depends on
|
|
111
|
+
- Works with your editor's "Show Call Hierarchy" command
|
|
112
|
+
- Helps understand complex fixture dependency chains
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
@pytest.fixture
|
|
116
|
+
def database(): # <-- Call Hierarchy shows:
|
|
117
|
+
... # Incoming: test_query, test_insert (tests using this)
|
|
118
|
+
# Outgoing: connection (fixtures this depends on)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### ✨ Code Completion
|
|
122
|
+
Smart auto-completion for pytest fixtures:
|
|
123
|
+
- **Context-aware**: Only triggers inside test functions and fixture functions
|
|
124
|
+
- **Hierarchy-respecting**: Suggests fixtures based on pytest's priority rules (same file > conftest.py > third-party)
|
|
125
|
+
- **Rich information**: Shows fixture source file and docstring
|
|
126
|
+
- **No duplicates**: Automatically filters out shadowed fixtures
|
|
127
|
+
- **Works everywhere**: Completions available in both function parameters and function bodies
|
|
128
|
+
- Supports both sync and async functions
|
|
129
|
+
|
|
130
|
+
### 🔍 Find References
|
|
131
|
+
Find all usages of a fixture across your entire test suite:
|
|
132
|
+
- Works from fixture definitions or usage sites
|
|
133
|
+
- Character-position aware (distinguishes between fixture name and parameters)
|
|
134
|
+
- Shows references in all test files
|
|
135
|
+
- Correctly handles fixture overriding and hierarchies
|
|
136
|
+
- **LSP spec compliant**: Always includes the current position in results
|
|
137
|
+
|
|
138
|
+
### 📚 Hover Documentation
|
|
139
|
+
View fixture information on hover:
|
|
140
|
+
- Fixture signature
|
|
141
|
+
- Source file location
|
|
142
|
+
- Docstring (with proper formatting and dedenting)
|
|
143
|
+
- Markdown support in docstrings
|
|
144
|
+
|
|
145
|
+
### 📑 Document Symbols
|
|
146
|
+
Navigate fixtures within a file using the document outline:
|
|
147
|
+
- **File outline view**: See all fixtures defined in the current file (Cmd+Shift+O / Ctrl+Shift+O)
|
|
148
|
+
- **Breadcrumb navigation**: Shows fixture hierarchy in editor breadcrumbs
|
|
149
|
+
- **Return type display**: Shows fixture return types when available
|
|
150
|
+
- **Sorted by position**: Fixtures appear in definition order
|
|
151
|
+
|
|
152
|
+
### 🔎 Workspace Symbols
|
|
153
|
+
Search for fixtures across your entire workspace:
|
|
154
|
+
- **Global search**: Find any fixture by name (Cmd+T / Ctrl+T)
|
|
155
|
+
- **Fuzzy matching**: Case-insensitive substring search
|
|
156
|
+
- **File context**: Shows which file each fixture is defined in
|
|
157
|
+
- **Fast lookup**: Instant results from in-memory fixture database
|
|
158
|
+
|
|
159
|
+
### 🔢 Code Lens
|
|
160
|
+
See fixture usage counts directly in your editor:
|
|
161
|
+
- **Usage count**: Shows "N usages" above each fixture definition
|
|
162
|
+
- **Click to navigate**: Clicking the lens shows all references (find-references integration)
|
|
163
|
+
- **Real-time updates**: Counts update as you add/remove fixture usages
|
|
164
|
+
- **Local fixtures only**: Only shows lenses for project fixtures, not third-party
|
|
165
|
+
|
|
166
|
+
### 🏷️ Inlay Hints
|
|
167
|
+
See fixture return types inline without leaving your code:
|
|
168
|
+
- **Type annotations**: Shows return types next to fixture parameters (e.g., `db: Database`)
|
|
169
|
+
- **Explicit types only**: Only displays hints when fixtures have explicit return type annotations
|
|
170
|
+
- **Generator support**: Extracts yielded type from `Generator[T, None, None]` annotations
|
|
171
|
+
- **Non-intrusive**: Hints appear as subtle inline decorations that don't modify your code
|
|
172
|
+
|
|
173
|
+
Example:
|
|
174
|
+
```python
|
|
175
|
+
# With a fixture defined as:
|
|
176
|
+
@pytest.fixture
|
|
177
|
+
def database() -> Database:
|
|
178
|
+
return Database()
|
|
179
|
+
|
|
180
|
+
# In your test, you'll see:
|
|
181
|
+
def test_example(database): # Shows ": Database" after "database"
|
|
182
|
+
pass
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### 💡 Code Actions (Quick Fixes)
|
|
186
|
+
One-click fixes for common pytest issues:
|
|
187
|
+
- **Add missing fixture parameters**: Automatically add undeclared fixtures to function signatures
|
|
188
|
+
- **Smart insertion**: Handles both empty and existing parameter lists
|
|
189
|
+
- **Editor integration**: Works with any LSP-compatible editor's quick fix menu
|
|
190
|
+
- **LSP compliant**: Full support for `CodeActionKind::QUICKFIX`
|
|
191
|
+
|
|
192
|
+
### ⚠️ Diagnostics & Quick Fixes
|
|
193
|
+
Detect and fix common pytest fixture issues with intelligent code actions:
|
|
194
|
+
|
|
195
|
+
**Fixture Scope Validation:**
|
|
196
|
+
- Detects when a broader-scoped fixture depends on a narrower-scoped fixture
|
|
197
|
+
- Example: A `session`-scoped fixture cannot depend on a `function`-scoped fixture
|
|
198
|
+
- Warnings show both the fixture's scope and its dependency's scope
|
|
199
|
+
- Prevents hard-to-debug test failures from scope violations
|
|
200
|
+
|
|
201
|
+
**Circular Dependency Detection:**
|
|
202
|
+
- Detects when fixtures form circular dependency chains (A → B → C → A)
|
|
203
|
+
- Reports the full cycle path for easy debugging
|
|
204
|
+
- Works across files (conftest.py hierarchies)
|
|
205
|
+
|
|
206
|
+
Scope mismatch example:
|
|
207
|
+
```python
|
|
208
|
+
# ⚠️ Scope mismatch! session-scoped fixture depends on function-scoped
|
|
209
|
+
@pytest.fixture(scope="session")
|
|
210
|
+
def shared_db(temp_dir): # temp_dir is function-scoped
|
|
211
|
+
return Database(temp_dir)
|
|
212
|
+
|
|
213
|
+
@pytest.fixture # Default is function scope
|
|
214
|
+
def temp_dir(tmp_path):
|
|
215
|
+
return tmp_path / "test"
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**Undeclared Fixture Detection:**
|
|
219
|
+
- Detects when fixtures are used in function bodies but not declared as parameters
|
|
220
|
+
- **Line-aware scoping**: Correctly handles local variables assigned later in the function
|
|
221
|
+
- **Hierarchy-aware**: Only reports fixtures that are actually available in the current file's scope
|
|
222
|
+
- **Works in tests and fixtures**: Detects undeclared usage in both test functions and fixture functions
|
|
223
|
+
- Excludes built-in names (`self`, `request`) and actual local variables
|
|
224
|
+
|
|
225
|
+
**One-Click Quick Fixes:**
|
|
226
|
+
- **Code actions** to automatically add missing fixture parameters
|
|
227
|
+
- Intelligent parameter insertion (handles both empty and existing parameter lists)
|
|
228
|
+
- Works with both single-line and multi-line function signatures
|
|
229
|
+
- Triggered directly from diagnostic warnings
|
|
230
|
+
|
|
231
|
+
Example:
|
|
232
|
+
```python
|
|
233
|
+
@pytest.fixture
|
|
234
|
+
def user_db():
|
|
235
|
+
return Database()
|
|
236
|
+
|
|
237
|
+
def test_user(user_db): # ✅ user_db properly declared
|
|
238
|
+
user = user_db.get_user(1)
|
|
239
|
+
assert user.name == "Alice"
|
|
240
|
+
|
|
241
|
+
def test_broken(): # ⚠️ Warning: 'user_db' used but not declared
|
|
242
|
+
user = user_db.get_user(1) # 💡 Quick fix: Add 'user_db' fixture parameter
|
|
243
|
+
assert user.name == "Alice"
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**How to use quick fixes:**
|
|
247
|
+
1. Place cursor on the warning squiggle
|
|
248
|
+
2. Trigger code actions menu (usually Cmd+. or Ctrl+. in most editors)
|
|
249
|
+
3. Select "Add 'fixture_name' fixture parameter"
|
|
250
|
+
4. The parameter is automatically added to your function signature
|
|
251
|
+
|
|
252
|
+
### ⚡️ Performance
|
|
253
|
+
Built with Rust for maximum performance:
|
|
254
|
+
- Fast workspace scanning with concurrent file processing
|
|
255
|
+
- Efficient AST parsing using rustpython-parser
|
|
256
|
+
- Lock-free data structures with DashMap
|
|
257
|
+
- Minimal memory footprint
|
|
258
|
+
|
|
259
|
+
## Installation
|
|
260
|
+
|
|
261
|
+
Choose your preferred installation method:
|
|
262
|
+
|
|
263
|
+
### 📦 PyPI (Recommended)
|
|
264
|
+
|
|
265
|
+
The easiest way to install for Python projects:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
# Using uv (recommended)
|
|
269
|
+
uv tool install pytest-language-server
|
|
270
|
+
|
|
271
|
+
# Or with pip
|
|
272
|
+
pip install pytest-language-server
|
|
273
|
+
|
|
274
|
+
# Or with pipx (isolated environment)
|
|
275
|
+
pipx install pytest-language-server
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### 🍺 Homebrew (macOS/Linux)
|
|
279
|
+
|
|
280
|
+
Install via Homebrew for system-wide availability:
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
brew install bellini666/tap/pytest-language-server
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
To add the tap first:
|
|
287
|
+
```bash
|
|
288
|
+
brew tap bellini666/tap https://github.com/bellini666/pytest-language-server
|
|
289
|
+
brew install pytest-language-server
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### 🦀 Cargo (Rust)
|
|
293
|
+
|
|
294
|
+
Install from crates.io if you have Rust installed:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
cargo install pytest-language-server
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### 📥 Pre-built Binaries
|
|
301
|
+
|
|
302
|
+
Download pre-built binaries from the [GitHub Releases](https://github.com/bellini666/pytest-language-server/releases) page.
|
|
303
|
+
|
|
304
|
+
Available for:
|
|
305
|
+
- **Linux**: x86_64, aarch64, armv7 (glibc and musl)
|
|
306
|
+
- **macOS**: Intel and Apple Silicon
|
|
307
|
+
- **Windows**: x64 and x86
|
|
308
|
+
|
|
309
|
+
### 🔨 From Source
|
|
310
|
+
|
|
311
|
+
Build from source for development or customization:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
git clone https://github.com/bellini666/pytest-language-server
|
|
315
|
+
cd pytest-language-server
|
|
316
|
+
cargo build --release
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
The binary will be at `target/release/pytest-language-server`.
|
|
320
|
+
|
|
321
|
+
## Setup
|
|
322
|
+
|
|
323
|
+
### Neovim
|
|
324
|
+
|
|
325
|
+
Add this to your config:
|
|
326
|
+
|
|
327
|
+
```lua
|
|
328
|
+
vim.lsp.config('pytest_lsp', {
|
|
329
|
+
cmd = { 'pytest-language-server' },
|
|
330
|
+
filetypes = { 'python' },
|
|
331
|
+
root_markers = { 'pyproject.toml', 'setup.py', 'setup.cfg', 'pytest.ini', '.git' },
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
vim.lsp.enable('pytest_lsp')
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Zed
|
|
338
|
+
|
|
339
|
+
Install from the [Zed Extensions Marketplace](https://zed.dev/extensions/pytest-language-server):
|
|
340
|
+
|
|
341
|
+
1. Open Zed
|
|
342
|
+
2. Open the command palette (Cmd+Shift+P / Ctrl+Shift+P)
|
|
343
|
+
3. Search for "zed: extensions"
|
|
344
|
+
4. Search for "pytest Language Server"
|
|
345
|
+
5. Click "Install"
|
|
346
|
+
|
|
347
|
+
The extension downloads platform-specific binaries from GitHub Releases. If you prefer to use your own installation (via pip, cargo, or brew), place `pytest-language-server` in your PATH.
|
|
348
|
+
|
|
349
|
+
After installing the extension, you need to enable the language server for Python files. Add the following to your Zed `settings.json`:
|
|
350
|
+
|
|
351
|
+
```json
|
|
352
|
+
{
|
|
353
|
+
"languages": {
|
|
354
|
+
"Python": {
|
|
355
|
+
"language_servers": ["pyright", "pytest-language-server", "..."]
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### VS Code
|
|
362
|
+
|
|
363
|
+
**The extension includes pre-built binaries - no separate installation required!**
|
|
364
|
+
|
|
365
|
+
Install from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=bellini666.pytest-language-server):
|
|
366
|
+
|
|
367
|
+
1. Open VS Code
|
|
368
|
+
2. Go to Extensions (Cmd+Shift+X / Ctrl+Shift+X)
|
|
369
|
+
3. Search for "pytest Language Server"
|
|
370
|
+
4. Click "Install"
|
|
371
|
+
|
|
372
|
+
Works out of the box with zero configuration!
|
|
373
|
+
|
|
374
|
+
### IntelliJ IDEA / PyCharm
|
|
375
|
+
|
|
376
|
+
**The plugin includes pre-built binaries - no separate installation required!**
|
|
377
|
+
|
|
378
|
+
Install from the [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/29056-pytest-language-server):
|
|
379
|
+
|
|
380
|
+
1. Open PyCharm or IntelliJ IDEA
|
|
381
|
+
2. Go to Settings/Preferences → Plugins
|
|
382
|
+
3. Search for "pytest Language Server"
|
|
383
|
+
4. Click "Install"
|
|
384
|
+
|
|
385
|
+
Requires PyCharm 2024.2+ or IntelliJ IDEA 2024.2+ with Python plugin.
|
|
386
|
+
|
|
387
|
+
### Other Editors
|
|
388
|
+
|
|
389
|
+
Any editor with LSP support can use pytest-language-server. Configure it to run the `pytest-language-server` command.
|
|
390
|
+
|
|
391
|
+
## Configuration
|
|
392
|
+
|
|
393
|
+
### pyproject.toml
|
|
394
|
+
|
|
395
|
+
Configure pytest-language-server via your project's `pyproject.toml`:
|
|
396
|
+
|
|
397
|
+
```toml
|
|
398
|
+
[tool.pytest-language-server]
|
|
399
|
+
# Glob patterns for files/directories to exclude from scanning
|
|
400
|
+
exclude = ["build/**", "dist/**", ".tox/**"]
|
|
401
|
+
|
|
402
|
+
# Disable specific diagnostics
|
|
403
|
+
# Valid codes: "undeclared-fixture", "scope-mismatch", "circular-dependency"
|
|
404
|
+
disabled_diagnostics = ["undeclared-fixture"]
|
|
405
|
+
|
|
406
|
+
# Additional directories to scan for fixtures (planned feature)
|
|
407
|
+
fixture_paths = ["fixtures/", "shared/fixtures/"]
|
|
408
|
+
|
|
409
|
+
# Third-party plugins to skip when scanning venv (planned feature)
|
|
410
|
+
skip_plugins = ["pytest-xdist"]
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
**Available Options:**
|
|
414
|
+
|
|
415
|
+
| Option | Type | Description |
|
|
416
|
+
|--------|------|-------------|
|
|
417
|
+
| `exclude` | `string[]` | Glob patterns for paths to exclude from workspace scanning |
|
|
418
|
+
| `disabled_diagnostics` | `string[]` | Diagnostic codes to suppress |
|
|
419
|
+
| `fixture_paths` | `string[]` | Additional fixture directories *(planned)* |
|
|
420
|
+
| `skip_plugins` | `string[]` | Third-party plugins to skip *(planned)* |
|
|
421
|
+
|
|
422
|
+
**Diagnostic Codes:**
|
|
423
|
+
- `undeclared-fixture` - Fixture used in function body but not declared as parameter
|
|
424
|
+
- `scope-mismatch` - Broader-scoped fixture depends on narrower-scoped fixture
|
|
425
|
+
- `circular-dependency` - Circular fixture dependency detected
|
|
426
|
+
|
|
427
|
+
### Logging
|
|
428
|
+
|
|
429
|
+
Control log verbosity with the `RUST_LOG` environment variable:
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
# Minimal logging (default)
|
|
433
|
+
RUST_LOG=warn pytest-language-server
|
|
434
|
+
|
|
435
|
+
# Info level
|
|
436
|
+
RUST_LOG=info pytest-language-server
|
|
437
|
+
|
|
438
|
+
# Debug level (verbose)
|
|
439
|
+
RUST_LOG=debug pytest-language-server
|
|
440
|
+
|
|
441
|
+
# Trace level (very verbose)
|
|
442
|
+
RUST_LOG=trace pytest-language-server
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
Logs are written to stderr, so they won't interfere with LSP communication.
|
|
446
|
+
|
|
447
|
+
### Virtual Environment Detection
|
|
448
|
+
|
|
449
|
+
The server automatically detects your Python virtual environment:
|
|
450
|
+
1. Checks for `.venv/`, `venv/`, or `env/` in your project root
|
|
451
|
+
2. Falls back to `$VIRTUAL_ENV` environment variable
|
|
452
|
+
3. Scans third-party pytest plugins for fixtures
|
|
453
|
+
|
|
454
|
+
### Code Actions / Quick Fixes
|
|
455
|
+
|
|
456
|
+
Code actions are automatically available on diagnostic warnings. If code actions don't appear in your editor:
|
|
457
|
+
|
|
458
|
+
1. **Check LSP capabilities**: Ensure your editor supports code actions (most modern editors do)
|
|
459
|
+
2. **Enable debug logging**: Use `RUST_LOG=info` to see if actions are being created
|
|
460
|
+
3. **Verify diagnostics**: Code actions only appear where there are warnings
|
|
461
|
+
4. **Trigger manually**: Use your editor's code action keybinding (Cmd+. / Ctrl+.)
|
|
462
|
+
|
|
463
|
+
## CLI Commands
|
|
464
|
+
|
|
465
|
+
In addition to the LSP server mode, pytest-language-server provides useful command-line tools:
|
|
466
|
+
|
|
467
|
+
### Fixtures List
|
|
468
|
+
|
|
469
|
+
View all fixtures in your test suite with a hierarchical tree view:
|
|
470
|
+
|
|
471
|
+
```bash
|
|
472
|
+
# List all fixtures
|
|
473
|
+
pytest-language-server fixtures list tests/
|
|
474
|
+
|
|
475
|
+
# Skip unused fixtures
|
|
476
|
+
pytest-language-server fixtures list tests/ --skip-unused
|
|
477
|
+
|
|
478
|
+
# Show only unused fixtures
|
|
479
|
+
pytest-language-server fixtures list tests/ --only-unused
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
The output includes:
|
|
483
|
+
- **Color-coded display**: Files in cyan, directories in blue, used fixtures in green, unused in gray
|
|
484
|
+
- **Usage statistics**: Shows how many times each fixture is used
|
|
485
|
+
- **Smart filtering**: Hides files and directories with no matching fixtures
|
|
486
|
+
- **Hierarchical structure**: Visualizes fixture organization across conftest.py files
|
|
487
|
+
|
|
488
|
+
Example output:
|
|
489
|
+
```
|
|
490
|
+
Fixtures tree for: /path/to/tests
|
|
491
|
+
|
|
492
|
+
conftest.py (7 fixtures)
|
|
493
|
+
├── another_fixture (used 2 times)
|
|
494
|
+
├── cli_runner (used 7 times)
|
|
495
|
+
├── database (used 6 times)
|
|
496
|
+
├── generator_fixture (used 1 time)
|
|
497
|
+
├── iterator_fixture (unused)
|
|
498
|
+
├── sample_fixture (used 7 times)
|
|
499
|
+
└── shared_resource (used 5 times)
|
|
500
|
+
subdir/
|
|
501
|
+
└── conftest.py (4 fixtures)
|
|
502
|
+
├── cli_runner (used 7 times)
|
|
503
|
+
├── database (used 6 times)
|
|
504
|
+
├── local_fixture (used 4 times)
|
|
505
|
+
└── sample_fixture (used 7 times)
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
This command is useful for:
|
|
509
|
+
- **Auditing fixture usage** across your test suite
|
|
510
|
+
- **Finding unused fixtures** that can be removed
|
|
511
|
+
- **Understanding fixture organization** and hierarchy
|
|
512
|
+
- **Documentation** - visualizing available fixtures for developers
|
|
513
|
+
|
|
514
|
+
### Fixtures Unused
|
|
515
|
+
|
|
516
|
+
Find unused fixtures in your test suite, with CI-friendly exit codes:
|
|
517
|
+
|
|
518
|
+
```bash
|
|
519
|
+
# List unused fixtures (text format)
|
|
520
|
+
pytest-language-server fixtures unused tests/
|
|
521
|
+
|
|
522
|
+
# JSON output for programmatic use
|
|
523
|
+
pytest-language-server fixtures unused tests/ --format json
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
**Exit codes:**
|
|
527
|
+
- `0`: All fixtures are used
|
|
528
|
+
- `1`: Unused fixtures found
|
|
529
|
+
|
|
530
|
+
Example text output:
|
|
531
|
+
```
|
|
532
|
+
Found 4 unused fixture(s):
|
|
533
|
+
|
|
534
|
+
• iterator_fixture in conftest.py
|
|
535
|
+
• auto_cleanup in utils/conftest.py
|
|
536
|
+
• temp_dir in utils/conftest.py
|
|
537
|
+
• temp_file in utils/conftest.py
|
|
538
|
+
|
|
539
|
+
Tip: Remove unused fixtures or add tests that use them.
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
Example JSON output:
|
|
543
|
+
```json
|
|
544
|
+
[
|
|
545
|
+
{"file": "conftest.py", "fixture": "iterator_fixture"},
|
|
546
|
+
{"file": "utils/conftest.py", "fixture": "auto_cleanup"},
|
|
547
|
+
{"file": "utils/conftest.py", "fixture": "temp_dir"},
|
|
548
|
+
{"file": "utils/conftest.py", "fixture": "temp_file"}
|
|
549
|
+
]
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
This command is ideal for:
|
|
553
|
+
- **CI/CD pipelines** - fail builds when unused fixtures accumulate
|
|
554
|
+
- **Code cleanup** - identify dead code in test infrastructure
|
|
555
|
+
- **Linting** - integrate with pre-commit hooks or quality gates
|
|
556
|
+
|
|
557
|
+
## Supported Fixture Patterns
|
|
558
|
+
|
|
559
|
+
### Decorator Style
|
|
560
|
+
```python
|
|
561
|
+
@pytest.fixture
|
|
562
|
+
def my_fixture():
|
|
563
|
+
"""Fixture docstring."""
|
|
564
|
+
return 42
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
### Assignment Style (pytest-mock)
|
|
568
|
+
```python
|
|
569
|
+
mocker = pytest.fixture()(_mocker)
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
### Async Fixtures
|
|
573
|
+
```python
|
|
574
|
+
@pytest.fixture
|
|
575
|
+
async def async_fixture():
|
|
576
|
+
return await some_async_operation()
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
### Fixture Dependencies
|
|
580
|
+
```python
|
|
581
|
+
@pytest.fixture
|
|
582
|
+
def fixture_a():
|
|
583
|
+
return "a"
|
|
584
|
+
|
|
585
|
+
@pytest.fixture
|
|
586
|
+
def fixture_b(fixture_a): # Go to definition works on fixture_a
|
|
587
|
+
return fixture_a + "b"
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
### @pytest.mark.usefixtures
|
|
591
|
+
```python
|
|
592
|
+
@pytest.mark.usefixtures("database", "cache")
|
|
593
|
+
class TestWithFixtures:
|
|
594
|
+
def test_something(self):
|
|
595
|
+
pass # database and cache are available
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
### @pytest.mark.parametrize with indirect
|
|
599
|
+
```python
|
|
600
|
+
@pytest.fixture
|
|
601
|
+
def user(request):
|
|
602
|
+
return User(name=request.param)
|
|
603
|
+
|
|
604
|
+
# All parameters treated as fixtures
|
|
605
|
+
@pytest.mark.parametrize("user", ["alice", "bob"], indirect=True)
|
|
606
|
+
def test_user(user):
|
|
607
|
+
pass
|
|
608
|
+
|
|
609
|
+
# Selective indirect fixtures
|
|
610
|
+
@pytest.mark.parametrize("user,value", [("alice", 1)], indirect=["user"])
|
|
611
|
+
def test_user_value(user, value):
|
|
612
|
+
pass
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
## Fixture Priority Rules
|
|
616
|
+
|
|
617
|
+
pytest-language-server correctly implements pytest's fixture shadowing rules:
|
|
618
|
+
1. **Same file**: Fixtures defined in the same file have highest priority
|
|
619
|
+
2. **Closest conftest.py**: Searches parent directories for conftest.py files
|
|
620
|
+
3. **Virtual environment**: Third-party plugin fixtures
|
|
621
|
+
|
|
622
|
+
### Fixture Overriding
|
|
623
|
+
|
|
624
|
+
The LSP correctly handles complex fixture overriding scenarios:
|
|
625
|
+
|
|
626
|
+
```python
|
|
627
|
+
# conftest.py (parent)
|
|
628
|
+
@pytest.fixture
|
|
629
|
+
def cli_runner():
|
|
630
|
+
return "parent runner"
|
|
631
|
+
|
|
632
|
+
# tests/conftest.py (child)
|
|
633
|
+
@pytest.fixture
|
|
634
|
+
def cli_runner(cli_runner): # Overrides parent
|
|
635
|
+
return cli_runner # Uses parent
|
|
636
|
+
|
|
637
|
+
# tests/test_example.py
|
|
638
|
+
def test_example(cli_runner): # Uses child
|
|
639
|
+
pass
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
When using find-references:
|
|
643
|
+
- Clicking on the **function name** `def cli_runner(...)` shows references to the child fixture
|
|
644
|
+
- Clicking on the **parameter** `cli_runner(cli_runner)` shows references to the parent fixture
|
|
645
|
+
- Character-position aware to distinguish between the two
|
|
646
|
+
|
|
647
|
+
## Supported Third-Party Fixtures
|
|
648
|
+
|
|
649
|
+
Automatically discovers fixtures from **50+ popular pytest plugins**, including:
|
|
650
|
+
|
|
651
|
+
- **Testing frameworks**: pytest-mock, pytest-asyncio, pytest-bdd, pytest-cases
|
|
652
|
+
- **Web frameworks**: pytest-flask, pytest-django, pytest-aiohttp, pytest-tornado, pytest-sanic, pytest-fastapi
|
|
653
|
+
- **HTTP clients**: pytest-httpx
|
|
654
|
+
- **Databases**: pytest-postgresql, pytest-mongodb, pytest-redis, pytest-mysql, pytest-elasticsearch
|
|
655
|
+
- **Infrastructure**: pytest-docker, pytest-kubernetes, pytest-rabbitmq, pytest-celery
|
|
656
|
+
- **Browser testing**: pytest-selenium, pytest-playwright, pytest-splinter
|
|
657
|
+
- **Performance**: pytest-benchmark, pytest-timeout
|
|
658
|
+
- **Test data**: pytest-factoryboy, pytest-freezegun, pytest-mimesis
|
|
659
|
+
- And many more...
|
|
660
|
+
|
|
661
|
+
The server automatically scans your virtual environment for any pytest plugin and makes their fixtures available.
|
|
662
|
+
|
|
663
|
+
## Architecture
|
|
664
|
+
|
|
665
|
+
- **Language**: Rust 🦀
|
|
666
|
+
- **LSP Framework**: tower-lsp-server
|
|
667
|
+
- **Parser**: rustpython-parser
|
|
668
|
+
- **Concurrency**: tokio async runtime
|
|
669
|
+
- **Data Structures**: DashMap for lock-free concurrent access
|
|
670
|
+
|
|
671
|
+
## Development
|
|
672
|
+
|
|
673
|
+
### Prerequisites
|
|
674
|
+
|
|
675
|
+
- Rust 1.85+ (2021 edition)
|
|
676
|
+
- Python 3.10+ (for testing)
|
|
677
|
+
|
|
678
|
+
### Building
|
|
679
|
+
|
|
680
|
+
```bash
|
|
681
|
+
cargo build --release
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
### Running Tests
|
|
685
|
+
|
|
686
|
+
```bash
|
|
687
|
+
cargo test
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
### Logging During Development
|
|
691
|
+
|
|
692
|
+
```bash
|
|
693
|
+
RUST_LOG=debug cargo run
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
## Security
|
|
697
|
+
|
|
698
|
+
Security is a priority. This project includes:
|
|
699
|
+
- Automated dependency vulnerability scanning (cargo-audit)
|
|
700
|
+
- License compliance checking (cargo-deny)
|
|
701
|
+
- Daily security audits in CI/CD
|
|
702
|
+
- Dependency review on pull requests
|
|
703
|
+
- Pre-commit security hooks
|
|
704
|
+
|
|
705
|
+
See [SECURITY.md](SECURITY.md) for our security policy and how to report vulnerabilities.
|
|
706
|
+
|
|
707
|
+
## Contributing
|
|
708
|
+
|
|
709
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
710
|
+
|
|
711
|
+
### Development Setup
|
|
712
|
+
|
|
713
|
+
1. Install pre-commit hooks:
|
|
714
|
+
```bash
|
|
715
|
+
pre-commit install
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
2. Run security checks locally:
|
|
719
|
+
```bash
|
|
720
|
+
cargo audit
|
|
721
|
+
cargo clippy
|
|
722
|
+
cargo test
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
## License
|
|
726
|
+
|
|
727
|
+
MIT License - see LICENSE file for details.
|
|
728
|
+
|
|
729
|
+
## Acknowledgments
|
|
730
|
+
|
|
731
|
+
Built with:
|
|
732
|
+
- [tower-lsp-server](https://github.com/tower-lsp-community/tower-lsp-server) - LSP framework
|
|
733
|
+
- [rustpython-parser](https://github.com/RustPython/RustPython) - Python AST parsing
|
|
734
|
+
- [tokio](https://tokio.rs/) - Async runtime
|
|
735
|
+
|
|
736
|
+
Special thanks to the pytest team for creating such an amazing testing framework.
|
|
737
|
+
|
|
738
|
+
---
|
|
739
|
+
|
|
740
|
+
**Made with ❤️ and Rust. Blazingly fast 🔥**
|
|
741
|
+
|
|
742
|
+
*Built with AI assistance, maintained with care.*
|
|
743
|
+
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
pytest_language_server-0.17.3.data/scripts/pytest-language-server.exe,sha256=_WRVqKrX0cWdKceBi_WMDvziBNXSVLGrbm589BgDObE,9040384
|
|
2
|
+
pytest_language_server-0.17.3.dist-info/METADATA,sha256=fZykqqdAZ39iZn5KUkphXO5VwJXjwLHK8lxM8P8T5ic,25098
|
|
3
|
+
pytest_language_server-0.17.3.dist-info/WHEEL,sha256=14-pPWiwFoCAtTgD4hWnxHSfZQqe6Zt0DfwcROvwlzs,94
|
|
4
|
+
pytest_language_server-0.17.3.dist-info/licenses/LICENSE,sha256=rIv127_3ZUtmHMK0ZZ8uieKKo4BhFxMKytwy3RstKIk,1100
|
|
5
|
+
pytest_language_server-0.17.3.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Thiago Bellini Ribeiro
|
|
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.
|