
    f]                        d dl mZmZmZ d dlZd dlZd dlZd dlZd dlZd dl	m
Z
 d dlmZ d dlZ ej                  e      Z G d de      Z G d de      Z G d d	e      Z G d
 de      Z G d de      Z G d de      Zy)    )divisionprint_functionunicode_literalsN)unicode_strc                   T    e Zd ZdZddZd Zd Zd Zd Zd Z	d	 Z
d
 Zd Zd Zd Zy)SpellCheckerd   Nc                 .    || _         d | _        i | _        y N)_language_db_backend_cached_queries)selflanguage_dbs     6/usr/lib/python3/dist-packages/Onboard/SpellChecker.py__init__zSpellChecker.__init__(   s    '!    c                 T   |.| j                   r| j                   j                          d| _         nh|dk(  rt        }nt        }| j                   rt	        | j                         |k(  s2| j                   r| j                   j                           |       | _         | j                          y)z' Switch spell check backend on the fly Nr   )r   stophunspell
aspell_cmdtypeinvalidate_query_cache)r   backend_classs      r   set_backendzSpellChecker.set_backend-   sz    ?}}""$ DM!|!#==&&0==MM&&( &##%r   c                    d}| j                  |      }| j                  r|| j                  j                         k(  ss| j                  j                          |r| j                  j	                  |       d}n9t
        j                  dj                  t        | j                        |             | j                          |S )NFTz0No matching dictionaries for '{backend}' {dicts}r   dicts)
_find_matching_dictsr   get_active_dict_idsr   start_loggerinfoformatr   r   )r   dict_idssuccessidss       r   set_dict_idszSpellChecker.set_dict_idsA   s    ''1==dmm7799MM ##C(O$fT$---@+3 % 56 	##%r   c                 b    g }|D ]'  }| j                  |      }|s|j                  |       ) |S r   )_find_matching_dictappend)r   r&   resultsdict_idids        r   r    z!SpellChecker._find_matching_dictsQ   s<     	#G))'2Br"	# r   c                    | j                         }d}||v r|}|S |j                  dd      }||v r|}|S | j                  rI| j                  j                  |      \  }}||v r|}|S | j                  j	                  |      }|r||v r|}|S )z
        Try to match up the given dict_id with the available dictionaries.
        Look for alternatives if there is no direct match.
         _-)get_supported_dict_idsreplacer   split_lang_idget_main_lang_id)r   r.   available_dict_idsresultalt_id	lang_codecountry_codelang_ids           r   r+   z SpellChecker._find_matching_dictY   s    
 "88:((F"  __S#.F++  ""*.*;*;*I*I'*R'	< 22&F 	 #//@@KG7.@#@!(r   c                     d}g }| j                   r2| j                  |      }|D ]  }|d   d   |kD  r ||fS |d   }|d   } ||fS )z
        Return spelling suggestions for word.
        Multiple result sets may be returned, as the spell
        checkers may return more than one result for certain tokens,
        e.g. before and after hyphens.
        Nr      r   query_cached)r   wordcaret_offsetspansuggestionsr-   r9   s          r   find_correctionszSpellChecker.find_correctionsv   sw     ==''-G " !!9Q<,. [   %Qiay	! [  r   c                 r    g }| j                   r#| j                  |      }|D cg c]  }|d   	 }}|S c c}w )z
        Return misspelled spans (begin- to end-index) inside word.
        Multiple result sets may be returned, as the spell
        checkers may return more than one result for certain tokens,
        e.g. before and after hyphens.
        r   r@   )r   rB   spansr-   r9   s        r   find_incorrect_spansz!SpellChecker.find_incorrect_spans   sC     ==''-G .556VAY5E5 6s   4c                    | j                   j                  |      }|t        | j                         }|| j                  k\  rc|dz  }t        j                  dj                  ||             t        | j                   j                         d       }t        ||d       | _         | j                  |      }d|g}|| j                   |<   t        j                         |d<   |d   S )	zF
        Return cached query or ask the backend if necessary.
        N   z,shrinking query cache from {} to {} entries.c                     | d   d   S )Nr?   r    )xs    r   <lambda>z+SpellChecker.query_cached.<locals>.<lambda>   s    1a r   )keyg        r   r?   )r   getlenMAX_QUERY_CACHE_SIZEr#   debugr%   sorteditemsdictquerytime)r   rB   rX   sizenew_sizequeriesr-   s          r   rA   zSpellChecker.query_cached   s     $$((.=t++,Dt00019L%vdH57 !!5!5!;!;!='8:'+GHI,>'?$ jj&G'NE).D  &99;aQxr   c                 8    | j                   j                  |      S r   )r   rX   )r   rB   s     r   rX   zSpellChecker.query   s    }}""4((r   c                     i | _         y r   )r   r   s    r   r   z#SpellChecker.invalidate_query_cache   s
    !r   c                 6    | j                   j                         S r   )r   r4   r_   s    r   r4   z#SpellChecker.get_supported_dict_ids   s    }}3355r   r   )__name__
__module____qualname__rS   r   r   r)   r    r+   rF   rI   rA   rX   r   r4   rM   r   r   r   r   %   s?    "
&( :!, 8)"6r   r   c                   >    e Zd ZdZd
dZd
dZd Zd Zd Zd Z	d	 Z
y)	SCBackendz2 Abstract base class of all spellchecker backends Nc                      d | _         d | _        y r   )_active_dicts_pr   r&   s     r   r   zSCBackend.__init__   s    !r   c                 p    || _         t        j                  dj                  t	        |       |             y )Nzstarting '{backend}' {dicts}r   )rg   r#   r$   r%   r   ri   s     r   r"   zSCBackend.start   s,    %3fT$Zxf@	Br   c                     | j                         r6t        j                  dj                  t	        |                    d | _        y y )Nzstopping '{backend}')r   )
is_runningr#   r$   r%   r   rg   r_   s    r   r   zSCBackend.stop   s8    ??LL/ &d&46!%D r   c                     t               S r   NotImplementedErrorr_   s    r   rl   zSCBackend.is_running   s    "$$r   c                    g }| j                   r!| j                   j                         d| _         | j                   rt        |      t        d      k(  rd|z   dz   }|j                  d      }nd|z   dz   }| j                   j                  j                  |       | j                   j                  j                          	 | j                   j                  j                         j                  d      }|j                         }|s	 |S |dd d	k(  r|j                  d
      }|d   j                         }t        |d         dz
  }|t        |d         z   }|||d   g}	|d   j                         j                  d      }
|j                  |	|
g       |dd dk(  rc|j                  d
      }|d   j                         }t        |d         dz
  }|t        |d         z   }|||d   g}	g }
|j                  |	|
g       @|S z
        Query for spelling suggestions.
        Text may contain one or more words. Each word generates its own
        list of suggestions. The spell checker backend decides about
        word boundaries.
        Nr1   ^
UTF-8   ^   
r?   &:r      z, #rK   rh   pollr   encodestdinwriteflushstdoutreadlinedecodestripsplitintrR   r,   r   textr-   linessectionsabeginendrD   rE   s              r   rX   zSCBackend.query        77477<<>1DG77 DzT"X%TzD({{7+d{U*GGMM%GGMM!GGNN++-44W=GGI$ # Ra5C< wws|H ))+A!IME!C!I-C!3!-D"*1+"3"3"5";";D"AKNND+#67Ra5C< wws|H ))+A!IME!C!I-C!3!-D"$KNND+#67) , r   c                     t               6
        Return raw supported dictionary ids.
        rn   r_   s    r   r4   z SCBackend.get_supported_dict_ids       "##r   c                     | j                   S z/
        Return active dictionary ids.
        rg   r_   s    r   r!   zSCBackend.get_active_dict_ids       !!!r   r   )ra   rb   rc   __doc__r   r"   r   rl   rX   r4   r!   rM   r   r   re   re      s*    <B
