Skip to content

Commit 5659b0f

Browse files
authored
Merge pull request jxmorris12#126 from mdevolde/types
fix: more explicit MANIFEST.in, added uv.lock and py.typed, fixed type annotations errors and adding mypy to check them
2 parents 923cef4 + 2287685 commit 5659b0f

File tree

14 files changed

+1332
-81
lines changed

14 files changed

+1332
-81
lines changed

.github/pull_request_template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ If applicable, include links to any relevant documentation, articles, or resourc
3131
- [ ] Updated any relevant tests.
3232
- [ ] Updated any relevant documentation.
3333
- [ ] Added comments to your code where necessary.
34-
- [ ] Formatted your code, run the linters and tests.
34+
- [ ] Formatted your code, run the linters, checked types and tests.

.github/workflows/test.yml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,28 @@ jobs:
7272
- name: Run Ruff Linter
7373
run: |
7474
uvx ruff check .
75-
uvx ruff format --check .
75+
uvx ruff format --check .
76+
77+
type_check:
78+
name: Type Check with Mypy
79+
runs-on: ubuntu-latest
80+
steps:
81+
- name: Clone repository
82+
uses: actions/checkout@v5
83+
84+
- name: Install uv
85+
uses: astral-sh/setup-uv@v7
86+
87+
- name: Set up venv
88+
run: uv venv .venv
89+
90+
- name: Install dependencies & build package
91+
run: |
92+
. .venv/bin/activate
93+
uv pip install setuptools wheel build mypy
94+
uv build
95+
uv pip install dist/*.whl
96+
97+
- name: Run Mypy Type Checker
98+
run: |
99+
uvx mypy

CONTRIBUTING.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ If you want to contribute, you first need to fork the repo (and preferably creat
2020

2121
To start developing, you can install all the necessary packages in your python environment with this command (optional dependencies will be installed):
2222
```shell
23-
pip install -e .[dev]
23+
uv sync --group tests --group docs --group types
2424
```
2525

2626
When pushing commits, please use the project naming conventions, which are available in [this guide](https://www.conventionalcommits.org/en/v1.0.0/).
@@ -31,10 +31,13 @@ The documentation style used in the project is **ReStructuredText**. Please, if
3131
Before creating your pull request, when you have made all your commits, you need to run this:
3232
```shell
3333
# Run linters (maybe you will have to fix some issues)
34-
ruff check language_tool_python tests
34+
uvx ruff check .
3535

3636
# Format code
37-
ruff format language_tool_python tests
37+
uvx ruff format .
38+
39+
# Check types
40+
uvx mypy
3841

3942
# Tests
4043
pytest

MANIFEST.in

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
include tests/test_local.bash
2-
include tests/test_remote.bash
3-
prune pytest-cache-files-*/
1+
include pyproject.toml
2+
include README.md
3+
include LICENSE
4+
recursive-include language_tool_python *.py
5+
include language_tool_python/py.typed
6+
7+
prune .github/
8+
prune .pytest-cache/
9+
prune .ruff_cache/
410
prune env/
511
prune .env
612
prune .venv
@@ -9,3 +15,13 @@ prune venv/
915
prune ENV/
1016
prune env.bak/
1117
prune venv.bak/
18+
prune docs/
19+
prune tests/
20+
21+
exclude .gitignore
22+
exclude build_and_publish.sh
23+
exclude CONTRIBUTING.md
24+
exclude extract_long_description.py
25+
exclude Makefile
26+
exclude pytest.ini
27+
exclude uv.lock

language_tool_python/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def __call__(
132132
namespace: Any,
133133
values: Any,
134134
option_string: Optional[str] = None,
135-
):
135+
) -> None:
136136
"""
137137
This method is called when the action is triggered. It updates the set of rules
138138
in the namespace with the provided values. The method is invoked automatically

language_tool_python/config_file.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import tempfile
66
from dataclasses import dataclass
77
from pathlib import Path
8-
from typing import Any, Callable, Dict, Iterable, Optional, Union
8+
from typing import Any, Callable, Dict, Iterable, Optional, Tuple, Union
99

1010
from .exceptions import PathError
1111

@@ -22,7 +22,7 @@ class OptionSpec:
2222
remain constant throughout the application lifecycle.
2323
"""
2424

25-
py_types: Union[type, tuple[type, ...]]
25+
py_types: Union[type, Tuple[type, ...]]
2626
"""The Python type(s) that this option accepts."""
2727

2828
encoder: Callable[[Any], str]
@@ -47,7 +47,7 @@ def _bool_encoder(v: Any) -> str:
4747
return str(bool(v)).lower()
4848

4949

