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

fix: return None for non file: URIs #500

Merged
merged 1 commit into from
Oct 7, 2024
Merged
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
5 changes: 5 additions & 0 deletions docs/source/howto/migrate-to-v2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ Python Support

*pygls v2* removes support for Python 3.8 and adds support for Python 3.13 (with the GIL, you are welcome to try the free-threaded version just note that it has not been tested yet!)

URI Handling
------------

The :func:`pygls.uris.to_fs_path` will now return ``None`` for URIs that do not have a ``file:`` scheme.


Removed Deprecated Functions
----------------------------
Expand Down
16 changes: 16 additions & 0 deletions docs/source/reference/uris.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
URIs
====

.. currentmodule:: pygls.uris

.. autofunction:: from_fs_path

.. autofunction:: to_fs_path

.. autofunction:: uri_scheme

.. autofunction:: uri_with

.. autofunction:: urlparse

.. autofunction:: urlunparse
10 changes: 7 additions & 3 deletions pygls/uris.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

https://github.com/Microsoft/vscode-uri/blob/e59cab84f5df6265aed18ae5f43552d3eef13bb9/lib/index.ts
"""
from __future__ import annotations

from typing import Optional, Tuple

import re
Expand Down Expand Up @@ -75,20 +77,22 @@ def from_fs_path(path: str):
return None


def to_fs_path(uri: str):
def to_fs_path(uri: str) -> str | None:
"""
Returns the filesystem path of the given URI.

Will handle UNC paths and normalize windows drive letters to lower-case.
Also uses the platform specific path separator. Will *not* validate the
path for invalid characters and semantics.
Will *not* look at the scheme of this URI.
"""
try:
# scheme://netloc/path;parameters?query#fragment
scheme, netloc, path, _, _, _ = urlparse(uri)

if netloc and path and scheme == "file":
if scheme != "file":
return None

if netloc and path:
# unc path: file://shares/c$/far/boo
value = f"//{netloc}{path}"

Expand Down
18 changes: 10 additions & 8 deletions pygls/workspace/text_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
import io
import logging
import os
import pathlib
import re
from typing import List, Optional, Pattern

from lsprotocol import types

from pygls.uris import to_fs_path
from pygls.uris import urlparse, to_fs_path
from .position_codec import PositionCodec

# TODO: this is not the best e.g. we capture numbers
Expand All @@ -47,9 +48,10 @@ def __init__(
):
self.uri = uri
self.version = version
path = to_fs_path(uri)
if path is None:
raise Exception("`path` cannot be None")

if (path := to_fs_path(uri)) is None:
_, _, path, *_ = urlparse(uri)

self.path = path
self.language_id = language_id
self.filename: Optional[str] = os.path.basename(self.path)
Expand Down Expand Up @@ -177,10 +179,10 @@ def offset_at_position(self, client_position: types.Position) -> int:

@property
def source(self) -> str:
if self._source is None:
with io.open(self.path, "r", encoding="utf-8") as f:
return f.read()
return self._source
if self._source is None and self.path is not None:
return pathlib.Path(self.path).read_text(encoding="utf-8")

return self._source or ""

def word_at_position(
self,
Expand Down
16 changes: 9 additions & 7 deletions pygls/workspace/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ def __init__(
self._root_uri = root_uri
if self._root_uri is not None:
self._root_uri_scheme = uri_scheme(self._root_uri)
root_path = to_fs_path(self._root_uri)
if root_path is None:
raise Exception("Couldn't get `root_path` from `root_uri`")
self._root_path = root_path
self._root_path = to_fs_path(self._root_uri)
else:
self._root_path = None
self._sync_kind = sync_kind
Expand Down Expand Up @@ -151,9 +148,14 @@ def get_text_document(self, doc_uri: str) -> TextDocument:
return self._text_documents.get(doc_uri) or self._create_text_document(doc_uri)

def is_local(self):
return (
self._root_uri_scheme == "" or self._root_uri_scheme == "file"
) and os.path.exists(self._root_path)

if self._root_uri_scheme not in {"", "file"}:
return False

if (path := self._root_path) is None:
return False

return os.path.exists(path)

def put_notebook_document(self, params: types.DidOpenNotebookDocumentParams):
notebook = params.notebook_document
Expand Down
Loading