&%/b$"r   re   c                        e Zd ZdZddZd fd	Z fdZd Z ej                  dej                  ej                  z        Zd Zd Zd	 Zed
        Zd Z xZS )r   a   
    Hunspell backend using the C API.

    Doctests:
    # known word
    >>> sp = hunspell(["en_US"])
    >>> sp.query("test")
    []

    # unknown word
    >>> sp = hunspell(["en_US"])
    >>> sp.query("jdaskljasd")  # doctest: +ELLIPSIS
    [[...
    c                 f    d | _         t        j                  | |       |r| j                  |       y y r   )_osk_hunspellre   r   r"   ri   s     r   r   zhunspell.__init__$  s.    !4*JJx  r   c                    t         t        |   |       |r| j                  |d         \  }}t        j                  dj                  ||             |rY	 t        j                  ||      | _	        t        j                  dj                  | j                  j                                      y y y # t        $ r2}t        j                  dt        |      z          d | _	        Y d }~y d }~ww xY w)Nr   zusing hunspell files '{}', '{}'zdictionary encoding '{}'z#failed to create hunspell backend: )superr   r"   _search_dict_filesr#   r$   r%   oskHunspellr   get_encoding	Exceptionerrorr   )r   r&   dicaffe	__class__s        r   r"   zhunspell.start*  s    h#H-..x{;HCLL:#VC-/.),c3)?D&LL!;"(&););)H)H)J"KM 	  ! .MM"G"-a.#1 2)-D&&.s   AB0 0	C+9(C&&C+c                 h    t         t        |           | j                         rd | _        d | _        y y r   )r   r   r   rl   r   rg   r   r   s    r   r   zhunspell.stop;  s/    h"$??!%D!%D r   c                     | j                   d uS r   )r   r_   s    r   rl   zhunspell.is_runningA  s    %%--r   z[^-_\s]+c                    g }| j                   r| j                  j                  |      }|D ]  }|j                         }|j	                         }|j                         }|||g}	 | j                   j                  |      dk(  r7t        | j                   j                  |            }	|j                  ||	g        |S # t        $ r |j                  |g g       Y w xY w)u  
        Query for spelling suggestions.
        Text may contain one or more words. Each word generates its own
        list of suggestions. Word boundaries are chosen to match the
        behavior of the hunspell command line tool, i.e. split at '-','_'
        and whitespace.

        Doctests:
        # one prediction token, two words for the spell checker
        >>> sp = hunspell(["en_US"])
        >>> q = sp.query("conter_trop")
        >>> q  # doctest: +ELLIPSIS
        [[[0, 6, 'conter'], [...
        >>> len(q)
        2

        # dashes
        >>> sp = hunspell(["en_US"])
        >>> sp.query("ubuntu-system")  # doctest: +ELLIPSIS
        [[[0, 6, 'ubuntu'], ['Ubuntu', 'Kubuntu', 'urbanite', 'urbanity']]]

        # unrecognized word returns error span with zero choices (# mark)
        >>> q = sp.query("ἄναρχος")
        >>> q  # doctest:
        [[[0, 7, 'ἄναρχος'], []]]
        >>> len(q)
        1

        # dictionaries come in various encodings, spot-check German
        >>> sp = hunspell(["de_DE"])
        >>> sp.query("Frühstück")
        []
        >>> sp.query("Früstück")   # doctest: +ELLIPSIS
        [[[0, 8, 'Früstück'], ['Frühstück', ...

        # dictionaries come in various encodings, spot-check Spanish
        >>> sp = hunspell(["es_ES"])
        >>> sp.query("situación")
        []
        >>> sp.query("situción")   # doctest: +ELLIPSIS
        [[[0, 8, 'situción'], ['situación', ...

        # dictionaries come in various encodings, spot-check Portuguese
        >>> sp = hunspell(["pt_PT"])
        >>> sp.query("questão")
        []
        >>> sp.query("quetão")   # doctest: +ELLIPSIS
        [[[0, 6, 'quetão'], ['questão', ...

        # dictionaries come in various encodings, spot-check French
        >>> sp = hunspell(["fr_FR"])
        >>> sp.query("garçon")
        []
        >>> sp.query("garçoon")   # doctest: +ELLIPSIS
        [[[0, 7, 'garçoon'], ['garçon', ...

        # dictionaries come in various encodings, spot-check Italian
        >>> sp = hunspell(["it_IT"])
        >>> sp.query("parlerò")
        []
        >>> sp.query("parllerò")   # doctest: +ELLIPSIS
        [[[0, 8, 'parllerò'], ['parlerò', ...

        # dictionaries come in various encodings, spot-check Russian
        >>> sp = hunspell(["ru_RU"])
        >>> sp.query("ОБЕДЕННЫЙ") # dinner
        []
        >>> sp.query("ОБЕДЕНЫЙ")   # doctest: +ELLIPSIS
        [[[0, 8, 'ОБЕДЕНЫЙ'], ['ОБЕДЕННЫЙ', ...

        # dictionaries come in various encodings, spot-check Greek
        >>> sp = hunspell(["el_GR"])
        >>> sp.query("Ωκεανού")
        []
        >>> sp.query("Ωκεαανού")   # doctest: +ELLIPSIS
        [[[0, 8, 'Ωκεαανού'], ['Ωκεανού', ...

        r   )r   
SPLITWORDSfinditergroupr"   r   spelllistsuggestr,   UnicodeEncodeError)
r   r   r-   matchesmatchrB   r   r   rD   rE   s
             r   rX   zhunspell.queryF  s    ^ oo..t4G  /{{}		sD)/))//5:&*4+=+=+E+Ed+K&Lk':;/   * / NND":.	/s   %AB>>CCc                    g }g }| j                         }|D ]d  }t        j                  j                  |dt        j                  j                  z   dz         }|j                  t        j                  |             f |D ]r  }t        j                  j                  t        j                  j                  |            \  }}|j                         j                  d      rb|j                  |       t |S )aO  
        Return raw supported dictionary ids.
        They may not all be valid language ids, e.g. en-GB
        instead of en_GB for myspell dicts.

        Doctests:
        # Just check it does anything at all
        >>> sp = hunspell(["en_US"])
        >>> sp.get_supported_dict_ids()   # doctest: +ELLIPSIS
        ['...
        *r   hyph)_get_dict_pathsospathjoinextsepextendglobsplitextbasenamelower
startswithr,   )r   r&   	filenamespathsr   fnr=   _exts           r   r4   zhunspell.get_supported_dict_ids  s      	$$& 	,DdC"''..$85$@ABTYYr]+	,
  	)BGG,,RWW-=-=b-ABMGT==?--f5(	)
 r   c                 v    | j                         }| j                  ||d      }| j                  ||d      }||fS )z9 Locate dictionary and affix files for the given dict_id r   r   )r   _find_file_in_paths)r   r.   r   r   r   s        r   r   zhunspell._search_dict_files  sA    $$&&&ugu=&&ugu=Cxr   c                     | D ]c  }t         j                  j                  ||t         j                  j                  z   |z         }t         j                  j	                  |      sa|c S  y)z+ Search for a file name in multiple paths. N)r   r   r   r   exists)r   name	extensionr   files        r   r   zhunspell._find_file_in_paths  sS      	D77<<dRWW^^&;i&GHDww~~d#	 r   c                    g }t         j                  j                  }g d}g d}g d}|j                  d       t        j                  d      }|r |j                  |j                  |             |j                  |       t        j                  d      }|r"|j                  |       |j                  |       |j                  |       |S )z
        Return all paths where dictionaries may be located.
        Path logic taken from the source of the hunspell command line tool.
        )z/usr/share/hunspellz/usr/share/myspellz/usr/share/myspell/dictsz/Library/Spelling)z.openoffice.org/3/user/wordbookz.openoffice.org2/user/wordbookz .openoffice.org2.0/user/wordbookzLibrary/Spelling)
z+/opt/openoffice.org/basis3.0/share/dict/oooz//usr/lib/openoffice.org/basis3.0/share/dict/ooozP/opt/openoffice.org2.4/share/dict/ooo,/usr/lib/openoffice.org2.4/share/dict/ooo,z%/opt/openoffice.org2.3/share/dict/oooz)/usr/lib/openoffice.org2.3/share/dict/oooz%/opt/openoffice.org2.2/share/dict/oooz)/usr/lib/openoffice.org2.2/share/dict/ooozO/opt/openoffice.org2.1/share/dict/ooo,/usr/lib/openoffice.org2.1/share/dict/oooz%/opt/openoffice.org2.0/share/dict/oooz)/usr/lib/openoffice.org2.0/share/dict/ooo.DICPATHHOME)r   r   pathsepr,   getenvr   r   )r   r   r   LIBDIRSUSEROOODIRSOOODIRSdicpathhomes           r   r   zhunspell._get_dict_paths  s    
 ''//!
 
9 	S))I&LLw/0Wyy LLLL%Wr   r   )ra   rb   rc   r   r   r"   r   rl   recompileUNICODEDOTALLr   rX   r4   r   staticmethodr   r   __classcell__r   s   @r   r   r     sg    !."&. KBII)=>JcJ:  .r   r   c                   F     e Zd ZdZd fd	Z fdZd Zd Zd Zd Z	 xZ
S )	SCBackend_cmdz. Abstract base class of command line backends c                 :    t         t        |   |       d | _        y r   )r   r   r   rh   )r   r&   r   s     r   r   zSCBackend_cmd.__init__  s    mT+H5r   c                     t         t        |   t               | j	                         r<| j
                  j                          | j
                  j                          d | _        y y r   )r   r   r   r&   rl   rh   	terminatewaitr   s    r   r   zSCBackend_cmd.stop  sE    mT+H5??GGGGLLNDG r   c                     | j                   d uS r   )rh   r_   s    r   rl   zSCBackend_cmd.is_running  s    77d?"r   c                    g }| j                   r!| j                   j                         d| _         | j                   rt        |      t        d      k(  rd|z   dz   }|j                  d      }nd|z   dz   }| j                   j                  j                  |       | j                   j                  j                          	 | j                   j                  j                         j                  d      }|j                         }|s	 |S |dd d	k(  r|j                  d
      }|d   j                         }t        |d         dz
  }|t        |d         z   }|||d   g}	|d   j                         j                  d      }
