Skip to content
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
36 changes: 17 additions & 19 deletions language_tool_python/download_lt.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@

import requests
import tqdm
from packaging import version
from packaging.version import Version

from ._compat import deprecated, toml_loads
from .exceptions import JavaError, PathError
Expand All @@ -32,6 +30,7 @@
LTP_JAR_DIR_PATH_ENV_VAR,
get_env_int,
get_language_tool_download_path,
version_tuple,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -275,7 +274,7 @@ def confirm_java_compatibility(

is_old_version = language_tool_version != LTP_DOWNLOAD_VERSION and (
re.match(r"^\d+\.\d+$", language_tool_version)
and Version(language_tool_version) < Version("6.6")
and version_tuple(language_tool_version) < (6, 6) # 6.6
)

# Some installs of java show the version number like '14.0.1'
Expand Down Expand Up @@ -765,15 +764,15 @@ def version_name(self) -> str:

@property
@abstractmethod
def version_into(self) -> Version | datetime:
def version_into(self) -> tuple[int, int] | datetime:
"""Get the version as a comparable object.

This abstract property must be implemented by subclasses to return the version
as either a Version object (for releases) or datetime object (for snapshots) for
comparison purposes.
as either a tuple of integers (for releases) or datetime object (for snapshots)
for comparison purposes.

:return: A Version object for releases or datetime for snapshots.
:rtype: Version | datetime
:return: A tuple of integers for releases or datetime for snapshots.
:rtype: tuple[int, int] | datetime
:raises NotImplementedError: Always, unless implemented by a subclass.
"""
raise NotImplementedError
Expand Down Expand Up @@ -835,8 +834,7 @@ def __lt__(self, other: object) -> bool:
self_version = self.version_into
other_version = other.version_into
if (
isinstance(self_version, Version)
and isinstance(other_version, Version)
isinstance(self_version, tuple) and isinstance(other_version, tuple)
) or (
isinstance(self_version, datetime)
and isinstance(other_version, datetime)
Expand Down Expand Up @@ -919,13 +917,13 @@ def version_name(self) -> str:
return self._version_name

@property
def version_into(self) -> Version:
"""Get the version as a Version object for comparison.
def version_into(self) -> tuple[int, int]:
"""Get the version as a tuple of integers for comparison.

:return: A parsed Version object from the version string.
:rtype: Version
:return: A tuple of integers representing the version.
:rtype: tuple[int, int]
"""
return version.parse(self._version_name)
return version_tuple(self._version_name)

@property
def download_url(self) -> str:
Expand All @@ -941,16 +939,16 @@ def download_url(self) -> str:
:rtype: str
:raises PathError: If the version is below 4.0 (unsupported).
"""
version_num = Version(self._version_name)
version_num = version_tuple(self._version_name)
filename = FILENAME_RELEASE.format(version=self._version_name)
# Versions >= 6.7 from new release page
if version_num >= Version("6.7"):
if version_num >= (6, 7): # 6.7
base_url = BASE_URL_NEW_RELEASES.format(version=self._version_name)
return urljoin(base_url, filename)
# Versions >= 6.0 from main download page
if version_num >= Version("6.0"):
if version_num >= (6, 0): # 6.0
return urljoin(BASE_URL_RELEASE, filename)
if version_num < Version("4.0"):
if version_num < (4, 0): # 4.0
err = (
"LanguageTool versions below 4.0 are no longer supported for download."
" Below version 4.0, the API changed significantly and is "
Expand Down
6 changes: 3 additions & 3 deletions language_tool_python/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import psutil
import requests
from packaging.version import Version

from .api_types import (
is_check_response,
Expand All @@ -41,6 +40,7 @@
get_locale_language,
kill_process_force,
parse_url,
version_tuple,
)

startupinfo: object | None = None
Expand Down Expand Up @@ -1136,8 +1136,8 @@ def _wait_for_server_ready(self, timeout: int = 15) -> None:
url = (
urllib.parse.urljoin(self._url, "check?text=healthcheck&language=en")
if re.match(r"^\d+\.\d+$", self._language_tool_download_version)
and Version(self._language_tool_download_version)
< Version("4.2") # healthcheck endpoint added in 4.2
and version_tuple(self._language_tool_download_version)
< (4, 2) # healthcheck endpoint added in 4.2
else urllib.parse.urljoin(self._url, "healthcheck")
)
start = time.time()
Expand Down
26 changes: 21 additions & 5 deletions language_tool_python/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from typing import TYPE_CHECKING, Protocol, runtime_checkable

import psutil
from packaging import version

from ._compat import deprecated
from .exceptions import JavaError, PathError
Expand Down Expand Up @@ -221,7 +220,7 @@ def find_existing_language_tool_downloads(download_folder: Path) -> list[Path]:
"This function is no longer used internally and will be removed in 4.0.",
stacklevel=2,
)
def _extract_version(path: Path) -> version.Version:
def _extract_version(path: Path) -> tuple[int, int]:
"""Extract the version number from a LanguageTool directory path.

This function parses the directory name to extract the version information
Expand All @@ -230,8 +229,8 @@ def _extract_version(path: Path) -> version.Version:

:param path: The path to the LanguageTool directory
:type path: Path
:return: The parsed version object extracted from the directory name
:rtype: version.Version
:return: The parsed version tuple extracted from the directory name
:rtype: tuple[int, int]
:raises ValueError: If the directory name doesn't start with 'LanguageTool-'

.. deprecated:: 3.3.0
Expand All @@ -244,7 +243,7 @@ def _extract_version(path: Path) -> version.Version:
version_str = path.name.removeprefix("LanguageTool-")
# Handle both -SNAPSHOT and -snapshot suffixes
version_str = version_str.removesuffix("-SNAPSHOT").removesuffix("-snapshot")
return version.parse(version_str)
return version_tuple(version_str)


@deprecated(
Expand Down Expand Up @@ -471,3 +470,20 @@ class SupportsFloat(Protocol):
def __float__(self) -> float:
"""Define the interface for types that can be converted to a float."""
...


def version_tuple(v: str) -> tuple[int, int]:
"""Convert a version string into a tuple of integers.

This function takes a version string in the format 'X.Y' and converts it into a
tuple of integers (X, Y). This can be useful for comparing version numbers.

:param v: The version string to be converted, expected in the format 'X.Y'.
:type v: str
:return: A tuple of integers representing the version, in the format (X, Y).
:rtype: tuple[int, int]
:raises ValueError: If the version string is not in the expected format or contains
non-integer components.
"""
major, minor = v.split(".")
return int(major), int(minor)
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ keywords = ["python", "nlp", "grammar", "languagetool", "grammar-checker", "spel
dependencies = [
"requests",
"tqdm",
"packaging",
"psutil",
"tomli; python_version < '3.11'", # only needed for py < 3.11 because tomllib added in 3.11 is used in the codebase, needs a fallback
"typing_extensions; python_version < '3.13'", # only needed for py < 3.13 because warnings.deprecated added in 3.13 is used in the codebase
Expand Down
8 changes: 3 additions & 5 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading