Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/github_actions/actions/checkout-4
Browse files Browse the repository at this point in the history
  • Loading branch information
EeyoreLee authored Jan 10, 2025
2 parents 0a377a4 + 696f67b commit a420a80
Show file tree
Hide file tree
Showing 22 changed files with 4,470 additions and 1,814 deletions.
56 changes: 56 additions & 0 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: setup

inputs:
node_version:
description: 'Version of Node to install'
required: true

runs:
using: 'composite'
steps:
- name: Install Node
uses: actions/setup-node@v3
with:
node-version: ${{ inputs.node_version }}
cache: 'npm'

- name: Use Python 3.8
uses: actions/setup-python@v4
with:
python-version: 3.8

- name: Pip lib cache
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-build-vsix-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-build-vsix-
- name: Pip tool cache
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-build-vsix-${{ hashFiles('**/requirements-tool.txt') }}
restore-keys: |
${{ runner.os }}-pip-build-vsix-tool
- name: Upgrade pip
run: python -m pip install -U pip
shell: bash

- name: Install build pre-requisite
run: python -m pip install wheel
shell: bash

- name: Install nox
run: python -m pip install nox
shell: bash

- name: Run npm ci
run: npm ci --prefer-offline
shell: bash

- name: Install bundled python packages
run: python -m nox -s install_package
shell: bash
10 changes: 5 additions & 5 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
python: ['3.8', '3.9', '3.10', '3.11']
python: ['3.9', '3.10', '3.11', '3.12', '3.13']

steps:
- name: Checkout
Expand All @@ -30,10 +30,10 @@ jobs:
path: ${{ env.special-working-directory-relative }}

# Install bundled libs using 3.8 even though you test it on other versions.
- name: Use Python 3.8
uses: actions/setup-python@v4
- name: Use Python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.8'
python-version: '3.10'

- name: Update pip, install wheel and nox
run: python -m pip install -U pip wheel nox
Expand All @@ -47,7 +47,7 @@ jobs:
# Now that the bundle is installed to target using python 3.8
# switch back the python we want to test with
- name: Use Python ${{ matrix.python }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}

Expand Down
38 changes: 38 additions & 0 deletions .github/workflows/prerelease.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: prerelease

on:
pull_request:
types:
- closed
branches:
- 'main'
paths:
- 'bundled/**'
- 'src/**'
- '!src/test/**'

env:
NODE_VERSION: 16.19.0

jobs:
if_merged:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: setup
uses: ./.github/actions/setup
with:
node_version: ${{ env.NODE_VERSION}}

- name: Update extension build number
run: |
commit_time=`git show --pretty=format:"%ci" | head -1`
python -m nox -s update_build_number -- "$commit_time"
- name: Publish prerelease VSIX
run: npm run vsce-publish-prerelease ${{ secrets.MARKETPLACE_ACCESS_TOKEN }}
shell: bash
31 changes: 31 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: release

on:
schedule:
- cron: '0 1 1 */3 *'


env:
NODE_VERSION: 16.19.0

jobs:
release:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: setup
uses: ./.github/actions/setup
with:
node_version: ${{ env.NODE_VERSION}}

- name: Update extension build number
run: |
commit_time=`git show --pretty=format:"%ci" | head -1`
python -m nox -s update_build_number -- "$commit_time" release
- name: Publish prerelease VSIX
run: npm run vsce-publish-release ${{ secrets.MARKETPLACE_ACCESS_TOKEN }}
shell: bash
3 changes: 0 additions & 3 deletions .style.yapf

This file was deleted.

37 changes: 30 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@