|j                  |	|
g       |dd dk(  rc|j                  d
      }|d   j                         }t        |d         dz
  }|t        |d         z   }|||d   g}	g }
|j                  |	|
g       @|S rq   r{   r   s              r   rX   zSCBackend_cmd.query  r   r   c                     t               r   rn   r_   s    r   r4   z$SCBackend_cmd.get_supported_dict_idsK  r   r   c                     | j                   S r   r   r_   s    r   r!   z!SCBackend_cmd.get_active_dict_idsQ  r   r   r   )ra   rb   rc   r   r   r   rl   rX   r4   r!   r   r   s   @r   r   r   	  s%    8#/b$"r   r   c                   2     e Zd ZdZddZd fd	Zd Z xZS )hunspell_cmda  
    Hunspell backend, using the "hunspell" command.

    Doctests:
    # known word
    >>> sp = hunspell_cmd(["en_US"])
    >>> sp.query("test")
    []

    # unknown word
    >>> sp = hunspell_cmd(["en_US"])
    >>> sp.query("jdaskljasd")  # doctest: +ELLIPSIS
    [[...
    c                 X    t         j                  | |       |r| j                  |       y y r   re   r   r"   ri   s     r   r   zhunspell_cmd.__init__g  &    4*JJx  r   c           	         t         t        |   |       g d}|r|ddj                  |      gz  }	 t	        j
                  |t        j                  t        j                  d      | _        | j                  j                  j                          y # t        $ r@}t        j                  t        ddj                  |      |             d | _        Y d }~y d }~ww xY w)N)r   -az-irt   z-d,Tr~   r   	close_fdsFailed to execute '{}', {} )r   r   r"   r   
subprocessPopenPIPErh   r   r   OSErrorr#   r   _formatr   r&   argsr   r   s       r   r"   zhunspell_cmd.startl  s    lD'10T388H-..D		 &&t-7__.8oo157DG GGNN##% 	MM'">HHTNA/ 0DGG	   AB 	C6CCc           	      x   g }ddg}	 t        j                  |t         j                  t         j                  t         j                  d      }|j                  d      \  }}d}|j	                  d      j                  d      D ]n  }|rVd	|vr |S t        j                  j                  |      }|j                         j                  d
      s|j                  |       |j                  d      smd}p 	 |S # t        $ r:}	t        j                  t        ddj!                  |      |	             Y d}	~	|S d}	~	ww xY w)z
        Return raw supported dictionary ids.
        They may not all be valid language ids, e.g. en-GB for myspell dicts.
        r   z-DT)r~   r   stderrr   r1   Frt   rs   /r   zAVAILABLE DICTIONARIESr   r   N)r   r   r   communicater   r   r   r   r   r   r   r,   r   r#   r   r   r   )
