1414from .utils import *
1515
1616class LanguageTool :
17- """ Main class used for checking text against different rules. """
17+ """ Main class used for checking text against different rules.
18+
19+ LanguageTool v2 API documentation: https://languagetool.org/http-api/swagger-ui/#!/default/post_check
20+ """
1821 _HOST = socket .gethostbyname ('localhost' )
1922 _MIN_PORT = 8081
2023 _MAX_PORT = 8999
@@ -28,6 +31,7 @@ class LanguageTool:
2831 _PORT_RE = re .compile (r"(?:https?://.*:|port\s+)(\d+)" , re .I )
2932
3033 def __init__ (self , language = None , motherTongue = None , remote_server = None ):
34+ print ('__init__' , remote_server )
3135 if remote_server is not None :
3236 self ._remote = True
3337 if remote_server [- 1 ] == '/' : remote_server = remote_server [:- 1 ]
@@ -42,9 +46,11 @@ def __init__(self, language=None, motherTongue=None, remote_server=None):
4246 language = FAILSAFE_LANGUAGE
4347 self ._language = LanguageTag (language )
4448 self .motherTongue = motherTongue
45- self .disabled = set ()
46- self .enabled = set ()
47- self .enabled_only = False
49+ self .disabled_rules = set ()
50+ self .enabled_rules = set ()
51+ self .disabled_categories = set ()
52+ self .enabled_categories = set ()
53+ self .enabled_rules_only = False
4854 self ._instances [id (self )] = self
4955
5056 def __del__ (self ):
@@ -63,8 +69,8 @@ def language(self):
6369 @language .setter
6470 def language (self , language ):
6571 self ._language = LanguageTag (language )
66- self .disabled .clear ()
67- self .enabled .clear ()
72+ self .disabled_rules .clear ()
73+ self .enabled_rules .clear ()
6874
6975 @property
7076 def motherTongue (self ):
@@ -105,12 +111,16 @@ def _encode(self, text, srctext=None):
105111 params ['srctext' ] = srctext .encode ('utf-8' )
106112 if self .motherTongue is not None :
107113 params ['motherTongue' ] = self .motherTongue
108- if self .disabled :
109- params ['disabled ' ] = ',' .join (self .disabled )
110- if self .enabled :
111- params ['enabled' ] = ',' .join (self .enabled )
112- if self .enabled_only :
114+ if self .disabled_rules :
115+ params ['disabledRules ' ] = ',' .join (self .disabled_rules )
116+ if self .enabled_rules :
117+ params ['enabled' ] = ',' .join (self .enabled_rules )
118+ if self .enabled_rules_only :
113119 params ['enabledOnly' ] = 'yes'
120+ if self .disabled_categories :
121+ params ['disabledCategories' ] = ',' .join (self .disabled_categories )
122+ if self .enabled_categories :
123+ params ['enabledCategories' ] = ',' .join (self .enabled_categories )
114124 return urllib .parse .urlencode (params ).encode ()
115125
116126 def correct (self , text : str , srctext = None ) -> str :
@@ -119,48 +129,44 @@ def correct(self, text: str, srctext=None) -> str:
119129
120130 def enable_spellchecking (self ):
121131 """Enable spell-checking rules."""
122- self .disabled .difference_update (self ._spell_checking_rules )
132+ self .disabled_rules .difference_update (self ._spell_checking_rules )
123133
124134 def disable_spellchecking (self ):
125135 """Disable spell-checking rules."""
126- self .disabled .update (self ._spell_checking_rules )
136+ self .disabled_rules .update (self ._spell_checking_rules )
127137
128- @classmethod
129- def _get_languages (cls ) -> set :
138+ def _get_languages (self ) -> set :
130139 """Get supported languages (by querying the server)."""
131- cls ._start_server_if_needed ()
132- url = urllib .parse .urljoin (cls ._url , 'languages' )
140+ import pdb ; pdb .set_trace ()
141+ self ._start_server_if_needed ()
142+ url = urllib .parse .urljoin (self ._url , 'languages' )
133143 languages = set ()
134- for e in cls ._get_root (url , num_tries = 1 ):
144+ for e in self ._get_root (url , num_tries = 1 ):
135145 languages .add (e .get ('code' ))
136146 languages .add (e .get ('longCode' ))
137147 return languages
138148
139- @classmethod
140- def _get_attrib (cls ):
149+ def _get_attrib (self ):
141150 """Get matches element attributes."""
142- cls ._start_server_if_needed ()
151+ self ._start_server_if_needed ()
143152 params = {'language' : FAILSAFE_LANGUAGE , 'text' : '' }
144153 data = urllib .parse .urlencode (params ).encode ()
145- root = cls ._get_root (cls ._url , data , num_tries = 1 )
154+ root = self ._get_root (self ._url , data , num_tries = 1 )
146155 return root .attrib
147156
148- @classmethod
149- def _start_server_if_needed (cls ):
157+ def _start_server_if_needed (self ):
150158 # Start server.
151- if not cls ._server_is_alive () and cls ._remote is False :
152- cls ._start_server_on_free_port ()
159+ if not self ._server_is_alive () and self ._remote is False :
160+ self ._start_server_on_free_port ()
153161
154- @classmethod
155- def _update_remote_server_config (cls , url ):
156- cls ._url = url
157- cls ._remote = True
162+ def _update_remote_server_config (self , url ):
163+ self ._url = url
164+ self ._remote = True
158165
159- @classmethod
160- def _get_root (cls , url , data = None , num_tries = 2 ):
166+ def _get_root (self , url , data = None , num_tries = 2 ):
161167 for n in range (num_tries ):
162168 try :
163- with urlopen (url , data , cls ._TIMEOUT ) as f :
169+ with urlopen (url , data , self ._TIMEOUT ) as f :
164170 raw_data = f .read ().decode ('utf-8' )
165171 try :
166172 return json .loads (raw_data )
@@ -169,39 +175,38 @@ def _get_root(cls, url, data=None, num_tries=2):
169175 print (raw_data )
170176 raise e
171177 except (IOError , http .client .HTTPException ) as e :
172- if cls ._remote is False :
173- cls ._terminate_server ()
174- cls ._start_local_server ()
178+ if self ._remote is False :
179+ self ._terminate_server ()
180+ self ._start_local_server ()
175181 if n + 1 >= num_tries :
176- raise LanguageToolError ('{}: {}' .format (cls ._url , e ))
182+ raise LanguageToolError ('{}: {}' .format (self ._url , e ))
177183
178- @classmethod
179- def _start_server_on_free_port (cls ):
184+ def _start_server_on_free_port (self ):
180185 while True :
181- cls ._url = 'http://{}:{}/v2/' .format (cls ._HOST , cls ._port )
186+ self ._url = 'http://{}:{}/v2/' .format (self ._HOST , self ._port )
182187 try :
183- cls ._start_local_server ()
188+ self ._start_local_server ()
184189 break
185190 except ServerError :
186- if cls ._MIN_PORT <= cls ._port < cls ._MAX_PORT :
187- cls ._port += 1
191+ if self ._MIN_PORT <= self ._port < self ._MAX_PORT :
192+ self ._port += 1
188193 else :
189194 raise
190195
191- @ classmethod
192- def _start_local_server (cls ):
196+
197+ def _start_local_server (self ):
193198 # Before starting local server, download language tool if needed.
194199 download_lt ()
195200
196201 err = None
197202 try :
198- server_cmd = get_server_cmd (cls ._port )
203+ server_cmd = get_server_cmd (self ._port )
199204 except PathError as e :
200205 # Can't find path to LanguageTool.
201206 err = e
202207 else :
203208 # Need to PIPE all handles: http://bugs.python.org/issue3905
204- cls ._server = subprocess .Popen (
209+ self ._server = subprocess .Popen (
205210 server_cmd ,
206211 stdin = subprocess .PIPE ,
207212 stdout = subprocess .PIPE ,
@@ -210,86 +215,84 @@ def _start_local_server(cls):
210215 startupinfo = startupinfo
211216 )
212217 # Python 2.7 compatibility
213- # for line in cls ._server.stdout:
218+ # for line in self ._server.stdout:
214219 match = None
215220 while True :
216- line = cls ._server .stdout .readline ()
221+ line = self ._server .stdout .readline ()
217222 if not line :
218223 break
219- match = cls ._PORT_RE .search (line )
224+ match = self ._PORT_RE .search (line )
220225 if match :
221226 port = int (match .group (1 ))
222- if port != cls ._port :
227+ if port != self ._port :
223228 raise LanguageToolError ('requested port {}, but got {}' .format (
224- cls ._port , port ))
229+ self ._port , port ))
225230 break
226231 if not match :
227- err_msg = cls ._terminate_server ()
228- match = cls ._PORT_RE .search (err_msg )
232+ err_msg = self ._terminate_server ()
233+ match = self ._PORT_RE .search (err_msg )
229234 if not match :
230235 raise LanguageToolError (err_msg )
231236 port = int (match .group (1 ))
232- if port != cls ._port :
237+ if port != self ._port :
233238 raise LanguageToolError (err_msg )
234239
235- if cls ._server :
236- cls ._consumer_thread = threading .Thread (
237- target = lambda : _consume (cls ._server .stdout ))
238- cls ._consumer_thread .daemon = True
239- cls ._consumer_thread .start ()
240+ if self ._server :
241+ self ._consumer_thread = threading .Thread (
242+ target = lambda : _consume (self ._server .stdout ))
243+ self ._consumer_thread .daemon = True
244+ self ._consumer_thread .start ()
240245 else :
241246 # Couldn't start the server, so maybe there is already one running.
242247 params = {'language' : FAILSAFE_LANGUAGE , 'text' : '' }
243248 data = urllib .parse .urlencode (params ).encode ()
244249 try :
245- with urlopen (cls ._url , data , cls ._TIMEOUT ) as f :
250+ with urlopen (self ._url , data , self ._TIMEOUT ) as f :
246251 tree = ElementTree .parse (f )
247252 except (IOError , http .client .HTTPException ) as e :
248253 if err :
249254 raise err
250- raise ServerError ('{}: {}' .format (cls ._url , e ))
255+ raise ServerError ('{}: {}' .format (self ._url , e ))
251256 root = tree .getroot ()
252257
253258 # LanguageTool 1.9+
254259 if root .get ('software' ) != 'LanguageTool' :
255260 raise ServerError ('unexpected software from {}: {!r}'
256- .format (cls ._url , root .get ('software' )))
261+ .format (self ._url , root .get ('software' )))
257262 raise ServerError ('Server running; don\' t start a server here.' )
258263
259- @classmethod
260- def _server_is_alive (cls ):
261- return cls ._server and cls ._server .poll () is None
264+ def _server_is_alive (self ):
265+ return self ._server and self ._server .poll () is None
262266
263- @classmethod
264- def _terminate_server (cls ):
267+ def _terminate_server (self ):
265268 LanguageToolError_message = ''
266269
267270 try :
268- cls ._server .terminate ()
271+ self ._server .terminate ()
269272 except OSError :
270273 pass
271274
272275 try :
273- LanguageToolError_message = cls ._server .communicate ()[1 ].strip ()
276+ LanguageToolError_message = self ._server .communicate ()[1 ].strip ()
274277 except (IOError , ValueError ):
275278 pass
276279
277280 try :
278- cls ._server .stdout .close ()
281+ self ._server .stdout .close ()
279282 except IOError :
280283 pass
281284
282285 try :
283- cls ._server .stdin .close ()
286+ self ._server .stdin .close ()
284287 except IOError :
285288 pass
286289
287290 try :
288- cls ._server .stderr .close ()
291+ self ._server .stderr .close ()
289292 except IOError :
290293 pass
291294
292- cls ._server = None
295+ self ._server = None
293296
294297 return LanguageToolError_message
295298
@@ -299,11 +302,11 @@ class LanguageToolPublicAPI(LanguageTool):
299302 def __init__ (self , * args , ** kwargs ):
300303 super ().__init__ (* args , remote_server = 'https://api.languagetool.org' , ** kwargs )
301304
302- @atexit .register
303- def terminate_server ():
304- """Terminate the server."""
305- if LanguageTool ._server_is_alive ():
306- LanguageTool ._terminate_server ()
305+ # @atexit.register
306+ # def terminate_server():
307+ # """Terminate the server."""
308+ # if LanguageTool._server_is_alive():
309+ # LanguageTool._terminate_server()
307310
308311
309312
0 commit comments