50-
def _comma_list_encoder(v: Any) -> str:
50+
def _comma_list_encoder(v: Union[str, Iterable[str]]) -> str:
5151
"""
5252
Encode a value as a comma-separated list string.
5353
@@ -57,16 +57,13 @@ def _comma_list_encoder(v: Any) -> str:
5757
with commas.
5858
5959
:param v: The value to encode. Can be a string or an iterable of values.
60-
:type v: Any
60+
:type v: Union[str, Iterable[str]]
6161
:return: A comma-separated string representation of the input value.
6262
:rtype: str
63-
:raises TypeError: If the input is neither a string nor an iterable.
6463
"""
6564
if isinstance(v, str):
6665
return v
67-
if isinstance(v, Iterable):
68-
return ",".join(str(x) for x in v)
69-
raise TypeError("expected string or iterable for comma-list option")
66+
return ",".join(str(x) for x in v)
7067

7168

7269
def _path_encoder(v: Any) -> str:

language_tool_python/download_lt.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,15 @@ def parse_java_version(version_text: str) -> Tuple[int, int]:
7979

8080

8181
def confirm_java_compatibility(
82-
language_tool_version: Optional[str] = LTP_DOWNLOAD_VERSION,
82+
language_tool_version: str = LTP_DOWNLOAD_VERSION,
8383
) -> None:
8484
"""
8585
Confirms if the installed Java version is compatible with language-tool-python.
8686
This function checks if Java is installed and verifies that the major version is at least 8 or 17 (depending on the LanguageTool version).
8787
It raises an error if Java is not installed or if the version is incompatible.
8888
8989
:param language_tool_version: The version of LanguageTool to check compatibility for.
90-
:type language_tool_version: Optional[str]
90+
:type language_tool_version: str
9191
:raises ModuleNotFoundError: If no Java installation is detected.
9292
:raises SystemError: If the detected Java version is less than the required version.
9393
"""
@@ -228,7 +228,7 @@ def download_zip(url: str, directory: str) -> None:
228228
logger.info(f"Downloaded {url} to {directory}.")
229229

230230

231-
def download_lt(language_tool_version: Optional[str] = LTP_DOWNLOAD_VERSION) -> None:
231+
def download_lt(language_tool_version: str = LTP_DOWNLOAD_VERSION) -> None:
232232
"""
233233
Downloads and extracts the specified version of LanguageTool.
234234
This function checks for Java compatibility, creates the necessary download
@@ -238,7 +238,7 @@ def download_lt(language_tool_version: Optional[str] = LTP_DOWNLOAD_VERSION) ->
238238
:param language_tool_version: The version of LanguageTool to download. If not
239239
specified, the default version defined by
240240
LTP_DOWNLOAD_VERSION is used.
241-
:type language_tool_version: Optional[str]
241+
:type language_tool_version: str
242242
:raises PathError: If the download folder is not a directory.
243243
:raises ValueError: If the specified version format is invalid.
244244
"""

language_tool_python/language_tag.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ def _normalize(self, tag: str) -> str:
105105
return languages[tag.lower().replace("-", "_")]
106106
except KeyError:
107107
try:
108-
return languages[self._LANGUAGE_RE.match(tag).group(1).lower()]
108+
match = self._LANGUAGE_RE.match(tag)
109+
if match is None:
110+
raise AttributeError("tag does not match pattern")
111+
return languages[match.group(1).lower()]
109112
except (KeyError, AttributeError) as e:
110113
raise ValueError(f"unsupported language: {tag!r}") from e

language_tool_python/match.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def four_byte_char_positions(text: str) -> List[int]:
8787
:return: A list of positions where 4-byte encoded characters are found.
8888
:rtype: List[int]
8989
"""
90-
positions = []
90+
positions: List[int] = []
9191
char_index = 0
9292
for char in text:
9393
if len(char.encode("utf-8")) == 4:
@@ -176,10 +176,6 @@ def __init__(self, attrib: Dict[str, Any], text: str) -> None:
176176
This method adjusts the positions of 4-byte encoded characters in the text
177177
to ensure the offsets of the matches are correct.
178178
"""
179-
if text is None:
180-
raise ValueError("The text parameter must not be None")
181-
if not isinstance(text, str):
182-
raise TypeError("The text parameter must be a string")
183179

184180
# Process rule.
185181
attrib["category"] = attrib["rule"]["category"]["id"]
@@ -204,7 +200,10 @@ def __init__(self, attrib: Dict[str, Any], text: str) -> None:
204200
Match.FOUR_BYTES_POSITIONS = four_byte_char_positions(text)
205201
# Get the positions of 4-byte encoded characters in the text because without
206202
# carrying out this step, the offsets of the matches could be incorrect.
207-
self.offset -= sum(1 for pos in Match.FOUR_BYTES_POSITIONS if pos < self.offset)
203+
if Match.FOUR_BYTES_POSITIONS is not None:
204+
self.offset -= sum(
205+
1 for pos in Match.FOUR_BYTES_POSITIONS if pos < self.offset
206+
)
208207

209208
def __repr__(self) -> str:
210209
"""

language_tool_python/py.typed

Whitespace-only changes.

0 commit comments

Comments
 (0)