Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Format the whole repo with Black #419

Merged
merged 12 commits into from
Aug 16, 2023
10 changes: 7 additions & 3 deletions .github/workflows/static.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,15 @@ jobs:
python-version: '3.8'
architecture: 'x64'
- run: python -m pip install --upgrade pip setuptools jsonschema
- run: pip install -e .[pylint,pycodestyle,pyflakes]
# If we don't install pycodestyle, pylint will throw an unused-argument error in pylsp/plugins/pycodestyle_lint.py:72
# This error cannot be resolved by adding a pylint: disable=unused-argument comment ...
- run: |
pip install -e .[pylint,pycodestyle,pyflakes]
pip install black
- name: Pylint checks
run: pylint pylsp test
- name: Code style checks
run: pycodestyle pylsp test
- name: Code style checks with black
run: black --check pylsp test
- name: Pyflakes checks
run: pyflakes pylsp test
- name: Validate JSON schema
Expand Down
4 changes: 2 additions & 2 deletions pylsp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ def convert_version_info(version: str) -> (int, ..., str):

_version.VERSION_INFO = convert_version_info(__version__)

PYLSP = 'pylsp'
IS_WIN = os.name == 'nt'
PYLSP = "pylsp"
IS_WIN = os.name == "nt"

hookspec = pluggy.HookspecMarker(PYLSP)
hookimpl = pluggy.HookimplMarker(PYLSP)
Expand Down
69 changes: 36 additions & 33 deletions pylsp/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,58 +12,58 @@
except Exception: # pylint: disable=broad-except
import json

from .python_lsp import (PythonLSPServer, start_io_lang_server,
start_tcp_lang_server, start_ws_lang_server)
from .python_lsp import (
PythonLSPServer,
start_io_lang_server,
start_tcp_lang_server,
start_ws_lang_server,
)
from ._version import __version__

LOG_FORMAT = "%(asctime)s {0} - %(levelname)s - %(name)s - %(message)s".format(
time.localtime().tm_zone)
time.localtime().tm_zone
)


def add_arguments(parser):
parser.description = "Python Language Server"

parser.add_argument(
"--tcp", action="store_true",
help="Use TCP server instead of stdio"
"--tcp", action="store_true", help="Use TCP server instead of stdio"
)
parser.add_argument(
"--ws", action="store_true",
help="Use Web Sockets server instead of stdio"
"--ws", action="store_true", help="Use Web Sockets server instead of stdio"
)
parser.add_argument("--host", default="127.0.0.1", help="Bind to this address")
parser.add_argument("--port", type=int, default=2087, help="Bind to this port")
parser.add_argument(
"--host", default="127.0.0.1",
help="Bind to this address"
)
parser.add_argument(
"--port", type=int, default=2087,
help="Bind to this port"
)
parser.add_argument(
'--check-parent-process', action="store_true",
"--check-parent-process",
action="store_true",
help="Check whether parent process is still alive using os.kill(ppid, 0) "
"and auto shut down language server process when parent process is not alive."
"Note that this may not work on a Windows machine."
"Note that this may not work on a Windows machine.",
)

log_group = parser.add_mutually_exclusive_group()
log_group.add_argument(
"--log-config",
help="Path to a JSON file containing Python logging config."
"--log-config", help="Path to a JSON file containing Python logging config."
)
log_group.add_argument(
"--log-file",
help="Redirect logs to the given file instead of writing to stderr."
"Has no effect if used with --log-config."
"Has no effect if used with --log-config.",
)

parser.add_argument(
'-v', '--verbose', action='count', default=0,
help="Increase verbosity of log output, overrides log config file"
"-v",
"--verbose",
action="count",
default=0,
help="Increase verbosity of log output, overrides log config file",
)

parser.add_argument(
'-V', '--version', action='version', version='%(prog)s v' + __version__
"-V", "--version", action="version", version="%(prog)s v" + __version__
)


Expand All @@ -74,15 +74,14 @@ def main():
_configure_logger(args.verbose, args.log_config, args.log_file)

if args.tcp:
start_tcp_lang_server(args.host, args.port, args.check_parent_process,
PythonLSPServer)
start_tcp_lang_server(
args.host, args.port, args.check_parent_process, PythonLSPServer
)
elif args.ws:
start_ws_lang_server(args.port, args.check_parent_process,
PythonLSPServer)
start_ws_lang_server(args.port, args.check_parent_process, PythonLSPServer)
else:
stdin, stdout = _binary_stdio()
start_io_lang_server(stdin, stdout, args.check_parent_process,
PythonLSPServer)
start_io_lang_server(stdin, stdout, args.check_parent_process, PythonLSPServer)


def _binary_stdio():
Expand All @@ -99,14 +98,18 @@ def _configure_logger(verbose=0, log_config=None, log_file=None):
root_logger = logging.root

if log_config:
with open(log_config, 'r', encoding='utf-8') as f:
with open(log_config, "r", encoding="utf-8") as f:
logging.config.dictConfig(json.load(f))
else:
formatter = logging.Formatter(LOG_FORMAT)
if log_file:
log_handler = logging.handlers.RotatingFileHandler(
log_file, mode='a', maxBytes=50*1024*1024,
backupCount=10, encoding=None, delay=0
log_file,
mode="a",
maxBytes=50 * 1024 * 1024,
backupCount=10,
encoding=None,
delay=0,
)
else:
log_handler = logging.StreamHandler()
Expand All @@ -123,5 +126,5 @@ def _configure_logger(verbose=0, log_config=None, log_file=None):
root_logger.setLevel(level)


if __name__ == '__main__':
if __name__ == "__main__":
main()
70 changes: 37 additions & 33 deletions pylsp/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@

# Eol chars accepted by the LSP protocol
# the ordering affects performance
EOL_CHARS = ['\r\n', '\r', '\n']
EOL_CHARS = ["\r\n", "\r", "\n"]
EOL_REGEX = re.compile(f'({"|".join(EOL_CHARS)})')

log = logging.getLogger(__name__)


def debounce(interval_s, keyed_by=None):
"""Debounce calls to this function until interval_s seconds have passed."""

def wrapper(func):
timers = {}
lock = threading.Lock()
Expand All @@ -48,7 +49,9 @@ def run():
timer = threading.Timer(interval_s, run)
timers[key] = timer
timer.start()

return debounced

return wrapper


Expand Down Expand Up @@ -78,7 +81,9 @@ def find_parents(root, path, names):
# Search each of /a/b/c, /a/b, /a
while dirs:
search_dir = os.path.join(*dirs)
existing = list(filter(os.path.exists, [os.path.join(search_dir, n) for n in names]))
existing = list(
filter(os.path.exists, [os.path.join(search_dir, n) for n in names])
)
if existing:
return existing
dirs.pop()
Expand All @@ -92,11 +97,11 @@ def path_to_dot_name(path):
directory = os.path.dirname(path)
module_name, _ = os.path.splitext(os.path.basename(path))
full_name = [module_name]
while os.path.exists(os.path.join(directory, '__init__.py')):
while os.path.exists(os.path.join(directory, "__init__.py")):
this_directory = os.path.basename(directory)
directory = os.path.dirname(directory)
full_name = [this_directory] + full_name
return '.'.join(full_name)
return ".".join(full_name)


def match_uri_to_workspace(uri, workspaces):
Expand Down Expand Up @@ -128,6 +133,7 @@ def merge_dicts(dict_a, dict_b):