r   r&   r   pouterrin_dictsr   r=   r   s
             r   r4   z#hunspell_cmd.get_supported_dict_ids~  s"   
 D!	0  '1(2(2+/	1A
 }}R(HC H

7+11$7 $$;  !gg..t4G"==?55f= 0??#;<#H$    	0MM'">HHTNA/ 0 0	0s%   BC6 A C6 /C6 6	D9?/D44D9r   ra   rb   rc   r   r   r"   r4   r   r   s   @r   r   r   X  s    !
$"r   r   c                   2     e Zd ZdZddZd fd	Zd Z xZS )r   z
    Aspell backend.

    Doctests:
    # known word
    >>> sp = aspell_cmd(["en_US"])
    >>> sp.query("test")
    []

    # unknown word
    >>> sp = aspell_cmd(["en_US"])
    >>> sp.query("jdaskljasd")  # doctest: +ELLIPSIS
    [[...
    c                 X    t         j                  | |       |r| j                  |       y y r   r   ri   s     r   r   zaspell_cmd.__init__  r   r   c           	         t         t        |   |       ddg}|r|ddj                  |      gz  }	 t	        j
                  |t        j                  t        j                  d      | _        | j                  j                  j                          y # t        $ r@}t        j                  t        ddj                  |      |             d | _        Y d }~y d }~ww xY w)	Naspellr   z-lr   Tr   r   r   )r   r   r"   r   r   r   r   rh   r   r   r   r#   r   r   r   s       r   r"   zaspell_cmd.start  s    j$%h/$T388H-..D		 &&t-7__.8oo157DG GGNN##% 	MM'">HHTNA/ 0DGG	r   c           	      0   g }g d}	 t        j                  |      j                  d      j                  d      }|D cg c]  }|s|	 c}S # t        $ r9}t
        j                  t        ddj                  |      |             Y d}~Pd}~ww xY wc c}w )r   )r
  dumpr   rt   rs   r   r   N)	r   check_outputr   r   r   r#   r   r   r   )r   r&   r   r   r/   s        r   r4   z!aspell_cmd.get_supported_dict_ids  s     *	0!..t4!'t 
 &,r,,  	0MM'">HHTNA/ 0 0	0 -s"   3A BB	B/BBr   r  r   s   @r   r   r     s    !
$-r   r   )
__future__r   r   r   r   r   rY   r   r   Onboard.utilsr   Onboard.oskr   logging	getLoggerra   r#   objectr   re   r   r   r   r   rM   r   r   <module>r     s   * B A 	   	  %  
'

H
%Z66 Z6zP" P"fqy qhL"I L"^H= HV2- 2-r   