B
    5Ù&e0  ã               @   sR   d dl Z d dlZdZdd„ Zdd„ ZG dd„ dƒZG d	d
„ d
ƒZG dd„ dƒZdS )é    Nz1.0c             C   s
   |   d¡S )zaWill remove single or double quotes from the start and end of a string
    and return the result.z'")Ústrip)Ús© r   úT/home/dcms/DCMS/lib/python3.7/site-packages/supybot/plugins/Dict/local/dictclient.pyÚdequote   s    r   c             C   s   d|   dd¡ d S )z”This function will put a string in double quotes, properly
    escaping any existing double quotes with a backslash.  It will
    return the result.ú"z\")Úreplace)Ústrr   r   r   Úenquote   s    r
   c               @   sŠ   e Zd ZdZd#dd„Zdd„ Zdd	„ Zd
d„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"S )$Ú
ConnectionaJ  This class is used to establish a connection to a database server.
    You will usually use this as the first call into the dictclient library.
    Instantiating it takes two optional arguments: a hostname (a string)
    and a port (an int).  The hostname defaults to localhost
    and the port to 2628, the port specified in RFC.Ú	localhostéD
  c             C   sL   t   t jt j¡| _| j ||f¡ | j d¡| _| j dd¡| _|  ¡  d S )NÚrbÚwbr   )	ÚsocketÚAF_INETÚSOCK_STREAMÚsockÚconnectÚmakefileÚrfileÚwfileÚsaveconnectioninfo)ÚselfÚhostnameÚportr   r   r   Ú__init__(   s
    zConnection.__init__c             C   sB   | j  ¡  d¡ ¡ }| d¡r&d|gS | dd¡\}}t|ƒ|gS )zÈGeneric function to get a result code.  It will return a list
        consisting of two items: the integer result code and the text
        following.  You will not usually use this function directly.Úutf8ú[Nú é   )r   ÚreadlineÚdecoder   Ú
startswithÚsplitÚint)r   ÚlineÚcodeÚtextr   r   r   Úgetresultcode/   s
    
zConnection.getresultcodec             C   s0   |   ¡ \}}|dk s|dkr(tdt ƒ‚||gS )zjUsed when expecting a single line of text -- a 200-class
        result.  Returns [intcode, remaindertext]éÈ   i,  z)Got '%s' when 200-class response expected)r)   Ú	Exceptionr&   )r   r'   r(   r   r   r   Úget200result9   s
    zConnection.get200resultc             C   s<   g }x,| j  ¡  d¡ ¡ }|dkr$P | |¡ qW d |¡S )z‡Used when expecting multiple lines of text -- gets the block
        part only.  Does not get any codes or anything!  Returns a string.r   Ú.Ú
)r   r!   r"   r   ÚappendÚjoin)r   Údatar&   r   r   r   Úget100blockC   s    zConnection.get100blockc             C   sL   |   ¡ \}}|dk s|dkr(td| ƒ‚|  ¡  d¡}|  ¡ d }|||gS )zŸUsed when expecting multiple lines of text, terminated by a period
        and a 200 code.  Returns: [initialcode, [bodytext_1lineperentry],
        finalcode]éd   r*   z)Got '%s' when 100-class response expectedr.   r   )r)   r+   r2   r$   r,   )r   r'   r(   Z	bodylinesÚcode2r   r   r   Úget100resultN   s    zConnection.get100resultc             C   s:   i }x0|   ¡ d D ] }| dd¡\}}t|ƒ||< qW |S )zxUsed when expecting a dictionary of results.  Will read from
        the initial 100 code, to a period and the 200 code.r    r   )r5   r$   r   )r   Údictr&   ÚkeyÚvalr   r   r   Ú
