Skip to content

Commit 047a760

Browse files
committed
v2.6.5: explicitly support client-server connections
1 parent f2ce5eb commit 047a760

File tree

4 files changed

+37
-7
lines changed

4 files changed

+37
-7
lines changed

README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,30 @@ with language_tool_python.LanguageToolPublicAPI('de-DE') as tool:
125125
# no need to call `close() as it will happen at the end of the with statement
126126
```
127127

128+
## Client-Server Model
129+
130+
You can run LanguageTool on one host and connect to it from another. This is useful in some distributed scenarios. Here's a simple example:
131+
132+
#### server
133+
134+
```python
135+
>>> import language_tool_python
136+
>>> tool = language_tool_python.LanguageTool('en-US', host='0.0.0.0')
137+
>>> tool._url
138+
'http://0.0.0.0:8081/v2/'
139+
```
140+
141+
#### client
142+
```python
143+
>>> import language_tool_python
144+
>>> lang_tool = language_tool_python.LanguageTool('en-US', remote_server='http://0.0.0.0:8081')
145+
>>>
146+
>>>
147+
>>> lang_tool.check('helo darknes my old frend')
148+
[Match({'ruleId': 'UPPERCASE_SENTENCE_START', 'message': 'This sentence does not start with an uppercase letter.', 'replacements': ['Helo'], 'offsetInContext': 0, 'context': 'helo darknes my old frend', 'offset': 0, 'errorLength': 4, 'category': 'CASING', 'ruleIssueType': 'typographical', 'sentence': 'helo darknes my old frend'}), Match({'ruleId': 'MORFOLOGIK_RULE_EN_US', 'message': 'Possible spelling mistake found.', 'replacements': ['darkness', 'darkens', 'darkies'], 'offsetInContext': 5, 'context': 'helo darknes my old frend', 'offset': 5, 'errorLength': 7, 'category': 'TYPOS', 'ruleIssueType': 'misspelling', 'sentence': 'helo darknes my old frend'}), Match({'ruleId': 'MORFOLOGIK_RULE_EN_US', 'message': 'Possible spelling mistake found.', 'replacements': ['friend', 'trend', 'Fred', 'freed', 'Freud', 'Friend', 'fend', 'fiend', 'frond', 'rend', 'fr end'], 'offsetInContext': 20, 'context': 'helo darknes my old frend', 'offset': 20, 'errorLength': 5, 'category': 'TYPOS', 'ruleIssueType': 'misspelling', 'sentence': 'helo darknes my old frend'})]
149+
>>>
150+
```
151+
128152
## Installation
129153

130154
To install via pip:
@@ -156,7 +180,6 @@ The default download path is `~/.cache/language_tool_python/`. The LanguageTool
156180
- [Python 3.6+](https://www.python.org)
157181
- [LanguageTool](https://www.languagetool.org) (Java 8.0 or higher)
158182

159-
160183
The installation process should take care of downloading LanguageTool (it may
161184
take a few minutes). Otherwise, you can manually download
162185
[LanguageTool-stable.zip](https://www.languagetool.org/download/LanguageTool-stable.zip) and unzip it

language_tool_python/server.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ class LanguageTool:
3131
"""Main class used for checking text against different rules.
3232
LanguageTool v2 API documentation: https://languagetool.org/http-api/swagger-ui/#!/default/post_check
3333
"""
34-
_HOST = socket.gethostbyname('localhost')
3534
_MIN_PORT = 8081
3635
_MAX_PORT = 8999
3736
_TIMEOUT = 5 * 60
@@ -41,9 +40,13 @@ class LanguageTool:
4140
_consumer_thread: threading.Thread = None
4241
_PORT_RE = re.compile(r"(?:https?://.*:|port\s+)(\d+)", re.I)
4342

44-
def __init__(self, language=None, motherTongue=None, remote_server=None, newSpellings=None, new_spellings_persist=True):
43+
def __init__(self, language=None, motherTongue=None,
44+
remote_server=None, newSpellings=None,
45+
new_spellings_persist=True,
46+
host=None):
4547
self._new_spellings = None
4648
self._new_spellings_persist = new_spellings_persist
49+
self._host = host or socket.gethostbyname('localhost')
4750
if remote_server is not None:
4851
self._remote = True
4952
self._url = parse_url(remote_server)
@@ -223,7 +226,7 @@ def _query_server(self, url, params=None, num_tries=2):
223226

224227
def _start_server_on_free_port(self):
225228
while True:
226-
self._url = 'http://{}:{}/v2/'.format(self._HOST, self._port)
229+
self._url = 'http://{}:{}/v2/'.format(self._host, self._port)
227230
try:
228231
self._start_local_server()
229232
break

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
setup(
99
name='language_tool_python',
10-
version='2.6.4',
10+
version='2.6.5',
1111
description='Checks grammar using LanguageTool.',
1212
long_description_content_type='text/markdown',
1313
long_description=long_description,

tests/test_major_functionality.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@ def test_process_starts_and_stops_on_close():
2929
assert proc.poll() is not None, "tool._server should stop running after deletion"
3030
# if poll is None: # p.subprocess is alive
3131

32-
33-
# TODO(jxm): Add test to confirm that multiple instances connect to the same process instead of starting new ones.
32+
def test_local_client_server_connection():
33+
import language_tool_python
34+
tool1 = language_tool_python.LanguageTool('en-US', host='0.0.0.0')
35+
url = 'http://{}:{}/'.format(tool1._host, tool1._port)
36+
tool2 = language_tool_python.LanguageTool('en-US', remote_server=url)
37+
assert len(tool2.check('helo darknes my old frend'))
3438

3539
def test_langtool_languages():
3640
import language_tool_python

0 commit comments

Comments
 (0)