A formatter extension with support for python files and notebook cell. Feel free to open an issue to tell me what feature else do you need since it's a preview version.
Note:
* This extension is supported for all [actively supported versions](https://devguide.python.org/versions/#supported-versions) of the python language (i.e., python >= 3.8(EOL: 2024-10)).
* This extension is supported for all [actively supported versions](https://devguide.python.org/versions/#supported-versions) of the python language (i.e., python >= 3.9(EOL: 2025-10)).

## Quick Start
Setting the following can enable this formatter quickly.
```
"[python]": {
"editor.formatOnSaveMode": "file",
"editor.formatOnSave": true,
"editor.defaultFormatter": "eeyore.yapf"
"editor.defaultFormatter": "eeyore.yapf",
"editor.formatOnType": false
}
```


## Usage
* Install `yapf` package from pip in following. This is optional but recommended way, else it will use the bundled `yapf=0.40.2`
* Install `yapf` package from pip in following. This is optional but recommended way, else it will use the bundled `yapf=0.43.0`
```
pip install yapf
```
Expand All @@ -26,17 +27,17 @@ pip install yapf
"editor.defaultFormatter": "eeyore.yapf"
}
```
and change the following, the reason see [issue#13](https://github.com/EeyoreLee/vscode-extension-yapf/issues/13)
```
"python.formatting.provider": "none"
```
* Enable format on save by adding the following
```
"[python]": {
"editor.formatOnSave": true
}
```

## Address crash for python3.8 or lower
Use `yapf.interpreter` property to select a python interpreter that 3.9 or higher to run this tool by subprocess


## file mode & modifications mode
Choose the mode by the following
* Use file mode
Expand All @@ -63,8 +64,30 @@ Choose the mode by the following
```

## Set your own yapf style
Note this setting has to be in the global scope of `settings.json`, not in a `[python]` block.

* Set style by the following vscode settings which is equal to `yapf --style '{based_on_style: pep8, indent_width: 2}'`
```
"yapf.args": ["--style", "{based_on_style: pep8, indent_width: 2}"]
```

* Use a style file, like `.style.yapf`, `setup.cfg`, `pyproject.toml`, `~/.config/yapf/style`. For details, see [google/yapf](https://github.com/google/yapf)
```
"yapf.args": ["--style", "/home/example/.yapf"]
```

## Add extra magic function for jupyter
This extension supports the following magic functions by default
```
"capture",
"prun",
"pypy",
"python",
"python3",
"time",
"timeit"
```
Other magic functions like %matplotlib inline, you need to add it to the `yapf.cellMagics` property.
```
"yapf.cellMagics": ["matplotlib inline"]
```
74 changes: 74 additions & 0 deletions bundled/tool/lsp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import ast
import copy
import importlib
import json
import os
import pathlib
Expand Down Expand Up @@ -59,6 +60,37 @@ def update_sys_path(libs_path: str, tool_libs_path: str, strategy: str) -> None:
TOOL_ARGS = [] # default arguments always passed to your tool.


@LSP_SERVER.feature(lsp.TEXT_DOCUMENT_ON_TYPE_FORMATTING,
lsp.DocumentOnTypeFormattingOptions(first_trigger_character="\n"))
def on_type_formatting(params: lsp.DocumentFormattingParams) -> Optional[list[lsp.TextEdit]]:
document = LSP_SERVER.workspace.get_document(params.text_document.uri)
source = document.source.replace("\r\n", "\n")
if not document.lines[params.position.line - 1].rstrip(" \t\n") or \
document.lines[params.position.line -1].rstrip("\n").endswith(","):
return None
if str(document.uri).startswith("vscode-notebook-cell"):
settings = copy.deepcopy(_get_settings_by_document(document))
source = utils.encode_cell_magic(source, settings.get("cellMagics", []))
try:
ast_tree = ast.parse(source)
except SyntaxError:
return None
position_lineno = params.position.line
for node in ast_tree.body:
lineno = node.lineno
end_lineno = node.end_lineno
if position_lineno >= lineno and position_lineno <= end_lineno:
break
start = lineno
end = end_lineno
extra_args = ["-l", f"{start}-{end}"]
edits = _formatting_helper(document, extra_args=extra_args)
if edits:
return edits

return None


@LSP_SERVER.feature(lsp.TEXT_DOCUMENT_RANGE_FORMATTING)
def range_formatting(params: lsp.DocumentFormattingParams) -> list[lsp.TextEdit] | None:
document = LSP_SERVER.workspace.get_document(params.text_document.uri)
Expand Down Expand Up @@ -92,6 +124,8 @@ def formatting(params: lsp.DocumentFormattingParams) -> list[lsp.TextEdit] | Non

def _formatting_helper(document: workspace.Document,
extra_args: Optional[Sequence[str]] = None) -> list[lsp.TextEdit] | None:
if _is_ignored(document) is True:
return None
result = _run_tool_on_document(document, use_stdin=True, extra_args=extra_args)
if result.stdout:
new_source = _match_line_endings(document, result.stdout)
Expand All @@ -107,6 +141,38 @@ def _formatting_helper(document: workspace.Document,
return None


def _is_ignored(document: workspace.Document) -> bool:
try:
yapf_module = importlib.import_module("yapf")
# deep copy here to prevent accidentally updating global settings.
settings = copy.deepcopy(_get_settings_by_document(document))
code_workspace = settings["workspaceFS"]
path = document.path[len(code_workspace):] if document.path.startswith(code_workspace) else document.path
path = path.lstrip("/")
exclude: list[str] = yapf_module.file_resources.GetExcludePatternsForDir(code_workspace)
if exclude and any(e.startswith('./') for e in exclude):
log_error("path in '--exclude' should not start with ./")
return False
exclude = exclude and [e.rstrip('/' + os.path.sep) for e in exclude]
exclude_from_args = _get_exclude_from_args(settings=settings)
exclude = (exclude_from_args or []) + exclude
return yapf_module.file_resources.IsIgnored(path, exclude)
except Exception as e:
log_error(str(e))
return False


def _get_exclude_from_args(settings: dict) -> list[str]:
exclude = []
args = settings.get("args", [])
if not args:
return exclude
for idx, i in enumerate(args[:-1]):
if i in ("-e", "--exclude"): # BUG: Exceptional situations need to be considered
exclude.append(args[idx + 1])
return exclude


def _get_line_endings(lines: list[str]) -> str:
"""Returns line endings used in the text."""
try:
Expand Down Expand Up @@ -162,6 +228,7 @@ def _get_global_defaults():
"importStrategy": GLOBAL_SETTINGS.get("importStrategy", "useBundled"),
"showNotifications": GLOBAL_SETTINGS.get("showNotifications", "off"),
"showDebugLog": GLOBAL_SETTINGS.get("showDebugLog", False),
"cellMagics": GLOBAL_SETTINGS.get("cellMagics", [])
}


Expand Down Expand Up @@ -248,11 +315,14 @@ def _run_tool_on_document(

source = document.source
has_magics = False
blank_cell_trail = False
if str(document.uri).startswith("vscode-notebook-cell"):
try:
ast.parse(source.replace("\r\n", "\n"))
except SyntaxError:
has_magics = True
if source.replace("\r\n", "\n").rstrip(" \t").endswith("\n"):
blank_cell_trail = True

if utils.is_stdlib_file(document.path):
# Skip standard library python files.
Expand Down Expand Up @@ -284,6 +354,7 @@ def _run_tool_on_document(
argv += TOOL_ARGS + settings["args"] + extra_args

if has_magics is True:
log_debug(f"cellMagics: {settings.get('cellMagics', [])}", settings)
source = utils.encode_cell_magic(source, settings.get("cellMagics", []))

if use_stdin:
Expand Down Expand Up @@ -344,6 +415,9 @@ def _run_tool_on_document(
if has_magics:
result.stdout = utils.decode_cell_magic(result.stdout)

if str(document.uri).startswith("vscode-notebook-cell") and blank_cell_trail is not True:
result.stdout = result.stdout.rstrip("\n")

log_debug(f"{document.uri} :\r\n{result.stdout}", settings=settings)
return result

Expand Down
4 changes: 2 additions & 2 deletions bundled/tool/lsp_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def is_cell_magic(code_line: str, python_cell_magics: list = None) -> bool:


def encode_line_magic(code_line: str) -> str:
return code_line.replace("%", "#\x00%\x00#")
return code_line.replace("%", "#\x01%\x01#")


def encode_cell_magic(code: str, python_cell_magics: list = None) -> str:
Expand All @@ -65,7 +65,7 @@ def encode_cell_magic(code: str, python_cell_magics: list = None) -> str:


def decode_line_magic(code_line: str) -> str:
return code_line.replace("#\x00%\x00#", "%")
return code_line.replace("#\x01%\x01#", "%")


def decode_cell_magic(code: str) -> str:
Expand Down
Loading

0 comments on commit a420a80

Please sign in to comment.