get100dict\   s
    zConnection.get100dictc             C   sB   |   ¡ \}}|dkst‚t d|¡ ¡ \}}| d¡| _|| _dS )zkCalled by __init__ to handle the initial connection.  Will
        save off the capabilities and messageid.éÜ   z<(.*)> (<.*>)$r-   N)r,   ÚAssertionErrorÚreÚsearchÚgroupsr$   ÚcapabilitiesÚ	messageid)r   r'   ÚstringZcapstrÚmsgidr   r   r   r   e   s
    zConnection.saveconnectioninfoc             C   s   | j S )z<Returns a list of the capabilities advertised by the server.)r?   )r   r   r   r   Úgetcapabilitiesn   s    zConnection.getcapabilitiesc             C   s   | j S )z1Returns the message id, including angle brackets.)r@   )r   r   r   r   Úgetmessageidr   s    zConnection.getmessageidc             C   s*   t | dƒr| jS |  d¡ |  ¡ | _| jS )zœGets a dict of available databases.  The key is the db name
        and the value is the db description.  This command may generate
        network traffic!ÚdbdescszSHOW DB)ÚhasattrrE   Úsendcommandr9   )r   r   r   r   Ú
getdbdescsv   s
    


zConnection.getdbdescsc             C   s*   t | dƒr| jS |  d¡ |  ¡ | _| jS )z Gets a dict of available strategies.  The key is the strat
        name and the value is the strat description.  This call may
        generate network traffic!Ú
stratdescsz
SHOW STRAT)rF   rI   rG   r9   )r   r   r   r   Úgetstratdescs   s
    


zConnection.getstratdescsc             C   sh   t | dƒsi | _|| jkr$| j| S |dkrN|dkrN|| j ¡ krNtd| ƒ‚t| |ƒ| j|< | j| S )zÇGets a Database object corresponding to the database name passed
        in.  This function explicitly will *not* generate network traffic.
        If you have not yet run getdbdescs(), it will fail.ÚdbobjsÚ*ú!zInvalid database name '%s')rF   rK   rE   Úkeysr+   ÚDatabase)r   Údbnamer   r   r   ÚgetdbobjŒ   s    


zConnection.getdbobjc             C   s   | j  | d¡d ¡ dS )zQTakes a command, without a newline character, and sends it to
        the server.zutf-8ó   
N)r   ÚwriteÚencode)r   Úcommandr   r   r   rG       s    zConnection.sendcommandc       	      C   sÜ   |   ¡  |dkr0|dkr0||   ¡ kr0td| ƒ‚|  dt|ƒ d t|ƒ ¡ |  ¡ d }g }|dkrjg S |dkr~td	| ƒ‚xX|  ¡ \}}|d
ksœ|dkržP t d|¡ ¡ \}}|  ¡ }| 	t
| |  |¡||ƒ¡ q€W |S )aí  Returns a list of Definition objects for each matching
        definition.  Parameters are the database name and the word
        to look up.  This is one of the main functions you will use
        to interact with the server.  Returns a list of Definition
        objects.  If there are no matches, an empty list is returned.

        Note: database may be '*' which means to search all databases,
        or '!' which means to return matches from the first database that
        has a match.rL   rM   zInvalid database '%s' specifiedzDEFINE r   r   i(  é–   zUnknown code %dé—   Nz^"(.+)" (\S+))rH   r+   rG   r
   r)   r<   r=   r>   r2   r/   Ú