If override_nones is True, then
"""

def _merge_dicts_(a, b):
for key in set(a.keys()).union(b.keys()):
if key in a and key in b:
Expand All @@ -143,15 +149,16 @@ def _merge_dicts_(a, b):
yield (key, a[key])
elif b[key] is not None:
yield (key, b[key])

return dict(_merge_dicts_(dict_a, dict_b))


def escape_plain_text(contents: str) -> str:
"""
Format plain text to display nicely in environments which do not respect whitespaces.
"""
contents = contents.replace('\t', '\u00A0' * 4)
contents = contents.replace(' ', '\u00A0' * 2)
contents = contents.replace("\t", "\u00A0" * 4)
contents = contents.replace(" ", "\u00A0" * 2)
return contents


Expand All @@ -160,17 +167,17 @@ def escape_markdown(contents: str) -> str:
Format plain text to display nicely in Markdown environment.
"""
# escape markdown syntax
contents = re.sub(r'([\\*_#[\]])', r'\\\1', contents)
contents = re.sub(r"([\\*_#[\]])", r"\\\1", contents)
# preserve white space characters
contents = escape_plain_text(contents)
return contents


def wrap_signature(signature):
return '```python\n' + signature + '\n```\n'
return "```python\n" + signature + "\n```\n"


SERVER_SUPPORTED_MARKUP_KINDS = {'markdown', 'plaintext'}
SERVER_SUPPORTED_MARKUP_KINDS = {"markdown", "plaintext"}


def choose_markup_kind(client_supported_markup_kinds: List[str]):
Expand All @@ -181,10 +188,12 @@ def choose_markup_kind(client_supported_markup_kinds: List[str]):
for kind in client_supported_markup_kinds:
if kind in SERVER_SUPPORTED_MARKUP_KINDS:
return kind
return 'markdown'
return "markdown"


def format_docstring(contents: str, markup_kind: str, signatures: Optional[List[str]] = None):
def format_docstring(
contents: str, markup_kind: str, signatures: Optional[List[str]] = None
):
"""Transform the provided docstring into a MarkupContent object.

If `markup_kind` is 'markdown' the docstring will get converted to
Expand All @@ -195,33 +204,24 @@ def format_docstring(contents: str, markup_kind: str, signatures: Optional[List[
to the provided contents of the docstring if given.
"""
if not isinstance(contents, str):
contents = ''
contents = ""

if markup_kind == 'markdown':
if markup_kind == "markdown":
try:
value = docstring_to_markdown.convert(contents)
return {
'kind': 'markdown',
'value': value
}
return {"kind": "markdown", "value": value}
except docstring_to_markdown.UnknownFormatError:
# try to escape the Markdown syntax instead:
value = escape_markdown(contents)

if signatures:
value = wrap_signature('\n'.join(signatures)) + '\n\n' + value
value = wrap_signature("\n".join(signatures)) + "\n\n" + value

return {
'kind': 'markdown',
'value': value
}
return {"kind": "markdown", "value": value}
value = contents
if signatures:
value = '\n'.join(signatures) + '\n\n' + value
return {
'kind': 'plaintext',
'value': escape_plain_text(value)
}
value = "\n".join(signatures) + "\n\n" + value
return {"kind": "plaintext", "value": escape_plain_text(value)}


def clip_column(column, lines, line_number):
Expand All @@ -230,7 +230,9 @@ def clip_column(column, lines, line_number):

https://microsoft.github.io/language-server-protocol/specification#position
"""
max_column = len(lines[line_number].rstrip('\r\n')) if len(lines) > line_number else 0
max_column = (
len(lines[line_number].rstrip("\r\n")) if len(lines) > line_number else 0
)
return min(column, max_column)


Expand All @@ -242,14 +244,16 @@ def position_to_jedi_linecolumn(document, position):
"""
code_position = {}
if position:
code_position = {'line': position['line'] + 1,
'column': clip_column(position['character'],
document.lines,
position['line'])}
code_position = {
"line": position["line"] + 1,
"column": clip_column(
position["character"], document.lines, position["line"]
),
}
return code_position


if os.name == 'nt':
if os.name == "nt":
import ctypes

kernel32 = ctypes.windll.kernel32
Expand Down
Loading
Loading