Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,16 @@ jobs:
- name: Publish package
if: startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@81e9d935c883d0b210363ab89cf05f3894778450
- name: Build documentation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to build the docs in GitHub Actions. RTD can build the docs with just build instructions in .readthedocs.yaml, which is what the rope repository did.

If we do have some legitimate reason to build docs here, the same reason probably applies to the rope repository as well.

if: startsWith(github.ref, 'refs/tags')
run: |
cd doc
pip install sphinx sphinx-rtd-theme myst-parser
sphinx-build -b html . _build/html
- name: Deploy documentation
if: startsWith(github.ref, 'refs/tags')
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./doc/_build/html
destination_dir: docs
20 changes: 20 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

version: 2

# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.9"

# Build documentation in the "doc/" directory with Sphinx
sphinx:
configuration: doc/conf.py

# Optionally declare the Python requirements required to build your docs
python:
install:
- requirements: doc/requirements.txt
199 changes: 65 additions & 134 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,170 +2,101 @@

[![Tests](https://github.com/python-rope/pylsp-rope/actions/workflows/run-test.yml/badge.svg)](https://github.com/python-rope/pylsp-rope/actions/workflows/run-test.yml)
[![codecov](https://codecov.io/gh/python-rope/pylsp-rope/graph/badge.svg?token=LMO7PW0AEK)](https://codecov.io/gh/python-rope/pylsp-rope)
[![Documentation](https://readthedocs.org/projects/pylsp-rope/badge/?version=latest)](https://pylsp-rope.readthedocs.io/en/latest/?badge=latest)
[![PyPI version](https://badge.fury.io/py/pylsp-rope.svg)](https://badge.fury.io/py/pylsp-rope)

Extended refactoring capabilities for Python LSP Server using
[Rope](https://github.com/python-rope/rope).
Extended refactoring capabilities for Python LSP Server using [Rope](https://github.com/python-rope/rope).

This is a plugin for [Python LSP
Server](https://github.com/python-lsp/python-lsp-server), so you also need to
have it installed.
This is a plugin for [Python LSP Server](https://github.com/python-lsp/python-lsp-server), so you also need to have it installed.

python-lsp-server already has basic built-in support for using Rope, but it's
currently limited to just renaming and completion. Installing this plugin adds
more refactoring functionality to python-lsp-server.

## Installation

To use this plugin, you need to install this plugin in the same virtualenv as
python-lsp-server itself.

``` bash
pip install pylsp-rope
```

Then run `pylsp` as usual, the plugin will be auto-discovered by
python-lsp-server if you've installed it to the right environment. On Vim,
refer to [Rope in Vim or
Neovim](https://github.com/python-rope/rope/wiki/Rope-in-Vim-or-Neovim). For
other editors, refer to your IDE/text editor's documentation on how to setup a
language server.
python-lsp-server already has basic built-in support for using Rope, but it's currently limited to just renaming and completion. Installing this plugin adds more refactoring functionality to python-lsp-server.

## Features

This plugin adds the following features to python-lsp-server:

Rename:

- implemented: variables, classes, functions (disabled by default)
- coming soon: modules, packages (disabled by default)

Code Action:

- extract method
- extract variable
- inline method/variable/parameter
- use function
- method to method object
- convert local variable to field
- organize imports
- introduce parameter
- generate variable/function/class from undefined variable

Refer to [Rope documentation](https://github.com/python-rope/rope/blob/master/docs/overview.rst)
for more details on how these refactoring works.

## Usage

### Rename

When Rename is triggered, rename the symbol under the cursor. If the symbol
under the cursor points to a module/package, it will move that module/package
files.

### Extract method

Variants:

- Extract method
- Extract global method
- Extract method including similar statements
- Extract global method including similar statements
- **Enhanced Rename**: Advanced cross-file renaming with Rope's refactoring engine
- **Code Actions**: 12+ refactoring operations including extract method, inline, use function, and more
- **Code Generation**: Create variables, functions, and classes from undefined symbols
- **Import Organization**: Automatic cleanup and sorting of imports
- **Local to Field**: Convert local variables to class attributes

When CodeAction is triggered and the cursor is on any block of code, extract
that expression into a method. Optionally, similar statements can also be
extracted.
## Quick Start

### Extract variable
### Installation

Variants:
Install pylsp-rope in the same virtualenv as python-lsp-server:

- Extract variable
- Extract global variable
- Extract variable including similar statements
- Extract global variable including similar statements

When CodeAction is triggered and the cursor is on a expression, extract that
expression into a variable. Optionally, similar statements can also be
extracted.

### Inline

When CodeAction is triggered and the cursor is on a resolvable Python variable,
replace all calls to that method with the method body.

### Use function

When CodeAction is triggered and the cursor is on the function name of a `def`
statement, try to replace code whose AST matches the selected function with a
call to the function.

### Method to method object

When CodeAction is triggered and the cursor is on the function name of a `def`
statement, create a callable class to replace that method. You may want to
inline the method afterwards to remove the indirection.

### Convert local variable to field

When CodeAction is triggered wand the cursor is on a local variable inside a
method, convert that local variable to an attribute.

### Organize import

Trigger CodeAction anywhere in a Python file to organize imports.
```bash
pip install pylsp-rope
```

### Introduce parameter
### Basic Configuration

When CodeAction is triggered and the cursor is selecting a Python variable or
attribute, make that variable/attribute a parameter.
Add to your LSP configuration:

### Generate code
```json
{
"pylsp": {
"plugins": {
"pylsp_rope": {
"enabled": true
}
}
}
}
```

Variants:
### Enable Rename Support

For advanced rename functionality, enable it explicitly:

```json
{
"pylsp": {
"plugins": {
"pylsp_rope": {
"enabled": true,
"rename": true
}
}
}
}
```

- [x] Generate variable
- [x] Generate function
- [x] Generate class
- [ ] Generate module
- [ ] Generate package
## Documentation

When CodeAction is triggered and the cursor is on an undefined Python
variable, generate an empty variable/function/class/module/package for that
name.
Complete documentation is available at **[pylsp-rope.readthedocs.io](https://pylsp-rope.readthedocs.io/)**

## Configuration
- **[Installation Guide](https://pylsp-rope.readthedocs.io/en/latest/installation.html)** - Setup for various editors
- **[Configuration Guide](https://pylsp-rope.readthedocs.io/en/latest/configuration.html)** - Complete configuration options
- **[Features Overview](https://pylsp-rope.readthedocs.io/en/latest/features.html)** - Detailed feature descriptions
- **[Usage Examples](https://pylsp-rope.readthedocs.io/en/latest/usage.html)** - Practical examples
- **[Troubleshooting](https://pylsp-rope.readthedocs.io/en/latest/troubleshooting.html)** - Common issues and solutions

You can enable rename support using pylsp-rope with workspace config key
`pylsp.plugins.pylsp_rope.rename`.
## Available Refactorings

Note that this differs from the config key `pylsp.plugins.rope_rename.enabled`
that is used for the rope rename implementation using the python-lsp-rope's
builtin `rope_rename` plugin. To avoid confusion, avoid enabling more than one
python-lsp-server rename plugin. In other words, you should set both
`pylsp.plugins.rope_rename.enabled = false` and `pylsp.plugins.jedi_rename.enabled = false`
when pylsp-rope rename is enabled.
| Category | Operations |
|----------|------------|
| **Extract** | Method, Variable (with similar statement support) |
| **Inline** | Method, Variable, Parameter |
| **Restructure** | Use Function, Method to Method Object, Local to Field |
| **Generate** | Variable, Function, Class |
| **Utilities** | Organize Imports, Introduce Parameter |
| **Rename** | Enhanced cross-file renaming (Rope-based) |

## Caveat

Support for working on unsaved document is currently experimental, but it should work.
Support for working on unsaved documents is currently experimental, but it should work.

This plugin is in early development, so expect some bugs. Please report in
[Github issue tracker](https://github.com/python-lsp/python-lsp-server/issues)
if you had any issues with the plugin.
This plugin is in early development, so expect some bugs. Please report in the [GitHub issue tracker](https://github.com/python-lsp/python-lsp-server/issues) if you have any issues with the plugin.

## Developing
## Contributing

See [CONTRIBUTING.md](https://github.com/python-rope/pylsp-rope/blob/main/CONTRIBUTING.md).

## Packaging status

[![Packaging status](https://repology.org/badge/vertical-allrepos/python:pylsp-rope.svg)](https://repology.org/project/python:pylsp-rope/versions)

[![Packaging status](https://repology.org/badge/vertical-allrepos/python:lsp-rope.svg)](https://repology.org/project/python:lsp-rope/versions)

## Credits

This package was created with
[Cookiecutter](https://github.com/audreyr/cookiecutter) from
[python-lsp/cookiecutter-pylsp-plugin](https://github.com/python-lsp/cookiecutter-pylsp-plugin)
project template.
This package was created with [Cookiecutter](https://github.com/audreyr/cookiecutter) from [python-lsp/cookiecutter-pylsp-plugin](https://github.com/python-lsp/cookiecutter-pylsp-plugin) project template.
1 change: 1 addition & 0 deletions doc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_build/*
89 changes: 89 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Sphinx configuration file

import os
import sys

# Add project root to Python path for autodoc
sys.path.insert(0, os.path.abspath(".."))

# -- Project information --
project = "pylsp-rope"
copyright = "2024, pylsp-rope contributors"
author = "pylsp-rope contributors"
release = "0.1.4"

# -- General configuration --
extensions = [
"myst_parser", # Markdown support
"sphinx.ext.autodoc",
"sphinx.ext.viewcode",
"sphinx.ext.napoleon",
]

# MyST parser configuration
myst_enable_extensions = [
"colon_fence",
"deflist",
"html_admonition",
"linkify",
"replacements",
"smartquotes",
"substitution",
"tasklist",
]

# -- Options for HTML output --
html_theme = "sphinx_rtd_theme"
html_static_path = []
html_theme_options = {
"canonical_url": "",
"analytics_id": "",
"logo_only": False,
"prev_next_buttons_location": "bottom",
"style_external_links": False,
"collapse_navigation": True,
"sticky_navigation": True,
"navigation_depth": 4,
"includehidden": True,
"titles_only": False,
}

# -- Master document --
master_doc = "index"

# -- Exclude patterns --
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]

# -- Options for other output formats --
htmlhelp_basename = "pylsp-ropedoc"
latex_documents = [
(
master_doc,
"pylsp-rope.tex",
"pylsp-rope Documentation",
"pylsp-rope contributors",
"manual",
),
]

man_pages = [(master_doc, "pylsp-rope", "pylsp-rope Documentation", [author], 1)]

texinfo_documents = [
(
master_doc,
"pylsp-rope",
"pylsp-rope Documentation",
author,
"pylsp-rope",
"One line description of project.",
"Miscellaneous",
),
]

# -- Exclude patterns --
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]

# -- ReadTheDocs specific configuration --
# When building on ReadTheDocs, these environment variables are available
if os.environ.get("READTHEDOCS") == "True":
html_theme = "sphinx_rtd_theme"
Loading