DefinitionrQ   )	r   ÚdatabaseÚwordr'   Úretvalr(   Z
resultwordZresultdbÚdefstrr   r   r   Údefine¥   s(    
zConnection.definec       	      C   s  |   ¡  |  ¡  ||   ¡  ¡ kr,td| ƒ‚|dkrX|dkrX||  ¡  ¡ krXtd| ƒ‚|  dt|ƒt|ƒt|ƒf ¡ |  ¡ d }|dkrg S |dkr¤td	| ƒ‚g }xB|  ¡  d
¡D ]0}| dd¡\}}| 	t
| |  |¡t|ƒƒ¡ q¸W |  ¡ d dkr
td| ƒ‚|S )a¦  Gets matches for a query.  Arguments are database name,
        the strategy (see available ones in getstratdescs()), and the
        pattern/word to look for.  Returns a list of Definition objects.
        If there is no match, an empty list is returned.

        Note: database may be '*' which means to search all databases,
        or '!' which means to return matches from the first database that
        has a match.zInvalid strategy '%s'rL   rM   zInvalid database name '%s'zMATCH %s %s %sr   i(  é˜   zUnexpected code %dr.   r   r    éú   zUnexpected end-of-list code %d)rJ   rH   rN   r+   rG   r
   r)   r2   r$   r/   rX   rQ   r   )	r   rY   ÚstrategyrZ   r'   r[   Z	matchlineZ	matchdictZ	matchwordr   r   r   ÚmatchË   s.    	zConnection.matchN)r   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r)   r,   r2   r5   r9   r   rC   rD   rH   rJ   rQ   rG   r]   ra   r   r   r   r   r   "   s    


		&r   c               @   s@   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dS )rO   z=An object corresponding to a particular database in a server.c             C   s   || _ || _dS )zRInitialize the object -- requires a Connection object and
        a database name.N)ÚconnÚname)r   ÚdictconnrP   r   r   r   r   ò   s    zDatabase.__init__c             C   s   | j S )z)Returns the short name for this database.)rg   )r   r   r   r   Úgetnameø   s    zDatabase.getnamec             C   sR   t | dƒr| jS |  ¡ dkr$d| _n(|  ¡ dkr8d| _n| j ¡ |  ¡  | _| jS )NÚdescriptionrL   zAll DatabasesrM   zFirst matching database)rF   rj   ri   rf   rH   )r   r   r   r   Úgetdescriptionü   s    
zDatabase.getdescriptionc             C   sf   t | dƒr| jS |  ¡ dkr$d| _n<|  ¡ dkr8d| _n(| j d| j ¡ d | j ¡ d ¡| _| jS )	z2Returns a string of info describing this database.ÚinforL   z>This special database will search all databases on the system.rM   zKThis special database will return matches from the first matching database.z
SHOW INFO r.   r    )rF   rl   ri   rf   rG   rg   r0   r5   )r   r   r   r   Úgetinfo  s    
zDatabase.getinfoc             C   s   | j  |  ¡ |¡S )z¢Get a definition from within this database.
        The argument, word, is the word to look up.  The return value is the
        same as from Connection.define().)rf   r]   ri   )r   rZ   r   r   r   r]     s    zDatabase.definec             C   s   | j  |  ¡ ||¡S )zGet a match from within this database.
        The argument, word, is the word to look up.  The return value is
        the same as from Connection.define().)rf   ra   ri   )r   r`   rZ   r   r   r   ra     s    zDatabase.matchN)
rb   rc   rd   re   r   ri   rk   rm   r]   ra   r   r   r   r   rO   ð   s   rO   c               @   s2   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ ZdS )rX   z/An object corresponding to a single definition.Nc             C   s   || _ || _|| _|| _dS )zôInstantiate the object.  Requires: a Connection object,
        a Database object (NOT corresponding to '*' or '!' databases),
        a word.  Optional: a definition string.  If not supplied,
        it will be fetched if/when it is requested.N)rf   ÚdbrZ   r\   )r   rh   rn   rZ   r\   r   r   r   r   #  s    zDefinition.__init__c             C   s   | j S )z9Get the Database object corresponding to this definition.)rn   )r   r   r   r   Úgetdb-  s    zDefinition.getdbc             C   s.   | j s(| j |  ¡  ¡ | j¡d  ¡ | _ | j S )zJGet the definition string (the actual content) of this
        definition.r   )r\   rf   r]   ro   ri   rZ   Ú	getdefstr)r   r   r   r   rp   1  s    "zDefinition.getdefstrc             C   s   | j S )z#Get the word this object describes.)rZ   )r   r   r   r   Úgetword8  s    zDefinition.getword)N)rb   rc   rd   re   r   ro   rp   rq   r   r   r   r   rX   !  s
   

rX   )r   r<   Úversionr   r
   r   rO   rX   r   r   r   r   Ú<module>   s    O1