m
EFc           @   s6  d  Z  d k l Z d Z d k Z d k Z d k Z d k Z d k Z d k	 Z	 d k
 Z
 d k Z d k Z d k Z d k Z d k Z d k Z d k Z d k Z d k Z d k Z d k Z d k Z d k Z d k Z d k Z d k Z d k Td k Z e i e i d  y e  Wn  e! j
 o d k" l# Z  n Xy e$ d  e% Z& Wn e' j
 o e( Z& n Xe( a) d e* f d	     YZ+ d
 e+ f d     YZ, d e+ f d     YZ- d e+ f d     YZ. d e+ f d     YZ/ d e+ f d     YZ0 d e- e0 f d     YZ1 d e' f d     YZ2 d e+ f d     YZ3 d e+ f d     YZ4 d e4 f d     YZ5 d e4 f d     YZ6 d  e+ f d!     YZ7 d" e+ f d#     YZ8 d$ e+ f d%     YZ9 d& e* f d'     YZ: e i; i< i= Z> e i? d(  Z@ d) eA f d*     YZB d+ eB f d,     YZC d- eA f d.     YZD e% e( d/  ZE d0   ZF d1   ZG eG d2  d3   ZH eH d4  d5 eA f d6     YZI e( e( d d7  ZJ d8 g d9  ZK eL d: d;  ZM eL d d<  ZN eL d=  ZO eL d>  ZP d?   ZQ d@   ZR d dA  ZS eL dB  ZT eL dC  ZU eL dD  ZV dE   ZW dF   ZX dG   ZY dH   ZZ dI   Z[ eL dJ  Z\ dK   Z] g  dL  Z^ eL e% dM  Z_ dN eA f dO     YZ` h  Za h  Zb eL eL eL eL dP  Zc dQ   Zd dR   Ze dS   Zf d kg Zh e ii ij eh ik dT   dU e il d Uem in   Zo dV ap e iq ar e is at eL au y ec   Wn% ev j
 o dW GHe iw dX  n XdY   Zx dZ   Zy d[   Zz d\   Z{ eL d]  Z| d8 e i} j p ee   e i} j o e| e%  n e i? d^ e i~  Z d_   Z} e i   Z e i   Z g  Z eL e% e( d`  Z da   Z db   Z e( dc  Z eL dd  Z eL de  Z e i   Z df   Z e i dg e  Z e i dh  e i e%  di   Z dj   Z d k Z e i e  dk   Z eI e i e i  Z eI e i e i e(  Z dl e i f dm     YZ e i o d k Z d k Z d kg Zh eh ik dn do  Z e i   Z e ii i e  o e i e  n e i   Z xC e i i   D]2 Z e i eL e e i e dV e i e dX  qyWe i e  Z e i e i e  e  Z e i e  n e dp j o; d k Z d k Z dq e i   GHdr e i GHe i   n d S(s   s  
Library to get and put pages on a MediaWiki.

Contents of the library (objects and functions to be used outside, situation
late August 2004)

Classes:
Page: A MediaWiki page
    __init__              : Page(Site, Title) - the page with title Title on wikimedia site Site
    title                 : The name of the page, in a form suitable for an interwiki link
    urlname               : The name of the page, in a form suitable for a URL
    titleWithoutNamespace : The name of the page, with the namespace part removed
    section               : The section of the page (the part of the name after '#')
    sectionFreeTitle      : The name without the section part
    aslink                : The name of the page in the form [[Title]] or [[lang:Title]]
    site                  : The wiki this page is in
    encoding              : The encoding of the page
    isAutoTitle           : If the title is a well known, auto-translatable title
    autoFormat            : Returns (dictName, value), where value can be a year, date, etc.,
                            and dictName is 'YearBC', 'December', etc.
    isCategory            : True if the page is a category, false otherwise
    isImage               : True if the page is an image, false otherwise

    get (*)               : The text of the page
    exists (*)            : True if the page actually exists, false otherwise
    isRedirectPage (*)    : True if the page is a redirect, false otherwise
    isEmpty (*)           : True if the page has 4 characters or less content, not
                            counting interwiki and category links
    botMayEdit (*)        : True if bot is allowed to edit page
    interwiki (*)         : The interwiki links from the page (list of Pages)
    categories (*)        : The categories the page is in (list of Pages)
    linkedPages (*)       : The normal pages linked from the page (list of Pages)
    imagelinks (*)        : The pictures on the page (list of ImagePages)
    templates (*)         : All templates referenced on the page (list of strings)
    getRedirectTarget (*) : The page the page redirects to
    isDisambig (*)        : True if the page is a disambiguation page
    getReferences         : List of pages linking to the page
    namespace             : The namespace in which the page is
    permalink (*)         : The url of the permalink of the current version
    move                  : Move the page to another title
    put(newtext)          : Saves the page
    put_async(newtext)    : Queues the page to be saved asynchronously
    delete                : Deletes the page (requires being logged in)

    (*) : This loads the page if it has not been loaded before; permalink might
          even reload it if it has been loaded before

Site: a MediaWiki site
    messages              : There are new messages on the site
    forceLogin()          : Does not continue until the user has logged in to
                            the site
    getUrl()              : Retrieve an URL from the site
    mediawiki_message(key): Retrieve the text of the MediaWiki message with
                            the key "key"
    has_mediawiki_message(key) : True if this site defines a MediaWiki message
                                 with the key "key"
    Special pages:
        Dynamic pages:
            allpages(): Special:Allpages
            newpages(): Special:Newpages
            longpages(): Special:Longpages
            shortpages(): Special:Shortpages
            categories(): Special:Categories

        Cached pages:
            deadendpages(): Special:Deadendpages
            ancientpages(): Special:Ancientpages
            lonelypages(): Special:Lonelypages
            uncategorizedcategories(): Special:Uncategorizedcategories
            uncategorizedpages(): Special:Uncategorizedpages
            unusedcategories(): Special:Unusuedcategories

Other functions:
getall(): Load pages via Special:Export
setAction(text): Use 'text' instead of "Wikipedia python library" in
    editsummaries
handleArgs(): Checks whether text is an argument defined on wikipedia.py
    (these are -family, -lang, -log and others)
translate(xx, dict): dict is a dictionary, giving text depending on language,
    xx is a language. Returns the text in the most applicable language for
    the xx: wiki
setUserAgent(text): Sets the string being passed to the HTTP server as
    the User-agent: header. Defaults to 'Pywikipediabot/1.0'.

output(text): Prints the text 'text' in the encoding of the user's console.
input(text): Asks input from the user, printing the text 'text' first.
showDiff(oldtext, newtext): Prints the differences between oldtext and newtext
    on the screen

getLanguageLinks(text,xx): get all interlanguage links in wikicode text 'text'
    in the form xx:pagename
removeLanguageLinks(text): gives the wiki-code 'text' without any interlanguage
    links.
replaceLanguageLinks(oldtext, new): in the wiki-code 'oldtext' remove the
    language links and replace them by the language links in new, a dictionary
    with the languages as keys and either Pages or titles as values
getCategoryLinks(text,xx): get all category links in text 'text' (links in the
    form xx:pagename)
removeCategoryLinks(text,xx): remove all category links in 'text'
replaceCategoryLinks(oldtext,new): replace the category links in oldtext by
    those in new (new a list of category Pages)
stopme(): Put this on a bot when it is not or not communicating with the Wiki
    any longer. It will remove the bot from the list of running processes,
    and thus not slow down other bot threads anymore.

(   s
   generatorss6   $Id: wikipedia.py 4215 2007-09-08 18:17:35Z cydeweys $N(   t   *t    (   s   Seti= t   Errorc           B   s   t  Z d  Z RS(   s   Wikipedia error(   t   __name__t
   __module__t   __doc__(    (    (    t=   /home/cat/public_html/arm/mrobe/wiki/pywikipedia/wikipedia.pyR      s   t
   NoUsernamec           B   s   t  Z d  Z RS(   s!   Username is not in user-config.py(   R   R   R   (    (    (    R   R      s   t   NoPagec           B   s   t  Z d  Z RS(   s   Page does not exist(   R   R   R   (    (    (    R   R      s   t   IsRedirectPagec           B   s   t  Z d  Z RS(   s   Page is a redirect page(   R   R   R   (    (    (    R   R	      s   t   IsNotRedirectPagec           B   s   t  Z d  Z RS(   s   Page is not a redirect page(   R   R   R   (    (    (    R   R
      s   t
   LockedPagec           B   s   t  Z d  Z RS(   s   Page is locked(   R   R   R   (    (    (    R   R      s   t   LockedNoPagec           B   s   t  Z d  Z RS(   sG   Page does not exist, and creating it is not possible because of a lock.(   R   R   R   (    (    (    R   R      s   t   NoSuchEntityc           B   s   t  Z d  Z RS(   s"   No entity exist for this character(   R   R   R   (    (    (    R   R      s   t   SectionErrorc           B   s   t  Z d  Z RS(   s)   The section specified by # does not exist(   R   R   R   (    (    (    R   R      s   t   PageNotSavedc           B   s   t  Z d  Z RS(   s   Saving the page has failed(   R   R   R   (    (    (    R   R      s   t   EditConflictc           B   s   t  Z d  Z RS(   s8   There has been an edit conflict while uploading the page(   R   R   R   (    (    (    R   R      s   t   SpamfilterErrorc           B   s   t  Z d  Z d   Z RS(   sX   Saving the page has failed because the MediaWiki spam filter detected a blacklisted URL.c         C   s   | |  _ | f |  _ d  S(   N(   t   argt   selft   urlt   args(   R   R   (    (    R   t   __init__   s    	(   R   R   R   R   (    (    (    R   R      s    t   ServerErrorc           B   s   t  Z d  Z RS(   s   Got unexpected server response(   R   R   R   (    (    (    R   R      s   t   BadTitlec           B   s   t  Z d  Z RS(   s   Server responded with BadTitle.(   R   R   R   (    (    (    R   R      s   t   UserBlockedc           B   s   t  Z d  Z RS(   s$   Your username or IP has been blocked(   R   R   R   (    (    (    R   R      s   t   PageNotFoundc           B   s   t  Z d  Z RS(   s   Page not found in list(   R   R   R   (    (    (    R   R      s   s   ^(.+?) *: *(.*)$t   Pagec           B   s2  t  Z d  Z e d d  Z d   Z d   Z d   Z e e d  Z	 e d  Z
 e d  Z e d	  Z d
   Z d   Z e e d  Z d   Z d   Z e e e e e e d  Z e e e e e e d  Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z d   Z  d   Z! d   Z" e e e e d  Z# e e e e d   Z$ d!   Z% e e e e e d"  Z& e e e e d#  Z' e e e e e e e d$  Z( d%   Z) d&   Z* d'   Z+ e d(  Z, d)   Z- d*   Z. d+   Z/ e e d,  Z0 d-   Z1 d.   Z2 d/   Z3 d0   Z4 d1   Z5 e e e d2 d3  Z6 e e e d2 d4  Z7 d5 e e d6  Z8 e8 Z9 d7   Z: e e e e d8  Z; e e e d9  Z< d:   Z= e d;  Z> e d<  Z? d= e d>  Z@ d? d? e e e e d@  ZA e e e dA  ZB e e e e dB  ZC RS(C   s   A page on the wiki.i    c      	   C   s  yt  |  _ | d j o t   } n6 t |  t d  t d  g j o t |  } n | |  _ | p
 | } n t	 |  } t | d | d | } t i d |  } t i d d |  i   } | i d  o | d	 } d
 |  _ n
 | |  _ xAt o9t i |  }	 |	 p Pn |	 i d	  }
 |
 i   } |  i   i |  } | o |	 i d  } | |  _ Pq | |  i   i i  i!   j o |	 i d  } | |  i   i" j o! | d j o t# d   qn t | |  i   i i$  |  _ | d j o( | d
 d j o d
 |  _ | d	 } q2q | |  i   i i% j o |  i   i i% | |  i   i i$ j o |	 i d  } q2t& d | | f  |  i   i" } | d g j o
 | } n |  i   i i% | } y t | |  |  _ Wn2 t) j
 o& t* d | |  i   | f   n X|	 i d  } q Pq q W| i+ d  } | d
 j oi | | d	 i   |  _- t. |  i- |  i   i/    |  _- |  i- d j o d |  _- n | |  i   } n
 d |  _- t0 |  d
 j o0 |  i   i1 p | d
 i2   | d	 } qn |  i d
 j o$ |  i   i3 |  i  d | } n |  i- o | d |  i- 7} n | |  _4 d |  _5 d |  _6 d |  _7 d |  _8 d |  _9 d |  _: Wn4 t; i< d IJt; i< d | | | | f IJ  n Xd S(   sH  
        Constructor. Normally called with two arguments:
        Parameters:
         1) The wikimedia site on which the page resides
         2) The title of the page as a unicode string

        The argument insite can be specified to help decode
        the name; it is the wikimedia site where this link was found.
        R   u    t   sitet   site2t   NFCs   [ _]+t    t   :i   i    i   s   Can't have an empty self-linku*   Target link '%s' has different family '%s't   commonssS   %s is not a local page on %s, and the %s family is not supported by PyWikipediaBot!u   #u   :s   Exception in Page constructors1   site=%s, title=%s, insite=%s, defaultNamespace=%iN(=   t   FalseR   t   _editrestrictionR   t   Nonet   getSitet   typet   _sitet   insitet   html2unicodet   titlet   tt   url2unicodet   unicodedatat	   normalizet   ret   subt   stript
   startswitht
   _namespacet   defaultNamespacet   Truet   reNamespacet   matcht   mt   groupt   pt   lowert   lowerNst   getNamespaceIndext   nst   familyt   langst   keyst   langR   t   namet   known_familiest   outputt	   otherlangt
   familyNamet
   ValueErrorR   t   findt   sectionStartt   _sectiont   sectionencodet   encodingt   lent   nocapitalizet   uppert	   namespacet   _titlet   editRestrictiont
   _permalinkt	   _userNamet   _ipeditt	   _editTimet   _deletedRevst   syst   stderr(   R   R   R*   R(   R4   RF   R<   R>   RG   R8   R:   RJ   R+   (    (    R   R      s    	 	%	

	 		)
$! 	 $
						c         C   s   |  i S(   s>   The site of the page this Page refers to,
           without :N(   R   R'   (   R   (    (    R   R   k  s     c         C   s   |  i i   S(   sJ   
        Returns the character encoding used on this page's wiki.
        N(   R   R'   RM   (   R   (    (    R   RM   p  s     c         C   s:   |  i d t  } | i |  i   i    } t i |  S(   s`   The name of the page this Page refers to, in a form suitable
           for the URL of the page.t
   underscoreN(	   R   R*   R5   t   encodeR   RM   t   encodedTitlet   urllibt   quote(   R   R]   R*   (    (    R   t   urlnamev  s     c         C   s   |  i } | oS | i d  d j o9 y t i |  i d d  } Wq_ t j
 o q_ Xqc n | o | i d d  } n | S(   s*   The name of this Page, as a Unicode strings   ''is   %20R   t   _N(
   R   RR   R*   t	   savetitleRI   R^   R_   t   replacet   KeyErrorR[   (   R   R[   Rb   R*   (    (    R   R*   }  s     	c         C   sK   |  i   d j o |  i d |  Sn! |  i d |  i d d  d Sd S(   sY   
        Returns the name of the page without the namespace and without section.
        i    R[   R    i   N(   R   RQ   R*   R[   t   sectionFreeTitlet   split(   R   R[   (    (    R   t   titleWithoutNamespace  s     c         C   s   |  i S(   s   The name of the section this Page refers to. Sections are
           denominated by a # in the title(). If no section is referenced,
           None is returned.N(   R   RK   (   R   R[   (    (    R   t   section  s     c         C   sJ   |  i d |  } |  i d |  } | o | t |  d  Sn | Sd  S(   NR[   i   (   R   Rh   R[   t   sectionNameR*   RN   (   R   R[   R*   Ri   (    (    R   Re     s
    c         C   s   |  i   i t i d  S(   s(   A console representation of the pagelinkRc   N(   R   t   aslinkR\   t   configt   console_encoding(   R   (    (    R   t   __str__  s     c         C   s   d |  i i t |   f S(   s%   A more complete string representations   %s{%s}N(   R   t	   __class__R   t   str(   R   (    (    R   t   __repr__  s     c         C   s   | p |  i   t   j oy |  i   i t   i j o6 d |  i   i i |  i   i |  i d t  f Sq d |  i   i |  i d t  f Sn; | o% |  i
   d	 j o d |  i   Sn d |  i   Sd S(
   s  
        A string representation in the form of a link. The link will
        be an interwiki link if needed.

        If you set forceInterwiki to True, the link will have the format
        of an interwiki link even if it points to the home wiki.

        If you set textlink to True, the link will always appear in text
        form (that is, links to the Category: and Image: namespaces will
        be preceded by a : character).

        Note that the family is never included.
        s   [[%s:%s:%s]]Rb   s	   [[%s:%s]]i   i   s   [[:%s]]s   [[%s]]N(   i   i   (   t   forceInterwikiR   R   R%   R?   RC   RB   R*   R5   t   textlinkRQ   (   R   Rq   Rr   (    (    R   Rj     s     6'c         C   s   |  i   d d j	 S(   s>   If the title is a well known, auto-translatable title
        i    N(   R   t
   autoFormatR$   (   R   (    (    R   t   isAutoTitle  s     c         C   sE   t  |  d  p1 d k } | i |  i   i   |  i    } n | S(   sq  Returns (dictName, value), where value can be a year, date, etc.,
           and dictName is 'YearBC', 'Year_December', or another dictionary name.
           Please note that two entries may have exactly the same autoFormat,
           but be in two different namespaces, as some sites have categories with the same names.
           Regular titles return (None,None).t   _autoFormatN(   t   hasattrR   t   datet   getAutoFormatR   t   languageRg   Ru   (   R   Rw   Ru   (    (    R   Rs     s
     	(c      
   C   s  xx d d d d d d d d d	 d
 g
 D]R } | |  i   j o9 t o t d |  i    n t d |  i     q% q% W|  i   d j o t d |  i     n |  i   i	 |  i
    o& t d |  i   |  i   f   n | o? x d d d g D]' }
 t |  |
  o t |  |
  qqWn t |  d  o  | o | o t |  i  nT t |  d  oC |  i t j o | o q|  i t j o | o q|  i  n t |  d  pDy |  i d | d | d | d |  \ |  _ |  _ |  _ |  i   }	 |	 oJ t i d |	 |  i  } t o& | o t d |  i d t   qYn |  i   i  d j o t! |  i  |  _ n Wqt j
 o t |  _   qt j
 o2 } t |  _ | |  _ | o | o   qqt# j
 o t# |  _   qXn |  i S(   s  The wiki-text of the page. This will retrieve the page if it has not
           been retrieved yet. This can raise the following exceptions that
           should be caught by the calling code:

            NoPage: The page does not exist

            IsRedirectPage: The page is a redirect. The argument of the
                            exception is the title of the page it redirects to.

            SectionError: The subject does not exist on a page with a # link

            Set get_redirect to True to follow redirects rather than raise an exception.
            Set force to True to force a reload of all page attributes, including errors.
            Set nofollow_redirects to True to not follow redirects but obey all other exceptions.
            Set change_version_date to False if you have already loaded the page before and
                do not check this version for changes before saving
        t   #t   <t   >t   [t   ]t   |t   {t   }s   
u   �u   Illegal character in %s!s   Illegal character in %s!is   %s is in the Special namespace!s   %s is not a local page on %s!t	   _redirargt   _getexceptiont	   _contentst   get_redirectt   throttlet   sysopt   nofollow_redirectss
   =+ *%s *=+u#   WARNING: Section does not exist: %sRq   t   eoN($   t   illegalCharR   Re   t   verboseRE   Rj   R   RQ   R   t   isInterwikiLinkR*   t   forcet   attrRv   t   delattrR   R   R	   R   R   t   getEditPageR   R   R   t
   _isWatchedRS   Rh   t   hnR/   t   searchR8   R5   RB   t   resolveEsperantoXConventionR   R   (   R   R   R   R   R   R   t   change_edit_timeR   R   R   R   R8   (    (    R   t   get  s\     % &  6"				c         C   sV  t  } d% } t o t d |  i    n |  i   i	 |  i
    } | o | d | } n | o t   n t  } d }
 xx| pp|  i   i | d | }	 |	 i d  d j o t d |  i     n d |	 j o t |  i   _ n t  |  i   _ y: t i d	 |	  i   } t i d
 |	  i   } t } Wq t j
 o|	 i |  i   i d   d j o% t  |  i   |  i d t    q|	 i |  i   i d   d j o t! d |  i     q|	 i |  i   i d   d j o t! d   q|  i   i" d  o? |	 i |  i   i d   d j o t! d |  i     q|	 i d  d j o t# d |    qt t$ |	   t d |  i   i%   | |
 f  t& i' |
 d  |
 d 9}
 |
 d j o
 d }
 qq Xq Wt i( d  } | i |	  } | o& |  i   i+ | i, d  d | n7 |  i   i- d t   p |  i   i+ d d | n | ot t i d |	  } | o | i, d  |  _0 n
 d |  _0 t i d |	  } | o | i, d  |  _1 qd |  _1 n |  i   i2 i3 |  i   i4    o1 t i( |  i   i2 i3 |  i   i4     } n t i( d  } | i |	  } | p% t |  i   |  i d t    n t i( d   } | i |	  } | o
 t } n |  i   i8   i9 |	 | | ! } |  i0 d j o t o t d!  n d } n | on |  i:   o# d" | i, d  |  i:   f } n | i, d  } | o | |  _= q| p t? |   qn |  i:   op t i d# t i@ |  i:    tA |	 |  i   iB     } | p+ y |  iC Wqt j
 o tD  qXqn |	 | | !} tF |  } x' | o | d d$ j o | d  } q"W| | | f S(&   s  
        Get the contents of the Page via the edit page.
        Do not use this directly, use get() instead.

        Arguments:
            get_redirect  - Get the contents, even if it is a redirect page

        This routine returns a unicode string containing the wiki text.
        u   Getting page %ss   &oldid=i   R   s"   <title>Wiki does not exist</title>iu   Wiki %s does not exist yets   <div class="usermessage">s   <textarea[^>]*>s   </textarea>t   blockedtitleRq   t
   viewsourceu<   %s does not exist, and it is blocked via cascade protection.t   whitelistedittitleu.   Page editing is forbidden for anonymous users.t   nocreatetitleuF   %s does not exist, and page creation is forbidden for anonymous users.s$   var wgPageName = "Special:Badtitle";s   BadTitle: %suX   WARNING: No text area found on %s%s. Maybe the server is down. Retrying in %i minutes...i<   i   i   s:   \<input type='hidden' value=\"(.*?)\" name=\"wpEditToken\"t	   getalwaysR   s%   value="(\d+)" name=["']wpEdittime["']t   0s&   value="(\d+)" name=["']wpStarttime["']sM   <li id="ca-history"><a href=".*?title=.*?&amp;action=history".*?>.*?</a></li>sM   \<input tabindex='[\d]+' type='checkbox' name='wpWatchthis' checked='checked'u   DBG> page may be locked?!s   %s#%ssD   \.3D\_*(\.27\.27+)?(\.5B\.5B)?\_*%s\_*(\.5B\.5B)?(\.27\.27+)?\_*\.3Ds   
 N(G   R"   t	   isWatchedR$   RS   R   RE   R   Rj   R   t   edit_addressR`   t   patht   oldidR   t   get_throttlet   textareaFoundt   retry_idle_timet   getUrlR   t   textRI   R   R5   t   messagesR/   R   t   endt   i1t   startt   i2t   AttributeErrort   mediawiki_messageR   R   t   has_mediawiki_messageR   t   unicodet   hostnamet   timet   sleept   compilet   Rwatcht   tokenloct   putTokenR9   t   getTokenR   R8   RW   t
   _startTimeR?   t   RversionTabRy   t   matchVersionTabt   Rt   matchWatchingt   redirectRegexR7   Rh   t   redirtargetR   R   R   R	   t   escapeRL   RM   R   R   t   xt   unescape(   R   R   R   R   R   R   R   R   R   R   R   R   R   R   R   RS   R   R   R   R   R   R8   R   R   (    (    R   R   &  s    	  
%%%%;#
&	%1%
"
#: c         C   sD   d |  i   i |  i   i   |  i   i |  i    |  i   f S(   s6   
        Get the permalink page for this page
        s   %s://%s%s&oldid=%iN(   R   R   t   protocolR   t   get_addressR*   t   latestRevision(   R   (    (    R   t	   permalink  s     c         C   s7   |  i p  t |  i   |  g d t n t |  i  S(   s7   
        Get the latest revision for this page
        R   N(   R   RT   t   getallR   R5   t   int(   R   (    (    R   R     s     
 c         C   sX   y |  i   WnC t j
 o t Sn. t j
 o t Sn t j
 o t Sn Xt S(   s   
        True iff the page exists, even if it's a redirect.

        If the title includes a section, False if this section isn't found.
        N(   R   R   R   R"   R	   R5   R   (   R   (    (    R   t   exists  s     	c         C   sX   y |  i   WnC t j
 o t Sn. t j
 o t Sn t j
 o t Sn Xt S(   sA   True if the page is a redirect page, False if not or not existingN(   R   R   R   R"   R	   R5   R   (   R   (    (    R   t   isRedirectPage  s     	c         C   sS   |  i   } t |  } t | d |  i   } t |  d j  o t Sn t Sd S(   s   
        True if the page has less than 4 characters, except for
        language links and category links, False otherwise.
        Can raise the same exceptions as get()
        R   i   N(	   R   R   t   txtt   removeLanguageLinkst   removeCategoryLinksR   RN   R5   R"   (   R   R   (    (    R   t   isEmpty  s     c         C   s'   |  i   } | d j o | d d j S(   Ni    i   i   (   R   RQ   R>   (   R   R>   (    (    R   t
   isTalkPage  s    c         C   s  t  o t Sn y |  i   } Wn  t t t f j
 o t Sn XyG |  i o |  i	   i
 d t  n |  i	   i
   |  i	   i } Wn t j
 o d } n Xx | D] } | d d j o t Sq | d d j o t | d  d j o t Sq| d d i d d  \ } } | i d  } | d j o* d	 | j p | | j o t Sqat Sn | d
 j o* d	 | j p | | j o t Sqt Sqq q Wt S(   sn  
        True if page doesn't contain {{bots}} or {{nobots}} or
        contains them and active bot is allowed or not allowed
        to edit said page

        Note that the framework does not enforce this restriction; if it
        is desired to implement authorization-checking for a particular
        bot, the bot must call this method before editing.
        R   i    t   Nobotst   Botsi   t   =t   ,t   allowt   allt   denyN(   t   ignore_bot_templatesR5   R   t   templatesWithParamst	   templatesR   R	   R   RS   R   t
   forceLogint   _loggedInAst   usernameR   R$   t   templateR"   RN   Rf   R&   t   bots(   R   R   R   R&   R   R   (    (    R   t
   botMayEdit  sB    	  	
  c         C   s   |  i S(   N(   R   RU   (   R   (    (    R   t   userName  s    c         C   s   |  i S(   N(   R   RV   (   R   (    (    R   t   isIpEdit"  s    c         C   s   |  i S(   N(   R   RW   (   R   (    (    R   t   editTime%  s    c         C   s   |  i S(   s   Gives the number of the namespace of the page. Does not work for
           all namespaces in all languages, only when defined in family.py.
           If not defined, it will return 0 (the main namespace)N(   R   R3   (   R   (    (    R   RQ   (  s     c         C   s   |  i   d j S(   sB   
        True if the page is a Category, false otherwise.
        i   N(   R   RQ   (   R   (    (    R   t
   isCategory6  s     c         C   s   |  i   d j S(   sQ   
        True if the page is an image description page, false otherwise.
        i   N(   R   RQ   (   R   (    (    R   t   isImage<  s     c         C   s   t  |  d  p |  i   i i |  i i  } x |  i   D]n } y | d i
   | d } Wn t j
 o | i
   } n X| i d d  } | | j o t } Pq; q; Wt } n | S(   Nt   _isDisambigi    i   Ra   R   (   Rv   R   R   R?   t   disambigR'   RB   t   locdisR   t   tnRP   t
   IndexErrorRc   R5   R   R"   (   R   R   R   R   (    (    R   t
   isDisambigB  s     	
c         c   sn  t  i d j o d t  _ n |  i   } |  i   i |  i    } t d d |  i   i i	 }
 y |  i   i d  }	 Wn  t j
 o d t  i }	 n Xt  i d j o d p d } t i d	 | |	  }	 t i d
 |	 i d d   } d } |  i   i d  o |  i   i d  |  _ n |  i   i d  o |  i   i d  |  _ n t   } x| o t d |  i    t   |  i   i |  } t | d t i  d |
 } | i" d |  } | d j	 o | i% d i d d  } n d } | i" d  } | d j o d Sn xE |  i' | | | | |  D]( } | | j o | V| i- |  q9q9WqeWd S(   s  
        Yield all pages that link to the page. If you need a full list of
        referring pages, use this:

            pages = [page for page in s.getReferences()]

        Parameters:
        * follow_redirects      - if True, also returns pages that link to a
                                  redirect pointing to the page.
        * withTemplateInclusion - if True, also returns pages where self is
                                  used as a template.
        * onlyTemplateInclusion - if True, only returns pages where self is
                                  used as a template.
        * redirectsOnly         - if True, only returns redirects to self.
        i  t   divt   ids   whatlinkshere-nexts   next %ii   s   \1s   \2s   {{PLURAL:\$1\|(.*?)\|(.*?)}}s   ^%s$s   $1s   [0-9]+t
   Isredirectt
   Istemplateu   Getting references to %st   convertEntitiest   parseOnlyTheseR   t   hrefs   &amp;t   &R   t   ulN(.   Rk   t   special_page_limitR   R   t   references_addressR`   R   t   SoupStrainerR?   t
   content_idt   contentR   t   next_msgRd   t   pluralR/   R0   R   Rc   t   nextpatternt   delayR   t   _isredirectmessaget   _istemplatemessaget   sett   refPagesRE   Rj   R   R   R   t   BeautifulSoupt   HTML_ENTITIESt   bodyRI   t	   next_textR$   t   parentt   reflistt   _parse_reflistt   follow_redirectst   withTemplateInclusiont   onlyTemplateInclusiont   redirectsOnlyt   paget   add(   R   R  R  R  R	  R   R   R  R   R   R   R   R   R  R   R  R   R
  (    (    R   t   getReferencesT  sR     	 	
 c         c   s  x| d d t D]} | i i } | d j o t d |  n t |  i
   |  }	 t t } } | i i d t  }
 |
 d j	 o |  i
   i d  oL |  i |
 j o< t |  i
   |	 i    i   |  i   j o
 t } q n |  i
   i d  o |  i |
 j o
 t } qn | p | p | o& | p | o | p | o |	 Vn | oU | oN | i d  } | d j	 o. x+ |  i | | | | |  D]
 }	 |	 VqWqq q Wd S(	   s   
        For internal use only

        Parse a "Special:Whatlinkshere" list of references and yield Page
        objects that meet the criteria
        (used by getReferences)
        t   lit	   recursives+   DBG> invalid <li> item in Whatlinkshere: %sR   R   R   R   N(   R  R"   t   linkt   at   stringR*   R$   RE   R   R   R   R:   t
   isredirectt
   istemplatet   findNextSiblingR5   t	   textafterR   R   t   getRedirectTargetRe   R   R  R  R	  R  RI   t   sublistR  (   R   R  R  R  R  R	  R*   R  R  R:   R  R  R  (    (    R   R    s2    	  &.&4
 c         c   s  |  i   } | i |  i    } d }	 |  i   i   d j o d } d } n d } d } t	 i
 d  } t } x| ot } t   } t d |  i    x t o | i |  } y, | i |  t |  }
 | i |  } WnV t j
 oJ t d	 |	  t i |	 d
  |	 d 9}	 |	 d j o
 d }	 q q n X| |
 | !} Pq Wy" | i d  }
 | i d  } Wn t j
 o
 qt n X| |
 | d !} | i d  } x t |  D] \ } } | d j o qn | d j o qn | i" |  } | oI | i$ | i% d   | d j o" t d  t d | | f  qJqqWt' |  } | i(   x | D] } t* | |  VqkWqt Wd S(   s   
        Yield all pages that link to the page. If you need a full list of
        referring pages, use this:

            pages = [page for page in s.getReferences()]

        i   i   u   <!-- start content -->u   <!-- end content -->u   <body t   printfooters%   <li><a href=.*>(?P<title>.*)</a></li>u   Getting references to %su=   Invalid page received from server.... Retrying in %i minutes.f60.0i   i   u   <ul>u   </ul>u   
u   </li>R*   u   DBG> Unparsed line:u   (%i) %sN(+   R   R   R   R`   R   R   t   versionnumbert   startmarkert	   endmarkerR/   R   t   listitempatternR5   t   moreR"   R   t	   fileLinksRE   Rj   R   R   t   indexRN   R   R   RH   R   R   t   rindexRf   t   txtlinest	   enumeratet   numt   lineR   t   lmatchR  R9   R$   t   listt   sortt   fileLinkR   (   R   R%  R   R(  R#  R   R   R   R!  R   R   R  R  R  R  R$  R  (    (    R   t   getFileLinks  sn     
 	 

 
 
 c         C   sl   z5 t  i i   y t i   Wn t j
 o n XWd t  i i   Xt  i |  | | | | | | f  d S(   sh  Asynchronous version of put (takes the same arguments), which
           places pages on a queue to be saved by a daemon thread.
           All arguments are the same as for .put(), except --
           callback: a callable object that will be called after the page put
                     operation; this object must take two arguments:
                     (1) a Page object, and (2) an exception instance, which
                     will be None if the page was saved successfully.
           The callback is intended to be used by bots that need to keep track
           of which saves were successful.
        N(   t   page_put_queuet   mutext   acquiret
   _putthreadR   t   AssertionErrort   releaset   putR   t   newtextt   commentt   watchArticlet	   minorEditR   t   callback(   R   R1  R2  R3  R4  R   R5  (    (    R   t	   put_async  s     	 c      	   C   s  | p+ |  i   p t d |  i     q2 n |  i o7 t d |  i    |  i d t d t	  t	 |  _ n | p t } |  i oG y$ |  i   i d t  t d  Wq t j
 o t    q Xn |  i   i   t i o |  i   o | } t i p5 |  i   i i t i j o |  i   i t i j oq d k } | i |  i    } | i |  } | o9 | i   | i   j o  | t |  i   | i  7} qqn | d j oK t" |  d  o |  i# } qd k$ }
 |
 i% |  i&   d	 |  i   } n |  i'   } |  i }	 |	 oZ t" |  d
  o
 |  `* n y& |  i d t d t d t d t  Wqt+ j
 o qXn |  i   i d j o t, |  } n |  i- | | | | | |  i   i/ d |	  d |	 S(   s   Replace the new page with the contents of the first argument.
           The second argument is a string that is to be used as the
           summary for the modification

           If watchArticle is None, leaves the watchlist status unchanged.
        u8   Not allowed to edit %s because of a restricting templateuS   Page %s is semi-protected. Getting edit page to find out if we are allowed to edit.R   R   R   u$   Page is locked, using sysop account.NR   R   R   R   R   (0   R   R   R   R   Rj   R#   RE   R   R5   R"   R2  t   actionRS   R   R   R   Rk   t   cosmetic_changesR   R1  t   oldt   cosmetic_changes_mylang_onlyR?   RC   RB   t   mylangt   CosmeticChangesToolkitt	   ccToolkitt   changeR1   t	   translatet
   msg_appendR3  R$   Rv   R   t	   watchlistR   R*   R   t   newPageR   R   R   t   doubleXForEsperantot   putPageR4  R   (   R   R1  R2  R3  R4  R   RB  R9  R8  R   RA  R=  (    (    R   R0    sT     


@	 (	% 
	c	         C   s  t  } |  i   i   d j o; | p | o( |  i   i d | d |  } t	 } qZ n |  i   i
   } |  i   i |  i    } | i |  i   i    }
 | i |  i   i    } h  d d <d |
 <d | <} t i o t t i  | d <n | o d	 | d
 <d	 | d <n |  i | d
 <|  i | d <| o d | d <n | o d | d <n | o | | d <n |  i   i   i d j o' |  i   i    d j o d | d <n d } xt	 ot"   | o t# d |  i$ d t	   n t# d |  i$ d t	   |  i   i
   t i% i&   j o~ | i' dA  | i' d t( f  |  i   i) |  } t+ i, t+ i- |  i   i.   d |  i   i
   | |   } d } nT y% |  i   i0 | | |  \ } } Wn+ t1 i2 j
 o } t4 d | i3   n X| d j o2| i5 d j oO d | i6 i&   j o9 t7 o t# | d t  n t# d  t8 i9 d   qn | i: d!  oG t# d" |  t8 i9 d# |  | d$ 9} | d% j o
 d% } qqn d& | j o t; d'   qB|  i   i< d(  o |  i   i= d(  | j o yO t> i? t> i@ |  i   i= d)   iA d* d+   } | iC |  iD d,  } Wnt | | iF d-  d. | iF d/  !iG   }	 t> iI d0 d	 |	  }	 t> iC d1 |	  } | o | iD   } q|	 } n XtK |   qBd2 | j o t; d3   qB|  i   i< d4  o |  i   i= d4  | j o yZ | pO |  i   iL d t	  t# d5  |  iM | | | | | d6 d@ d7 t	 d t	 Sn Wq>tO j
 o t4 d8 |  i$     q>XqB| oU d9 | j oH t# d:  |  iM d; | d< | d= | d> | d? | d6 d@ d7 t	 d |  SqBt# |  | i5 | iP | f Sn |  i   i
   t i% i&   j o d@ Sq| i5 | iP | f SqWd@ S(B   s   
        Upload 'text' as new contents for this Page by filling out the edit
        page.

        Don't use this directly, use put() instead.
        i   t   getagainR   t   wpSavet   1t	   wpSummaryt
   wpTextbox1t   maxlagR   t
   wpEdittimet   wpStarttimet   wpMinoreditt   wpWatchthist   wpEditTokent   lovetot   recipest
   masterediti   u   Creating page %sRq   u   Changing page %ss   Content-types!   application/x-www-form-urlencodeds
   User-agents   ://u    s   Bad status line: %si  s   x-database-lagt   newlineu-   Pausing 5 seconds due to database server lag.i   s,   <html>
<head>
<title>Wikimedia Error</title>u;   Wikimedia has technical problems; will retry in %i minutes.i<   i   i   s!   id='wpTextbox2' name="wpTextbox2"u   An edit conflict has occured.t   spamprotectiontitlet   spamprotectionmatchs   \$1s   (?P<url>[^<]*)R   s   <!-- start content -->i   s   <!-- end content -->s   <.*?>s   http://[\w\-\.]+s   <label for='wpRecreate'u   Someone deleted the page.R   u-   Page is locked, retrying using sysop account.t   tokent   gettokenu   The page %s is locked. Possible reasons: There is a cascade lock, or you're affected by this MediaWiki bug: http://bugzilla.wikimedia.org/show_bug.cgi?id=9226s	   <textareau#   Changing page has failed. Retrying.R   R2  R3  R4  RB  N(   s   Content-types!   application/x-www-form-urlencoded(Q   R"   t   newTokenRetrievedR   R   R  RW  RV  R   R   R5   R   t   hostt   put_addressR`   t   addressR2  R\   RM   t   encodedCommentR   t   encodedTextt   predataRk   RJ  Ro   RB  RW   R   R4  R3  t   famRC   Ry   t   retry_delayt   put_throttleRE   Rj   t   authenticateRA   t   appendt	   useragentt	   urlEncodet   datat   urllib2t   urlopent   RequestR   t   responset   postFormt   httplibt   BadStatusLineR$  R   t   statust   msgR   R   R   R2   R   R   R   R/   R   R   Rc   t   reasonRR   R9   R   RI   R1   t   relevantR0   R8   R   R   RD  R$   R   t   reason(   R   R   R2  R3  R4  RB  RV  RW  R   Rq  R\  R]  Rp  RY  R[  R`  R$  Rf  Rj  RX  R   R8   R^  (    (    R   RD  d  s     !

5 "?
%&


23)
2


"c         C   s[   |  i o t i } n
 t i } y) | |  i   i i |  i   i	 t
 SWn t Sn Xd S(   s   
        Returns True iff:
            * the page is unprotected, and we have an account for this site, or
            * the page is protected, and we have a sysop account for this site.
        N(   R   RS   Rk   t
   sysopnamest   userdictt	   usernamesR   R?   RC   RB   R5   R"   (   R   Rt  (    (    R   t   canBeEdited  s     
	!c         C   s   |  i   } | d j  o d Sn |  i   oh |  i   d j o t |  i   |  i    Sq t |  i   |  i   i | d  d |  i    Sn5 t |  i   |  i   i | d  d |  i    Sd S(   s   
        If self is a talk page, returns the associated content page; otherwise,
        returns the associated talk page. Returns None if self is a special
        page.
        i    i   R    N(   R   RQ   R>   R$   R   R   R   Rg   (   R   R>   (    (    R   t   toggleTalkPage  s     8c         C   s`  g  } t |  i   d |  i   d |  i   } x)| i   D]\ } } xR |  i   i
 i |  i   i    D], } | i   i d | d |  i    } qn Wy) | i |  i | | d |  i    Wq= t j
 o$ t d |  i   | | f  q= t j
 o$ t d |  i   | | f  q= t j
 o$ t d |  i   | | f  q= Xq= W| S(	   s3  A list of interwiki links in the page. This will retrieve
           the page text to do its work, so it can raise the same exceptions
           that are raised by the get() method.

           The return value is a list of Page objects for each of the
           interwiki links in the page text.
        R(   t   pageLinks   {{s   }}u6   ERROR: link from %s to [[%s:%s]] is invalid encoding?!u=   ERROR: link from %s to [[%s:%s]] contains invalid character?!uE   ERROR: link from %s to [[%s:%s]] contains invalid unicode reference?!N(   t   resultt   getLanguageLinksR   R   R   Rj   t   llt	   iteritemst   newSiteRB  R?   t   pagenamecodesRy   t   pagenametextR*   Rc   t   newTitleRc  Rn   t   UnicodeErrorRE   R   RH   (   R   RB  R  R}  R  Ry  R{  (    (    R   t	   interwiki/  s"     * % *)!!&c         C   sE   y% t  |  i d |  |  i    } Wn t j
 o g  } n X| S(   s>  
        A list of categories that the article is in. This will retrieve
        the page text to do its work, so it can raise the same exceptions
        that are raised by the get() method.

        The return value is a list of Category objects, one for each of the
        category links in the page text.
        R   N(   t   getCategoryLinksR   R   R   R   t   category_links_to_returnR   (   R   R   R  (    (    R   t
   categoriesF  s     %c         C   ss   t  | t  p d Sn |  i   | i   j p t |  i   | i    Sn |  i   } | i   } t | |  S(   sX   Pseudo method to be able to use equality and inequality tests on
           Page objectsiN(	   t
   isinstancet   otherR   R   R   t   cmpR*   t   owntitlet
   othertitle(   R   R  R  R  (    (    R   t   __cmp__U  s     c         C   s   t  t |    S(   s   Pseudo method that makes it possible to store Page objects as
           keys in hash-tables. This relies on the fact that the string
           representation of an instance can not change after the construction.
        N(   t   hashRo   R   (   R   (    (    R   t   __hash__a  s     c         C   sG  g  } y% t |  i d t  |  i    } WnA t j
 o
   n- t j
 o
   n t	 j
 o g  Sn Xt
 | |  i    } t |  } t i d  } x | i |  D] } | i d  } | i   i d  o q n |  i   i |  pH y t |  i   |  } Wn
 q n X| i   o | i |  q?q q W| S(   su   Gives the normal (not-interwiki, non-category) pages the page
           links to, as a list of Page objects
        R   s&   \[\[(?P<title>[^\]\|]*)(\|[^\]]*)?\]\]R*   Rz   N(   Ry  R   R   R   R5   R   t   thistxtR   R	   R   R   t   removeDisabledPartsR/   R   t   Rlinkt   finditerR7   R9   R*   R1   R2   R   R   R
  Re   Rc  (   R   R  R
  Ry  R*   R7   R  (    (    R   t   linkedPagesh  s4     %	 c         C   s  g  } xM |  i   D]? } | i   o, t | i   | i    } | i	 |  q q W|  i
 d |  } t i d t i  }	 t i d |  i   i   |  i   i i d d  f  } x\ |	 i |  D]K } xB | i |  D]1 } t |  i   | i d   } | i	 |  q Wq W| of t   i   } t i d t i  }
 x? |
 i |  D]* } | i	 t |  i   | d |   qQWn t |  S(
   s8  
        Gives the images the page shows, as a list of ImagePage objects.
        This includes images in galleries.
        If loose is set to true, this will find anything that looks like it could be an image.
        This is useful for finding, say, images that are passed as parameters to templates.
        R   s   <gallery>.*?</gallery>s   (?P<title>(%s|%s):.+?)(\|.+)?
t   codet   _defaultR*   s!   \w\w\w+\.(?:gif|png|jpg|jpeg|svg)R    N(    t   resultsR   R  R
  R   t	   ImagePageR   R*   t	   imagePageRc  R   t   followRedirectst   pageTextR/   R   t   DOTALLt   galleryRt   image_namespaceR?   t   galleryEntryRt   findallt   galleryR  R7   R9   t   looseR%   R>   t
   IGNORECASEt   imageRt	   imageNameR   (   R   R  R  R  R  R  R  R  R  R  R  R>   R
  R7   (    (    R   t
   imagelinks  s.      :   ,c         C   s+   g  } |  i   D] \ } } | | q ~ S(   s   
        Gives a list of template names used on a page, as a list of strings.
        Template parameters are ignored.
        N(   t   _[1]R   R   R   t   param(   R   R  R  R   (    (    R   R     s     c         C   s   y |  i   } Wn t t f j
 o g  Sn Xt |  } g  } t i d t i	  } x | i |  D] } | i d  } g  } | o | i d  } n | i d  } |  i   i |  o qg n t |  i   |  i   } | i | | f  qg W| S(   s   
        Gives a list of tuples. There is one tuple for each use of a template
        in the page, with the template name as the first entry and a list
        of parameters as the second entry.
        s1   {{(msg:)?(?P<name>[^{\|]+?)(\|(?P<params>.+?))?}}t   paramsR   RC   N(   R   R   R  R	   R   R  Ry  R/   R   R  t	   RtemplateR  R8   R9   t   paramStringR  Rf   RC   R   R   R   R*   Rc  (   R   R  R  R8   RC   R  Ry  R  (    (    R   R     s(     	 c         C   s@   g  } |  i   D]( } | t |  i   | |  i   d  q ~ S(   sz   
        Gives a list of Page objects containing the templates used on the page. Template parameters are ignored.
        i
   N(   R  R   R   R   R   R   (   R   R  R   (    (    R   t   templatePages  s     c         C   s}   y |  i   Wn\ t j
 o t |    nK t j
 o2 } d | j o t i d t  n | d Sn Xt |    d S(   s   
        If the page is a redirect page, gives the title of the page it
        redirects to. Otherwise it will raise an IsNotRedirectPage exception.

        This function can raise a NoPage exception.
        R   s)   %s has a | character, this makes no sensei    N(	   R   R   R   R	   R   t   warningst   warnt   WarningR
   (   R   R   (    (    R   R    s     c         C   s4   |  i d d  } | d d } |  i d |  d S(   Nt   revCounti   i   i    R   (   R   t   getVersionHistoryt   vhR   R   (   R   R  R   (    (    R   t   getPreviousVersion  s    i  c         C   s  |  i   } |  i   i   d j  o t i d  } n t i d  } d } t } t } t i d  } | o\ t |  d  p | o g  |  _ q#| o& t |  i  | j o t } t } q#t } nY t |  d  p | o g  |  _ n4 | o& t |  i  | j o t } t } n t } x:| p2| i i |  i   i   |  i   |  } | o2 t |  i  | j o | d 7} q| d 7} n | o | d	 | 7} n d
 } t oC | o t d |  i d t   qt d |  i d t   n | i |  } | }
 | o| ojt |  i  d j o | i! |
  } | o | i# d
  } n t } | i$ |
  }	 |	 i&   x |	 D] } |  i i( |  qWt |	  | j  o
 t } qq| p | i$ |
  }	 |	 i&   x |	 D] } |  i i( |  qWt |	  | j  o
 t } n | i! |
  } | o | i# d
  } qt } qt } | i! |
  } | o | i# d
  } qt } q[x' | i$ |
  D] } |  i i( |  qW|  i i&   t } q&| o]t |  i  d j o | i! |
  } | o | i# d
  } n t } | i$ |
  }	 x |	 D] } |  i i( |  q)Wt |	  | j  o
 t } q'q[| p | i$ |
  }	 x |	 D] } |  i i( |  qWt |	  | j  o
 t } n | i$ |
  } t |  d j o | d
 } q't } q[t } | i! |
  } | o | i# d
  } q[t } q&x' | i$ |
  D] } |  i i( |  q;Wt } q&W| o; t |  i  | j o | o |  i d | !Sn |  i Sn t |  i  | j o | o |  i d | !Sn |  i S(   s   
        Loads the version history page and returns a list of tuples, where each
        tuple represents one edit and is built of edit date/time, user name, and edit
        summary.  Defaults to getting the first revCount edits.
        i   s   <li>.*?<a href=".*?oldid=([0-9]*)" title=".*?">([^<]*)</a> <span class='user'><a href=".*?" title=".*?">([^<]*?)</a></span>.*?(?:<span class='comment'>(.*?)</span>)?</li>s   <li>.*?<a href=".*?oldid=([0-9]*)" title=".*?">([^<]*)</a> <span class='history-user'><a href=".*?" title=".*?">([^<]*?)</a>.*?</span>.*?(?:<span class=['"]comment['"]>(.*?)</span>)?</li>s   &amp;offset=(.*?)&amp;t   _versionhistoryearliestt   _versionhistorys	   &dir=prevs	   &go=firsts   &offset=i   u'   Continuing to get version history of %sRq   u   Getting version history of %si    i   N()   R   R   R  R/   R   t   editRR$   t   startFromPageR"   t   thisHistoryDonet   skipt   RLinkToNextPaget   reverseOrderRv   t   forceReloadR  t   getAllRN   R  R5   R  R?   t   version_history_addressRy   R`   R   R   R   RE   Rj   R   R   t   self_txtR   t   matchObjR9   R  t   editst   reverset   editRc  (   R   R  R  R  R  R  R   R  R   R  R  R   R  R   R  R  R  R  (    (    R   R    s     


 *
 
 


 
  


 c   
   	   C   s}   d } | d 7} x\ |  i d | d | d | d |  D]6 \ }	 } } } | d 7} | d |	 | | | f 7} q5 W| d	 7} | S(   s>   
        Returns the version history as a wiki table.
        s   {| border="1"
s1   ! oldid || date/time || username || edit summary
R  R  R  R  s   |----
s(   | %s || %s || %s || <nowiki>%s</nowiki>
s   |}
N(   Ry  R   R  R  R  R  R  R   R   R   t   summary(
   R   R  R  R  R  R   R  Ry  R   R   (    (    R   t   getVersionHistoryTable  s     
% 

i2   c         C   s  d } |  i   i   } h  d d <d d <d |  i   <d d <d	 t |  <d
 d <} | | j  o t |  | d	 <n | o | | d <n t
 d d  t i   }	 d } g  } x7| | j  o)| d j o|  i   i   t i i   j o d | d <t | d <|  i i |  }
 t i t i |  i i   d |  i i   | |
   } | i   i |  i   i    }
 n |  i   i | |  \ } }
 t
 i t i   |	  t  i! |
  }
 |
 d d i"   d } d | j o t$ d |   n | i% d f   } x| | D]t } | p. | i) | d | d | i% d d  f  q| i) | d | d | i% d d  | i% d d  f  qW| t* |  7} | | | j  o t | |  | d	 <n d |
 j o  t |
 d d d  | d <q Pq W| S(    s   
        Returns all previous versions. Gives a list of tuples consisting of
        edit date/time, user name and content
        i2   R7  t   queryt   propt	   revisionst   titlest   rvprops   timestamp|user|comment|contentt   rvlimitt   formatt   jsont   rvendt   requestsizei
   i    is!   application/x-www-form-urlencodeds   Content-types
   User-agents   ://t   pagest   missings   Page %s not foundt	   timestampt   userR    u    R2  s   query-continuet	   rvstartidN(+   t   RV_LIMITR   R   t   api_addressR[  R*   Ro   R^  t   maxt   sinceR   R   t   nowt   countRE   R   Rk   Rb  RA   Rd  Re  Rf  Rg  Rh  Ri  R   Rj  t   readt   decodeRM   Rk  t   setDelayt
   simplejsont   loadst   valuesR
  R   R   R  t   revisionR2  Rc  RN   (   R   R  R2  R  R  RE   R  R  R[  R  Rf  Rj  R  R^  R
  (    (    R   t   fullVersionHistory  sN     H   "

9% .= c         C   s;   |  i   } t   } x | D] } | i | d  q W| S(   sq   
        Returns a set of all user names (including anonymous IPs) of those who
        edited the page.
        i   N(   R   R  R  R   t   usersR  R  (   R   R  R  R  (    (    R   t   contributingUsers  s     	 c         C   s  | o t   n | d  j o
 d } n |  i   d d j o
 t } n |  i   i	   } |  i   i   } |  i   i d |  |  i   i |  d | } h  d |  i   i |  i   i    <d | i |  i   i    <d | i |  i   i    <} | o d | d	 <n d
 | d	 <| o | | d <n |  i   i	   t i i   j or d | d <t | d <|  i   i |  } t i t i |  i   i   d |  i   i	   | |   }	 d } n% |  i   i! | | d | \ }	 } | d j o |  i   i" d  | j o" t# d |  i   | f  t$ Sqt# d  y& | i% d  d }
 | i% d  } Wn t( j
 o t# |  n X| |
 | !} t# |  t Sn d  S(   Ns   Pagemove by boti   i   R   t
   wpOldTitlet
   wpNewTitlet   wpReasonRG  t
   wpMovetalkR   RO  s!   application/x-www-form-urlencodeds   Content-types
   User-agents   ://R   u    t   pagemovedsubu   Page %s moved to %su   Page move failed.s   <!-- start content -->i   s   <!-- end content -->()   R   Ra  Rr  R$   R   RQ   R"   t   movetalkpageR   R   RY  t   move_addressR[  R   R   R   RV  R*   R\   RM   t   newtitleR^  Rk   Rb  RA   Rd  Re  Rf  Rg  Rh  Ri  R   Rj  Rk  R   RE   R5   R  t   ibegint   iendRH   (   R   R  Rr  R  R   R   RY  R[  Rf  Rj  R  RV  R^  R  (    (    R   t   move  sH    

f
"

?
$

c         C   s  | o t   n | d
 j o t d  } n | i |  i   i    } d } | o5 t d |  i d t  d d g d d g d  } n | d d g j o-|  i   i   } |  i   i |  i    } y |  i   i d	 t  Wn) t j
 o } t t |   d
 Sn X|  i   i |  d	 t }
 h  d | <d | <d d <d d <} |
 o |
 | d <n |  i   i   t i i   j or d | d <t | d <|  i   i |  } t! i" t! i# |  i   i$   d |  i   i   | |   } d } n% |  i   i& | | d	 t \ } } | o |  i   i' d  | j o t d  t Sqt d  y& | i( d  d }	 | i( d  } Wn t+ j
 o t |  n X| |	 | !} t |  t, Sqn d
 S(   s   Deletes the page from the wiki. Requires administrator status. If
           reason is None, asks for a reason. If prompt is True, asks the user
           if he wants to delete the page.
        u'   Please enter a reason for the deletion:t   yu   Do you want to delete %s?Rq   t   Yest   Not   Nt   YR   NR  t	   wpCommentt	   wpConfirmRG  t
   wpConfirmBRO  s!   application/x-www-form-urlencodeds   Content-types
   User-agents   ://u    t   actioncompleteu   Deletion successful.u   Deletion failed:.s   <!-- start content -->i   s   <!-- end content -->(-   R   Ra  Rr  R$   t   inputR\   R   R   RM   t   answert   promptt   inputChoiceRj   R5   R   RY  t   delete_addressR`   R[  R   R   t   errorRE   Ro   R   RV  R^  Rk   Rb  RA   Rd  Re  Rf  Rg  Rh  Ri  R   Rj  Rk  R   R  R  R  RH   R"   (   R   Rr  R  R   R  RY  R[  Rf  Rj  R  RV  R^  R  R  (    (    R   t   delete  sR     5	*"

?
$


c         C   s   t  d |  i    |  i   i |  i    } |  i   i d t  |  i   i	 | d t } t i d t i  } h  |  _ xW | i |  D]F } | i d  | i d  | i d  d t g |  i | i d  <q Wt |  _ |  i i   S(	   s   Loads up Special/Undelete for the page and stores all revisions'
           timestamps, dates, editors and comments.
           Returns list of timestamps (which are used to refer to revisions later on).
        u/   Loading list of deleted revisions for [[%s]]...R   s   <input name="(?P<ts>(?:ts|fileid)\d+)".*?title=".*?">(?P<date>.*?)</a>.*?title=".*?">(?P<editor>.*?)</a>.*?<span class="comment">\((?P<comment>.*?)\)</span>Rw   t   editorR2  t   tsN(   RE   R   R*   R   t   undelete_view_addressR`   R[  R   R5   R   R   R/   R   R  t   rxRevsRX   R  t   revR9   R$   R"   t   _deletedRevsModifiedRA   (   R   R  R   R  R[  (    (    R   t   loadDeletedRevisionsP  s     	 D	c         C   s	  |  i d j o |  i   n |  i i |  p d Sn | o |  i | d o | d  d j o t d  |  i   i	 |  i
   |  } |  i   i d t  |  i   i | d t } t i d | t i  } | o | i d  |  i | d <q n |  i | S(	   s   Returns a deleted revision [date, editor, comment, text, restoration marker].
           text will be None, unless retrieveText is True (or has been retrieved earlier).
        i   i   R  u&   Retrieving text of deleted revision...R   sS   <textarea readonly="1" cols="80" rows="25">(.*?)</textarea><div><form method="post"i   N(   R   RX   R$   R  t   has_keyR  t   retrieveTextRE   R   R   R`   R[  R   R5   R   R   R/   R   R  t   undR9   (   R   R  R  R  R   R[  (    (    R   t   getDeletedRevisionk  s     +
"c         C   sW   |  i d j o |  i   n |  i i |  p d Sn | |  i | d <t |  _ d S(   s   Marks revision (identified by timestamp) for undeletion (default)
           or to remain as deleted (if undelete=False).
        i   N(	   R   RX   R$   R  R  R  t   undeleteR5   R  (   R   R  R	  (    (    R   t   markDeletedRevision  s     R   c         C   s  | o t   n t d  |  i   i   } |  i   i d t  |  i   i	 |  d t } h  d |  i   <d | <d | <d |  i   i d  <} |  i d j oL |  i oB x? |  i i   D]* } |  i | d o d	 | d
 | <q q Wn d |  _ |  i   i | | d t S(   su  Undeletes page based on the undeletion markers set by previous calls.
           If no calls have been made since loadDeletedRevisions(), everything will be restored.

           Simplest case:
              wikipedia.Page(...).undelete('This will restore all revisions')

           More complex:
              pg = wikipedia.Page(...)
              revs = pg.loadDeletedRevsions()
              for rev in revs:
                  if ... #decide whether to undelete a revision
                      pg.markDeletedRevision(rev) #mark for undeletion
              pg.undelete('This will restore only selected revisions.')
        u   Undeleting...R   t   targetR  RO  t   restoret   undeletebtni   RG  R  N(   R   Ra  RE   R   R   t   undelete_addressR[  R   R5   R   RV  R*   R2  R   t   formdataRX   R$   R  RA   R  Rk  (   R   R2  R   R  RV  R[  R  (    (    R   R	    s     
? 	R   c         C   sx  |  i   i |  i    }	 | o |  i   i |  i    }	 n | o t   n | d j o t d  } n | i |  i   i    } d } | o5 t d |  i d t  d d g d d g d  } n | d d g j o|  i   i   } |  i   i d	 t  |  i   i |  d	 t } | d
 j o
 d } n | d
 j o
 d } n h  d | <d | <d | <} | o | | d <n |  i   i   t i i   j or d | d <t | d <|  i   i |  }
 t! i" t! i# |  i   i$   d |  i   i   |	 |
   } d }
 n% |  i   i& |	 | d	 t \ }
 } | p t' d  t Sqtt' d  t' |
  t( Sn d S(   s<  (Un)protects a wiki page. Requires administrator status. If reason is None,
           asks for a reason. If prompt is True, asks the user if he wants to protect the page.
           Valid values for edit and move are:
           * '' (equivalent to 'none')
           * 'autoconfirmed'
           * 'sysop'
        u-   Please enter a reason for the (un)protection:R  u   Do you want to (un)protect %s?Rq   R  R  R  R  R   t   noneR   s   mwProtect-level-edits   mwProtect-level-moves   mwProtect-reasonRO  s!   application/x-www-form-urlencodeds   Content-types
   User-agents   ://u   (Un)protection successful.u   Protection failed:N()   R   R   t   protect_addressR`   R[  t	   unprotectt   unprotect_addressR   Ra  Rr  R$   R  R\   RM   R  R  R  Rj   R5   R   RY  R   R   RV  R  R  R^  Rk   Rb  RA   Rd  Re  Rf  Rg  Rh  Ri  R   Rj  Rk  RE   R"   (   R   R  R  R  Rr  R  R   R  RY  R[  Rf  Rj  RV  R^  (    (    R   t   protect  sH     5 
 
!"

?
$


c         C   s   |  i | d  | | |  S(   N(   R   t   replaceImaget   imageR$   R0  R  t   safe(   R   R  R0  R  R  (    (    R   t   removeImage  s    c      	      s  |  i   }	 |  i   } | }
 d   } d   } d |	 i d d t |	 i d d t } d d	 i
 t | |   } d
 | |  i d d  } d   d   d } t i d | | | f  } xR t oJ | i |
  } | p Pn |
 | i     | d  |
 | i   }
 q Wd | d  | d  f } d | | f    d   } t i | | |
  }
 | |
 j p | o> d } d | | f    d   } t i | | |
  }
 n | o- | |
 j o |  i! |
 |  t Sn t# Sn |
 Sd S(   s  Replace all occurences of an image by another image.
        Giving None as argument for replacement will delink
        instead of replace.

        The argument image must be without namespace and all
        spaces replaced by underscores.

        If put is false, the new text will be returned.

        If put is true, the edits will be saved to the wiki
        and True will be returned on succes, and otherwise
        False. Edit errors propagate.c         C   s8   t  i |   }  d |  d i   |  d i   |  d f S(   Nu   (?:[%s%s]%s)i    i   (   R/   R   t   sRP   R;   (   R  (    (    R   t   create_regex  s    c         C   sB   d d i  g  } |  D]# } | d | i   | i   f q ~  S(   Nu   (?:%s)u    u   [%s%s](   t   joinR  R  t   cRP   R;   (   R  R  R  (    (    R   t   create_regex_i  s    t   Imaget   Mediai   R   iu   \s*(?:%s)\s*\:\s*u   |u   (%s)s   \_s   [ _]i   c            sB     d  j o d Sn* t |  i    }   | | <d i |  Sd  S(   Nu    (   t   replacementR$   R&  R7   t   groupst   groupNumberR  (   R7   R"  R!  (   R   (    R   t   simple_replacer  s
    
s!   (?:\|(?:(?!\[\[).|\[\[.*?\]\])*?)u/   (\[\[)(?P<namespace>%s)%s(?P<params>%s*?)(\]\])i   u   (?s)(\<%s\>)(?s)(.*?)(\<\/%s\>)R  u%   (?m)^((?:%s)?)(%s)(\s*(?:\|.*?)?\s*)$c            s;   d |  i d  t i    |  i d   |  i d  f S(   Nu   %s%s%si   i   i   (   R7   R9   R/   R0   t	   r_galleryR#  (   R7   (   R$  R#  (    R   t   gallery_replacer%  s    u   (?s)(\{\{.*?\}\})u   (?s)((?:%s)?)%sc            s   t  i    |  i d   S(   Ni   (   R/   R0   t   r_complicatedR#  R7   R9   (   R7   (   R#  R&  (    R   t   template_replacer0  s    N(   R  R  ($   R   R   R   R   t   new_textR  R  RQ   R5   t
   namespacesR  t   mapt   r_namespaceR  Rc   t   r_imageR#  t   r_paramR/   R   t   rImageR   R8   R   R   t   r_galleriesR$  R%  R0   R  t   r_templatesR&  R'  R0  R  R"   (   R   R  R   R0  R  R  R$  R0  R   R   R(  R  R/  R-  R#  R&  R+  R)  R'  R,  R%  R8   R  R.  (    (   R   R#  R$  R&  R   R    sB     		, 0(D   R   R   R   R$   R   R   RM   R`   R"   R*   Rg   Rh   Re   Rm   Rp   Rj   Rt   Rs   R5   R   R   R   R   R   R   R   R   R   R   R   R   RQ   R   R   R   R  R  R)  R6  R0  RD  Rv  Rw  R  R  R  R  R  R  R   R   R  R  R  R  R  R  t   fullRevisionHistoryR  R  R  R  R  R
  R	  R  R  R  (    (    (    R   R      s~    								K								2							<-	IF						#					8	0:	'7R  c           B   sV   t  Z d  d  d  Z d   Z d   Z d   Z d   Z d   Z d   Z	 d   Z
 RS(	   Nc         C   s#   t  i |  | | |  d  |  _ d  S(   N(   R   R   R   R   R*   R(   R$   t   _imagePageHtml(   R   R   R*   R(   (    (    R   R   ?  s    c         C   sH   |  i p7 |  i   i |  i    } |  i   i |  |  _ n |  i S(   s   
        Downloads the image page, and returns the HTML, as a unicode string.

        Caches the HTML code, so that if you run this method twice on the
        same ImagePage object, the page only will be downloaded once.
        N(   R   R2  R   R   R`   R   R   (   R   R   (    (    R   t   getImagePageHtmlC  s
     
c         C   s   t  i d t  i  } | i |  i    } y# | i d  p | i d  } Wn/ t
 j
 o# t d |  i d t    n X| S(   Ns   <div class="fullImageLink" id="file">.*?<a href="(?P<url>[^ ]+?)"(?! class="image")|<span class="dangerousLink"><a href="(?P<url2>.+?)"R   t   url2u    Image file URL for %s not found.Rq   (   R/   R   R  t   urlRR   R   R3  R8   R9   R   R   R   Rj   R5   (   R   R   R8   R5  (    (    R   t   fileUrlO  s    	#!c         C   s   |  i   i d  S(   Nu.   http://upload.wikimedia.org/wikipedia/commons/(   R   R6  R2   (   R   (    (    R   t   fileIsOnCommons`  s    c         C   s=   t    } | i |  i    } t i | i    i	   } | S(   N(   t   MyURLopenert   uot   openR   R6  t   ft   md5t   newR  t	   hexdigestt   md5Checksum(   R   R;  R9  R?  (    (    R   t   getFileMd5Sumc  s    	c   
      C   s   g  } t i d |  i    }	 |	 o t i d  } x | i |	 i	    D]t } | i	 d  } | i	 d  } | i	 d  } | i	 d  } | i	 d  p d } | i | | | | | f  qJ Wn | S(	   Ns*   (?s)<table class="filehistory">.+?</table>s   <tr><td>.*?</td><td><a href=".+?">(?P<datetime>.+?)</a></td><td><a href=".+?"(?: class="new"|) title=".+?">(?P<username>.+?)</a>.*?</td><td>(?P<resolution>.*?)</td><td class=".+?">(?P<filesize>.+?)</td><td>(?P<comment>.*?)</td></tr>t   datetimeR   t
   resolutiont   filesizeR2  R   (   Ry  R/   R   R   R3  t   historyR   t   lineRR  R9   R7   RA  R   RB  t   sizeR2  Rc  (
   R   R   R2  RE  RA  Ry  RF  RB  R7   RD  (    (    R   t   getFileVersionHistoryi  s     $c         C   sa   g  } xC |  i   D]5 \ } } } } } | i d | | | | | f  q Wd d i	 |  d S(   Ns-   | %s || %s || %s || %s || <nowiki>%s</nowiki>uR   {| border="1"
! date/time || username || resolution || size || edit summary
|----
u   
|----
s   
|}(
   t   linesR   RG  RA  R   RB  RF  R2  Rc  R  (   R   R   R2  RH  RA  RB  RF  (    (    R   t   getFileVersionHistoryTabley  s
     $c         C   sv   g  } t i d |  i    i   } t i d  } x< | i	 |  D]+ } | i t |  i   | i d    qC W| S(   Ns   (?s)<h2 id="filelinks">.+?</ul>s5   <li><a href=".+?" title=".+?">(?P<title>.+?)</a></li>R*   (   Ry  R/   R   R   R3  R9   t	   titleListR   RE  R  R7   Rc  R   R   (   R   RE  Ry  R7   RJ  (    (    R   t
   usingPages  s     )(   R   R   R$   R   R3  R6  R7  R@  RG  RI  RK  (    (    (    R   R  =  s   						t   GetAllc           B   s5   t  Z d   Z d   Z d   Z d   Z d   Z RS(   Nc         C   s   | |  _  g  |  _ | |  _ xj | D]b } t | d  o t | d  p | o |  i i |  q" t o t	 d | i
    q" q" Wd  S(   NR   R   u   BUGWARNING: %s already done!(   R   R   R  R   t   plRv   R   Rc  R   RE   Rj   (   R   R   R  R   R   RM  (    (    R   R     s    			 )c         C   ss  d } |  i o_x>t o6y |  i   } Wn t i t i	 t
 f j
 oz t d i t i t i       t d |  t i |  | d j o | d 7} qL| d j  o | d 7} qLq X| i d  d j o d  Sq | i d  d j oU t d	 |  t i |  | d j o | d 7} qL| d j  o | d 7} qLq Pq Wt i d
 t i  } | i |  } | o | i d  } n t i   } | i |  i  | i  |  i!  y t" i# i$ | |  WnS t" i# i% i& t' f j
 o" } t) d |  i* | |    n t+ j
 o d  Sn XxD |  i D]5 } t- | d  o t- | d  o t. | _/ q2q2Wn d  S(   Ni   u    u@   DBG> got network error in GetAll.run. Sleeping for %d seconds...i<   ih  s"   <title>Wiki does not exist</title>is
   <siteinfo>u5   Got incorrect export page. Sleeping for %d seconds...s   \s*<\?xml([^>]*)\?>(.*)i   t   SaxParseBugR   R   (0   t   dtR   R  R5   t   getDataRf  t   socketR  Rl  Rm  R   RE   R  t	   tracebackt   format_exceptionRY   t   exc_infoR   R   RI   R/   R   R  R   R7   R8   R9   t	   xmlreadert   MediaWikiXmlHandlert   handlert   setCallbackt   oneDonet   setHeaderCallbackt
   headerDonet   xmlt   saxt   parseStringt   _exceptionst   SAXParseExceptionRH   t   errt	   debugDumpR   R   RM  Rv   R   R   (   R   RW  RM  R   RO  Rf  Ra  R8   (    (    R   t   run  sT    
 "	
 "c      	   C   s  | i } | i } | i }	 | i }
 | i } | i } | i } t |  i
 |  } x |  i D]L } | i   | i   j o- t | d  p t | d  o d  Sn Pq[ q[ Wt d | | i d t  f  t d d i g  } |  i D] } | | i d t  q ~   t  | i | _ | i | _ | d j o t | _ n | i | _ | | _ |	 | _ |
 | _ | i   } |  i
 i   i |  } | oT | i  d  } | o( | i" d	  d
 j o | d	 | } n t# | _$ | | _% n t& t' |
  d  | _( | o t) i* d t) i+ |  t, | | i
   i-     } | pH y% | i$ t d | i d t   Wqt. j
 o t/ | _$ qXqn | | _0 d  S(   NR   R   u%   BUG>> title %s (%s) not found in listRq   u   Expected one of: %su   ,t   autoconfirmedi   Rz   isD   \.3D\_*(\.27\.27+)?(\.5B\.5B)?\_*%s\_*(\.5B\.5B)?(\.27\.27+)?\_*\.3Du   WARNING: Section not found: %s(1   t   entryR*   R   t   ipeditR  R   RS   t   moveRestrictionR   R   R   R
  R  t   page2Re   Rv   RE   Rj   R5   R  R  R   R#   t
   revisionidRT   RU   RV   RW   Rh   R   R7   R8   R9   t
   redirecttoRI   R	   R   R   Ro   R   R   R/   R   R   RL   RM   R   R   R   (   R   Re  Rj  R   Rh  RS   R*   Rg  R   Rf  R  R8   R
  R  Rh   (    (    R   RY    sV    							
  	 A				4c   	      C   sK  |  i i } | i i   } | i   x| D]} | i | } |  i i
 i |  o |  i i |  } | d  j o
 d } n | | j o |  i i
 i d |  } | | j o d | | f } n2 | | j o d | | f } n d | | f } t d |  i i
 i | | | f  qCq, t d |  i i
 i | | | f  q, Wd  S(   Nu    R  u,   is set to default ('%s'), but should be '%s'u3   is '%s', but should be removed (default value '%s')u   is '%s', but should be '%s'u8   WARNING: Outdated family file %s: namespace['%s'][%i] %suU   WARNING: Missing namespace in family file %s: namespace['%s'][%i] (it is set to '%s')(   R   R   RB   t   headerR)  RA   t   idsR'  R   t   nshdrR?   t   isDefinedNSRQ   R>   R$   t   dfltt   flagRE   RC   (	   R   Rk  RB   Ro  Rl  Rm  Rp  R>   R   (    (    R   R[    s&    
 
+c   
      C   s  |  i i   } g  } |  i D] }	 | |	 i   q ~ } |  i i	 d j o+ g  } | D] } | t |  qW ~ } n d i |  } t |  t d  j o t d  | GHn | i |  i i    } h  d d <d | <d d	 <} t d
 t |  i   t i   } |  i i   t i i   j oo d | d <t | d <|  i i |  } t i t i |  i i    d |  i i   | |   } | i"   } n |  i i# | |  \ } } | i |  i i    } t i$ t i   |  | S(   NR   u   
u    u`   Warning: xmlreader.WikipediaXMLHandler.getData() got non-unicode page names. Please report this.R7  t   submitR  t   curonlyR5   R  s!   application/x-www-form-urlencodeds   Content-types
   User-agents   ://(%   R   R   t   export_addressR[  R  R  R
  Re   t	   pagenamesRB   t	   pagetitleRC  R  R&   RE   R\   RM   R^  R   RN   R   R  R   Rk   Rb  RA   Rd  Re  Rf  Rg  Rh  Ri  R   Rj  R  Rk  R  (
   R   Ru  Rf  R  R^  Rt  R[  Rj  R  R
  (    (    R   RP  	  s,    *+
	!

9(   R   R   R   Rc  RY  R[  RP  (    (    (    R   RL    s
   	
	5	5	c         C   s3   t  d t |  |  f  t |  | | |  i   S(   s   Use Special:Export to bulk-retrieve a group of pages from site
       Arguments: site = Site object
                  pages = iterable that yields Page objects
    u   Getting %d pages from %s...N(   RE   RN   R  R   RL  R   R   Rc  (   R   R  R   R   (    (    R   R   8	  s     c         C   ss   d |  j o |  Sn |  i d d  }  |  i d d  }  |  i d d  }  |  i d d	  }  |  i d
 d  }  |  S(   s:   Replace escaped HTML-special characters by their originalsR   s   &lt;R{   s   &gt;R|   s   &apos;t   's   &quot;t   "s   &amp;N(   R  Rc   (   R  (    (    R   R   C	  s     c         C   s
   |  a d S(   s1   Set a summary to use for changed page submissionsN(   R  R7  (   R  (    (    R   t	   setActionN	  s      s   Wikipedia python libraryc         C   s
   |  a d S(   s2   Set a User-agent: header passed to the HTTP serverN(   R  Rd  (   R  (    (    R   t   setUserAgentV	  s      s   PythonWikipediaBot/1.0t   Throttlec           B   sk   t  Z e i e i e d  Z d   Z d   Z e i e	 d  Z
 d   Z d   Z d   Z d d	  Z RS(
   Nc         C   s   t  i   |  _ | |  _ | |  _ t |  _ d |  _ d |  _	 d |  _
 d |  _ d |  _ d |  _ d |  _ | o |  i   n |  i |  d S(   sj   Make sure there are at least 'delay' seconds between page-gets
           after 'ignore' initial page-getsi    f1.0i   ih  i f0.0N(   t	   threadingt   RLockR   t   lockt   mindelayt   maxdelayR"   t   pidR  t   next_multiplicityt
   checkdelayt	   dropdelayt
   releasepidt   lastwaitR   t   multiplydelayt   checkMultiplicityR  (   R   R~  R  R  (    (    R   R   `	  s     										c         C   s   d  k  } | i d  S(   Ns   throttle.log(   t   wikipediatoolst   _wtt   absoluteFilename(   R   R  (    (    R   t   logfnr	  s    	c   
      C   s  |  i i   zh  } d }	 d } y t |  i   d  } Wn$ t	 j
 o |  i
 p qP  n Xt i   } x | i   D] } y | i d  } t | d  } t | d i d  d  } | | |  i j o[ | | |  i j o | |  i
 j o | d 7} n | | | <| |	 j o | d }	 q/n Wq{ t t f j
 o q{ Xq{ W|  i
 p |	 |  _
 n t i   |  _ |  i | |  i
 <t |  i   d  } x= | i   D]/ } | i t |  d t | |  d  qW| i   | |  _ t d |  Wd  |  i i   Xd  S(	   Ni   t   rR   i    t   .t   ws   
u]   Checked for running processes. %s processes currently running, including the current process.(   R   R}  R,  t	   processest   my_pidR  R:  R  R;  t   IOErrorR  R   R  t	   readlinesR$  Rf   R   t   ptimeR  R  R   RH   t	   checktimeRA   R:   t   writeRo   t   closet   process_multiplicityRE   R/  (
   R   R  R  R  R;  R  R:   R$  R  R  (    (    R   R  v	  sN    
 $
	
 -
	 c         C   s[   |  i i   z9 | o | |  _ | |  _ n | |  _ t i   |  _ Wd  |  i i	   Xd  S(   N(
   R   R}  R,  t   absoluteR   R  R~  R   R  R/  (   R   R   R  (    (    R   R  	  s    		 c         C   s   |  i } |  i o t i   |  i |  i j o |  i   n | |  i |  i	 j  o |  i |  i	 } n | |  i
 j o |  i
 } n | |  i 9} n | S(   N(   R   R   t	   thisdelayR  R   R  R  R  R~  R  R  R  (   R   R  (    (    R   t   getDelay	  s    	
c         C   sL   |  i   } t i   } | |  i } | | j  o | | } | Sn d Sd S(   s`   Calculate the time in seconds we will have to wait if a query
           would be made right nowf0.0N(   R   R  R  R   R  t   agot   delta(   R   R  R  R  R  (    (    R   t   waittime	  s     
c         C   s6  d |  _ h  } y t |  i   d  } Wn t j
 o d Sn Xt i   } x | i	   D]t } | i d  } t | d  } t | d i d  d  } | | |  i j o | |  i j o | | | <q[ q[ Wt |  i   d  } x= | i   D]/ } | i t |  d t | |  d  q W| i   d S(	   s2   Remove me from the list of running bots processes.i    R  NR   i   R  R  s   
(   R   R  R  R:  R  R;  R  R   R  R  R$  Rf   R   R  R  R  RA   R:   R  Ro   R  (   R   R  R  R;  R  R:   R$  R  (    (    R   t   drop	  s(     		 $ -i   c         C   s   |  i i   z |  i   } t i d |  t i d  |  _ | t i	 j o* t
 d | t i d t i    f  n t i |  t i   |  _ Wd |  i i   Xd S(   s   This is called from getEditPage without arguments. It will make sure
           that if there are no 'ignores' left, there are at least delay seconds
           since the last time it was called before it returns.i   f2.0u   Sleeping for %.1f seconds, %ss   %Y-%m-%d %H:%M:%SN(   R   R}  R,  R  t   matht   logR  R  Rk   t
   noisysleepRE   R   t   strftimet	   localtimeR   R  R/  (   R   R  R  (    (    R   t   __call__	  s     #* (   R   R   Rk   t   minthrottlet   maxthrottleR5   R   R  R  R"   R  R  R  R  R  (    (    (    R   Rz  _	  s   		*			c         C   s   h  d t  i d  <d t  i d  <d t  i d  <d t  i d  <d	 t  i d
  <d t  i d  <d t  i d  <d t  i d  <d t  i d  <} t |  t d  j p t |  t d  j o: | o  t  i | t  i t  i B } qt  i |  } n g  } | D] } | | | q~ } d } t |   }	 xt o| i |  |  }
 |
 p Pn d } xW | D]O } | i |  |  } | o0 | d j p | i   | i   j  o
 | } qqW| d j	 o) | i   |
 i   j o | i   } qN| } t  i d  } xw t oo | i |  } | p Pn | i d  p t | i d   } | | i    |
 i |  | | i   } q!W|  |
 i    | |  |
 i   }  | o |
 i   d } n |
 i   t |  } |
 i   t |  }	 qNW|  |	  | |  |	 }  |  S(   s  
    Replaces old by new in text, skipping occurences of old e.g. within nowiki
    tags or HTML comments.
    If caseInsensitive is true, then use case insensitivity in the regex
    matching. If allowoverlap is true, overlapping occurences are all replaced
    (watch out when using this, it might lead to infinite loops!).

    Parameters:
        text            - a string
        old             - a compiled regular expression
        new             - a string
        exceptList      - a list of strings which signal what to leave out,
                          e.g. ['math', 'table', 'template']
        caseInsensitive - a boolean
        marker          - a string, it will be added to the last replacement,
                          if nothing is changed, it is added at the end
    R2  s   (?s)<!--.*?-->t   includeonlys#   (?is)<includeonly>.*?</includeonly>R  s   (?is)<math>.*?</math>t	   noincludes   (?is)<noinclude>.*?</noinclude>t   nowikis   (?is)<nowiki>.*?</nowiki>t   pres   (?is)<pre>.*?</pre>t
   startspaces   (?m)^ (.*?)$t   tables$   (?ims)^{\|.*?^\|}|<table>.*?</table>R   s   (?s){{.*?}}R   u    i    s$   \\(?P<number>\d+)|\\g<(?P<name>.+?)>RC   t   numberi   N("   R/   R   t   exceptionRegexesR&   R9  t   caseInsensitiveR  t   UNICODER  t
   exceptionsRC   t   dontTouchRegexesR  RN   R   t	   markerposR5   R   R7   R$   t   nextExceptionMatcht
   dontTouchRt   excMatchR   R   R=  R   t   groupRt
   groupMatchR9   R   t   groupIDt   allowoverlapt   marker(   R   R9  R=  R  R  R  R  R  R  R  R7   R  R  R  RC   R  R  R  R  R  R   (    (    R   t   replaceExcept	  sL     2 %  -& %0"R    c         C   s   h  d d <d d <d d <d d <} d	 | j o | i   } n t i d
 i g  } | D] } | | | q^ ~  t i t i	 B } | i d |   S(   s  
    Removes those parts of a wiki text where wiki markup is disabled, i.e.
    * HTML comments
    * nowiki tags
    * pre tags
    * includeonly tags

    The exact set of parts which should be removed can be passed as the
    'parts' parameter, which defaults to all.
    t   commentss
   <!--.*?-->R  s   <includeonly>.*?</includeonly>R  s   <nowiki>.*?</nowiki>R  s   <pre>.*?</pre>R    R   R   N(   t   regexest   partsRA   R/   R   R  R  R:   R  R  t	   toRemoveRR0   R   (   R   R  R  R:   R  R  (    (    R   R  U
  s    
 *Ds   [[]]c         C   s  | d j o t   } n h  } t |   }  t i d  } x | i	 |   D] \ } } | i   } | | i i j o | i i | } n | | i   j ou d | j o | | i d   } n | p t d | | | f  q| i d |  } t | | d | | | <qK qK W| S(   s   
    Returns a dictionary with language codes as keys and Page objects as values
    for each interwiki link found in the text. Do not call this routine
    directly, use Page objects insteads%   \[\[([a-zA-Z\-]+)\s?:([^\[\]\n]*)\]\]R   u-   ERROR: %s - ignoring impossible link to %s:%sR  R(   N(   R(   R$   R%   Ry  R  R   R/   R   t
   interwikiRR  RB   Ru  R;   R?   t   obsoletet   validLanguageLinksR  RE   Rx  R   R   (   R   R(   Rx  RB   R  R   Ru  Ry  (    (    R   Rz  m
  s&      !c         C   s   | d	 j o t   } n | i   p |  Sn d i | i    } t i d | t i	  } t |  | d d d d d g d | }  t |   S(
   sI  Given the wiki-text of a page, return that page with all interwiki
       links removed. If a link to an unknown language is encountered,
       a warning is printed. If a marker is defined, the marker is placed
       at the location of the last occurence of an interwiki link (at the end
       if there are no interwikilinks).R   s   \[\[(%s)\s?:[^\]]*\]\][\s]*R   R  R2  R  R  R  N(   R   R$   R%   R  R   R  t	   languageRR/   R   R  R  R  R  t   normalWhitespace(   R   R   R  R  R  (    (    R   R   
  s     'c   	      C   s  d } x | |  j o | d 7} q	 W| d j o t   } n t | d | } t |  d | d | } | o6| i
   | i i j o* | | i i | i | d  i   } q| i |  t |  } d | | j o | |  | | | } n | i
   | i i j oZ t | d | } t | i | d  i   |  | i i | } t | | d | } n' | i | d  i   | i i | } | i | d  } n | i | d  } | S(	   s   Replace the interwiki language links given in the wikitext given
       in oldtext by the new links given in new.

       'new' should be a dictionary with the language names as keys, and
       Page objects as values.
    s   @@t   @R(   R   R  R   s   </noinclude>N(   R  t   oldtextR   R$   R%   t   interwikiFormatR=  R  R   t   s2Ry   R?   t   interwiki_attopt   interwiki_text_separatorRc   R1   R1  RI   RN   t
   firstaftert   categories_lastR  t   catsR   t   replaceCategoryLinks(	   R  R=  R   R  R1  R  R  R  R  (    (    R   t   replaceLanguageLinks
  s.      */&c   
      C   s  | d j o t   } n |  p d Sn g  } |  i   } | i   | i   } | o g  } xh | D]` } | t   i   j oD | i d |  }	 |	 | j o! | | i |	  =| |	 g } q qe qe W| | } n | i |  o | i |  | } n xk | D]c }	 y' |  |	 i d t  } | i |  Wqt j
 o' | i |	 i |  |	 d |  qXqW| i | i i j o
 d } n d } | i |  d } | S(   s   Create a suitable string encoding all interwiki links for a wikipedia
       page.

       'links' should be a dictionary with the language codes as keys, and
       Page objects as values.

       The string is formatted for inclusion in insite (defaulting to your
       own site).
    R   R  Rq   t	   othersiteR   s   
N(   R(   R$   R%   t   linksR  RA   t   arR'  t   interwiki_putfirstt   putfirstt   ar2R  R  R   R  t   interwiki_putfirst_doubledRj   R5   R  Rc  R   t   linktoRB   R?   t   interwiki_on_one_linet   sepR  (
   R  R(   R  R  R  R  R  R  R  R   (    (    R   R  
  sB    	 

  )
c         C   s   xP |  o |  i d  o |  d }  q |  o |  i d  o |  d }  q Pq Wx, |  o |  d d j o |  d  }  qV PqV W|  S(   Ni   s   
i   R   is   
 	(   R   R2   (   R   (    (    R   R  
  s        c         C   s   d  k  } g  } t |   }  d i | i    } t i	 d |  } xa | i |   D]P } | i | d | i d  | i d  f d | i d  } | i |  qS W| S(   NR   sM   \[\[\s*(?P<namespace>%s)\s*:\s*(?P<catName>.+?)(?:\|(?P<sortKey>.+?))?\s*\]\]s   %s:%sRQ   t   catNamet   sortKey(   t   catlibRy  R  R   R  R   t   category_namespacest   catNamespaceR/   R   R   R  R7   t   CategoryR9   t   catRc  (   R   R   R  R   Ry  R  R7   R  (    (    R   R    s    	  =c         C   sY   d i  | i    } t i d |  } t |  | d d d d d g d | }  t
 |   S(
   s   Given the wiki-text of a page, return that page with all category
       links removed. Puts the marker after the last replacement (at the
       end of the text if there is no replacement)R   s   \[\[\s*(%s)\s*:.*?\]\][\s]*R   R  R2  R  R  R  N(   R  R   R  R  R/   R   t	   categoryRR  R   R  R  (   R   R   R  R  R  (    (    R   R     s
     'c         C   s7  | d j o t   } n d i | i    } t i d | | i	   f  } | d j o% t |  | d d d d d g  } n, t |  | d | i	   d d d d g  } t i d | | i	   i d	 d
  f  } | d j o% t | | d d d d d g  } n, t | | d | i	   d d d d g  } | S(   sl   Replaces the category oldcat with the category newcat and then returns
       the modified Wiki source.
    R   s   \[\[\s*(%s)\s*:%s\]\]R   R  R2  R  R  s   [[Category:%s]]R   Ra   N(   R   R$   R%   R  R  R  R/   R   t   oldcatRg   R  t   newcatR  R  R   Rc   (   R  R  R  R   R  R   R  (    (    R   t   replaceCategoryInPlace*  s     %++%+c   	      C   s  d } x | |  j o | d 7} q	 W| d
 j o t   } n | i   d j o t d   n t | d | } t
 |  d | d | } | o| i   | i i j o | | i i | } n | i |  } d | | j o | |  | | | } n | i   | i i j o* | i | d	  i   | i i | } nN t |  } t | i | d	  i   |  | i i | } t | | |  } | i | d	  } n | i | d	  } | S| S(   s   Replace the category links given in the wikitext given
       in oldtext by the new links given in new.

       'new' should be a list of Category objects.
    s   @@R  s   wikipedia:des   The PyWikipediaBot is no longer allowed to touch categories on the German Wikipedia. See http://de.wikipedia.org/wiki/Hilfe_Diskussion:Personendaten/Archiv2#Position_der_Personendaten_am_.22Artikelende.22R(   R   R  s   </noinclude>R   N(   R  R  R   R$   R%   t   sitenameR   t   categoryFormatR=  R  R   R  Ry   R?   t   category_attopt   category_text_separatorR1  RI   R  R  Rc   R1   Rz  R  R   R  (	   R  R=  R   R  R  R1  R  R  R  (    (    R   R  @  s4      */c         C   s~   |  p d Sn | d j o t   } n g  } |  D] } | | i   q4 ~ } | i   o
 d } n d } | i
 |  d S(   s   Create a suitable string with all category links for a wiki
       page.

       'categories' should be a list of Category objects.

       The string is formatted for inclusion in insite.
    R   R   s   
N(   R  R(   R$   R%   R  t   categoryRj   t   catLinkst   category_on_one_lineR  R  (   R  R(   R  R  R  R  (    (    R   R  i  s     '
c         C   s7   |  i d d  }  t |  d | } t | | i    S(   s   Convert a url-name of a page into a proper name for an interwiki link
       the argument 'insite' specifies the target wiki
       Ra   R   R   N(   t   percentnameRc   R,   R   R   t   unicode2htmlR(   RM   (   R  R(   R   R   (    (    R   t   url2link  s     c      	   C   s  h  d d <d d <d d <d d <d	 d
 <d d <d d <d d <d d <d d <d d <d d <} xq| i   D]c\ } }
 t i | d  }	 d } d } x5t	 o-|	 i
 |  |  } | o | i   } t |  d d j oM |
 d i g  } t d t |  d  D] } | | d | q~  } nN | d i g  } t d t |  d  D] } | | d | d qe~  } | |  | | i   | !| 7} | | i   t |  7} q | |  | 7} | }  Pq Wq W|  S(   s  
    Resolves the x convention used to encode Esperanto special characters,
    e.g. Cxefpagxo and CXefpagXo will both be converted to Ĉefpaĝo.
    Note that to encode non-Esperanto words like Bordeaux, one uses a
    double x, i.e. Bordeauxx or BordeauxX.
    u   cu   ĉu   Cu   Ĉu   gu   ĝu   Gu   Ĝu   hu   ĥu   Hu   Ĥu   ju   ĵu   Ju   Ĵu   su   ŝu   Su   Ŝu   uu   ŭu   Uu   Ŭs   [xX]+i    R   i   i   N(   t   charsR|  t   latint	   esperantoR/   R   t   xConvRt   posRy  R5   R   R   R7   R9   R9  RN   R  R  t   ranget   iR=  R   (   R   R  R9  R  R  R  R  Ry  R=  R  R  R7   (    (    R   R     s*     r  MM
c   	      C   s   t  i d  } d } d } x t o | i |  |  } | o | i	   } | d d i g  } t d t |   D] } | | | d qr ~  } | |  | | i   | !| 7} | | i   t |  7} q | |  | 7} | }  Pq W|  S(   s   
    Doubles X-es where necessary so that we can submit a page to an Esperanto
    wiki. Again, we have to keep stupid stuff like cXxXxxX in mind. Maybe
    someone wants to write about the Sony Cyber-shot DSC-Uxx camera series on
    eo: ;)
    s   [cghjsuCGHJSU][xX]+i    R   i   R   N(   R/   R   t	   notXConvRR  Ry  R5   R   R   R7   R9   R9  R  R  R  RN   R  R=  R   (	   R   R9  R  R  R  R  Ry  R=  R7   (    (    R   RC    s       Ic         C   s.   t  i |  i d d  i |   i d d  S(   NR   Ra   t   %R  (   R^   R_   R   Rc   R\   RM   (   R   RM   (    (    R   RL     s    c         C   s_   g  } xI |  D]A } t |  } | d j  o | i |  q | i d |  q Wd i |  S(   Ni   s   &#%d;R   (   t   htmlR  R  t   ordt   cordRc  R  (   R  R  R  R  (    (    R   t   UnicodeToAsciiHtml  s     c         C   s   | i   g t | i    } | o: | | j o- | i | i    | t | i    7} n d  } xf | D]^ } y/ |  i |  } t i |  } t | |  SWqm t j
 o } | p
 | } q qm Xqm W|  d  S(   N(   R   RM   R&  t	   encodingst   encListR   Rc  R$   t   firstExceptiont   encR*   R\   R+   R^   t   unquoteR   R  t   ex(   R*   R   R   R   R  R  R+   R  (    (    R   R,     s      
	c         C   s7   y |  i |  Wn t j
 o t |   }  n X|  S(   s   
    We have a unicode string. We can attempt to encode it into the desired
    format, and if that doesn't work, we encode the unicode into html #
    entities. If it does work, we return it unchanged.
    N(   R   R\   RM   R  R  (   R   RM   (    (    R   R    s     c   	      C   s  t  i d  } d } d } t } x[| oS|  | }  | i |   } | od	 } | i d  o t | i d   } nt | i d  o t | i d  d  } nH | i d  o7 | i d  } t i i |  o t i | } q n | |  | i    7} | o5 | | j o( t p | d j  o | t |  7} n | |  | i   | i   !7} | i   } q$ | |  7} t } q$ W| S(
   s^   
    Given a string, replaces all HTML entities by the equivalent unicode
    characters.
    sA   &(#(?P<decimal>\d+)|#x(?P<hex>[0-9a-fA-F]+)|(?P<name>[A-Za-z]+));u    i    t   decimalt   hexi   RC   i  N(   R/   R   t   entityRRy  R  R5   t   foundR   R   R7   R$   t   unicodeCodepointR9   R   RC   t   htmlentitydefst   name2codepointR  R   t   ignoret	   WIDEBUILDt   unichrR   R"   (	   R   R
  RC   R  R  R  Ry  R  R7   (    (    R   R)     s6      
(
c         B   s   |  d j o e i }  n y2 d k } e i i | i	 d   d |  d UWnX e
 j
 oL | o2 e d |   d k } | i   e i d  q e d   n Xe i   S(   s   
    Import the named family.
    If fatal is true, the bot will stop running when the given family is
    unknown. If fatal is false, it will only raise a ValueError exception.
    Nt   familiess   import %s_family as myfamilyuq   Error importing the %s family. This probably means the family does not exist. Also check your configuration file.i   s   Family does not exist(   R_  R$   Rk   R?   R  R  RY   R   Rc  R  t   ImportErrort   fatalRE   RR  t   print_stackt   exitRH   t   myfamilyt   Family(   R_  R  R  RR  (    (    R   R  '  s     		
t   Sitec           B   s  t  Z d  d  d  d  Z d   Z e e d  Z d e e d  Z e d  Z	 e d  Z
 e d  Z e d	  Z e i d
  Z e e d  e d  Z d   Z d   Z d e e d  Z d e d  Z d e d  Z d e d  Z d e d  Z d e d  Z d e d  Z d e d  Z d e d  Z d e d  Z d e d  Z d e d  Z d e d  Z d d e e d  Z  d   Z! d    Z" d  d!  Z# d"   Z$ d#   Z% d$   Z& e d%  Z' d&   Z( d'   Z) d(   Z* d) d*  Z+ d) d+  Z, d,   Z- d-   Z. d.   Z/ d/   Z0 d0   Z1 d1   Z2 d2   Z3 d3   Z4 d4   Z5 d5   Z6 d6 d7  Z7 d8   Z8 d9   Z9 d:   Z: d;   Z; d<   Z< d=   Z= d>   Z> d?   Z? d@   Z@ dA   ZA dB   ZB dC d dD  ZC dE   ZD d dF  ZE dG dH  ZF dC dI  ZG dC dJ  ZH dC dK  ZI dC dL  ZJ dC dM  ZK dC dN  ZL dC dO  ZM dC dP  ZN dC dQ  ZO dC dR  ZP dC dS  ZQ dC dT  ZR dU   ZS dV   ZT dW   ZU e dX  ZV e dY  ZW e dZ  ZX d[   ZY d\   ZZ d]   Z[ d^   Z\ d_   Z] d`   Z^ da   Z_ db   Z` dc   Za dd   Zb de   Zc dC d6 df  Zd dg   Ze e dh  Zf di   Zg dj   Zh dk   Zi dl   Zj dm   Zk dn   Zl do   Zm dp   Zn dq   Zo dr   Zp e e e ds  Zq e dt  Zr RS(u   Nc         C   su  | i   |  _ t | t  p | d	 j o t | d t	 |  _
 n
 | |  _
 |  i |  i   j oS |  i d j o  d |  i   j o d |  _ q t d |  i |  i
 i f   n |  i |  i
 i j o. |  i
 i |  i o |  i
 i |  i |  _ n t	 |  _ h  |  _ |  i |  i
 i j |  _ | |  _ d	 |  _ d	 |  _ h  |  _ d	 |  _ g  |  _ g  |  _ xM |  i   D]? } | d i   | d |  i   j o |  i i |  qqqqW| d	 j o t i } n | o |  i   d
 j |  _ | ob |  i   d j o t  i! |  i"    |  _# qS|  i   d j o t  i$ |  i"    |  _# qSn t% |  |  i
 i& |   |  _& d	 S(   s&  Constructor takes four arguments:

        code    language code for Site
        fam     Wikimedia family (optional: defaults to configured).
                Can either be a string or a Family object.
        user    User to use (optional: defaults to configured)
        persistent_http Use a persistent http connection. An http connection
                has to be established only once, making stuff a whole lot
                faster. Do NOT EVER use this if you share Site objects
                across threads without proper locking.
        R  s
   zh-classics   zh-classicals'   Language %s does not exist in family %si    i   t   httpt   httpsN(   R  R  ('   R  R;   R   RB   R  R_  t
   basestringR$   R  R"   R?   t	   languagesRd   RC   R  R   t   _mediawiki_messagesRO   R  t   _tokent   _sysoptokent   loginStatusKnownR   t
   userGroupst   _validlanguagesRy   RP   R)  Rc  t   persistent_httpRk   R   Rl  t   HTTPConnectionR   t   connt   HTTPSConnectionR   t   sandboxpage(   R   R  R_  R  R  Ry   (    (    R   R   ?  sD     	##*									 %  c         C   s   | p d Sn g  } x | i   D] \ } } t | t  o | i d  } n t | t  o | i d  } n t	 i
 |  } t	 i
 |  } | i | d |  q" Wd i |  S(   s[   This can encode a query so that it can be sent as a query using
        a http POST requests   utf-8R   R   N(   R  R$   t   lR|  t   keyt   valueR  R   R\   R^   R_   Rc  R  (   R   R  R$  R&  R%  (    (    R   Re  x  s      c         C   sZ   |  i |  } y  |  i | | d | d | SWn$ t i	 j
 o } t |   n Xd S(   sZ  
        Posts the given form data to the given address at this site.
        address is the absolute path without hostname.
        predata is a list of key-value tuples.
        Returns a (response, data) tuple where response is the HTTP
        response object and data is a Unicode string containing the
        body of the response.
        R   t	   useCookieN(   R   Re  R^  Rf  t   postDataR[  R   R'  RQ  R  t   eR   (   R   R[  R^  R   R'  R)  Rf  (    (    R   Rk    s      s!   application/x-www-form-urlencodedc         C   s  |  i o |  i } nY |  i   d j o t i |  i    } n- |  i   d j o t i |  i    } n | i d |  | i
 d t t |    | i
 d |  | i
 d t  | o3 |  i d |  o  | i
 d |  i d |   n |  i o | i
 d	 d
  n | i   | i |  y | i   } WnC t i j
 o4 | i   | i   |  i | | | | |  Sn X| i   i |  i    } | i   |  i p | i   n | | f S(   sV  
        Posts the given data to the given address at this site.
        address is the absolute path without hostname.
        data is an ASCII string. (or isn't it?)
        Returns a (response, data) tuple where response is the HTTP
        response object and data is a Unicode string containing the
        body of the response.
        R  R  t   POSTs   Content-Lengths   Content-types
   User-agentR   t   Cookiet
   Connections
   Keep-AliveN(   R   R  R!  R   Rl  R   R   R"  t
   putrequestR[  t	   putheaderRo   RN   Rf  t   contentTypeRd  R'  t   cookiesR   t
   endheaderst   sendt   getresponseRj  Rm  R  t   connectR(  R  R  RM   (   R   R[  Rf  R/  R   R'  Rj  R!  (    (    R   R(    s8     
 





c         C   s_   |  i d |  pH t i d |  d |  } | i d t  o t |  _ | i |  _	 q[ n d  S(   NR   R   t   retry(
   R   t
   loggedInAsR   t   logint   LoginManagert   loginManR5   R  R   R   (   R   R   R9  (    (    R   R     s
    	c   	      C   s  |  i d |  |  i p t d |   |  i d  } |  i | d | } t	 i
 d  } | i |  } | o t |  _ | i d  |  _ d | j o t d |   t } n t } t	 i
 d  } | i |  } | o  |  i | i d	  d | q qn |  i S(   s  
        Checks if we're logged in by loading a page and looking for the login
        link. We assume that we're not being logged out during a bot run, so
        loading the test page is only required once.

        If logged in, returns the username. Otherwise, returns None
        R   u0   Getting a page to check if we're logged in on %ss   Non-existing_pages=   <li id="pt-userpage"><a href=".+?">(?P<username>.+?)</a></li>R   s   <div class="usermessage">u$   NOTE: You have unread messages on %ss:   \<input type='hidden' value=\"(.*?)\" name=\"wpEditToken\"i   N(   R   t   _loadCookiesR   R  RE   RZ  R   R   R   R/   R   t   mytalkRR   R8   R5   R9   R   R   R"   R   R   R   (	   R   R   R   R   R8   R;  R   R   R   (    (    R   R6    s(     
	
(c         C   s   |  i d |  |  i S(   NR   (   R   R:  R   t   _cookies(   R   R   (    (    R   R0    s    c   	      C   sW  y| | oW y t i |  i i |  i } Wq{ t j
 o& t	 d |  i i |  i f   q{ Xn t i
 |  i i |  i } Wn% t j
 o d |  _ t |  _ n Xd k } d |  i i |  i | f } | i d |  } t i i |  p d |  _ t |  _ nP t |  } d i g  } | i   D] } | | i   q'~  |  _ | i   d S(   s"   Retrieve session cookies for logins   You tried to perform an action that requires admin privileges, but you haven't entered your sysop name in your user-config.py. Please add sysopnames['%s']['%s']='name' to your user-config.pyNs   %s-%s-%s-login.datas
   login-datas   ; (   R   Rk   Rs  R   R?   RC   RB   R   Rd   R   Ru  R$   R<  R5   R  R  R  t   tmpR  t   fnt   osR   R   R:  R;  R  R  R  R   R1   R  (	   R   R   R   R=  R;  R  R  R   R>  (    (    R   R:    s(     (			9u   var wgUserGroups \= (.*)\;c         C   s6  |  i o| o|  i i d |  |  i i d t  |  i i d |  i d |   |  i i d d  | o |  i i d d  n |  i i   y |  i i   } WnI t i j
 o: |  i i   |  i i   |  i | | | | |  Sn X| i   } | i d	  } | i d
  } n,|  i   t i i   j o
 t } nX t   } |  i d |  o  | i  d |  i d |   n | o | i  d d  n d |  i!   |  i   | f } |  i# |  } d } t% } xC| p;y |  i   t i i   j o^ | oA t' i( | |  } | i* d d  t' i+   }
 |
 i- |  } qrt' i/ | |  } n | i- | |  } t0 } Wqt1 j
 o
   qt2 j
 o} } | oj t4 d |  t4 d |  i!   |  i   | | f  t5 i6 | d  | d 9} | d j o
 d } qq  qXqW| i   } | i7   d	 } | i8 i9 d
  } | ox | d j ok y d k: l; } Wn  t< j
 o d k; l; } n Xd k= } | |  } | i? d |  } | i   } n tA iB d  } | iD |  } | o | iF d  }	 n t4 d  d }	 |  iH |	  y tI | |	 d d } WnR tJ j
 oF } | GHt4 d |  i!   |  i   | f  tI | |	 d d } n X|  iK iD |  } | o g  |  _M | iF d  d j og | iF d  d d !iN d  } xE | D]9 } | iP d  d  j o |  iM iQ | iP d   qqWq2n | S(!   s  
        Low-level routine to get a URL from the wiki.

        Parameters:
            path  - The absolute path, without the hostname.
            retry - If True, retries loading the page when a network error
                    occurs.
            sysop - If True, the sysop account's cookie will be used.
            data  - An optional dict providing extra post request parameters

           Returns the HTML text of the page converted to unicode.
        t   GETs
   User-agentR+  R   R,  s
   Keep-Alives   Accept-encodingt   gzips   Content-Types   Content-Encodings	   %s://%s%si   u   %suk   WARNING: Could not open '%s://%s%s'. Maybe the server or your connection is down. Retrying in %i minutes...i<   i   i   (   s   StringIONt   fileobjs   charset=([^'";]+)u    WARNING: No character set found.s   utf-8t   errorst   strictuA   ERROR: Invalid characters found on %s://%s%s, replaced by \ufffd.Rc   t   nullis   , Rw  R    (R   R   R  Rf  R!  R-  R   R.  Rd  R0  R   t   compressR1  R3  Rj  Rl  Rm  R  R4  R   R5  R  R   t	   getheaderR/  t   contentEncodingR   Rk   Rb  RA   t   authenticateURLopenerR9  R8  t	   addheaderR   R   Re  R   R"   t	   retrievedRg  Ri  t   requestt
   add_headert   build_openert   openerR:  R;  Rh  R5   t   KeyboardInterruptt	   ExceptionR)  RE   R   R   t   infot   headersR   t	   cStringIOt   StringIOR  RA  t   compressedstreamt   GzipFilet   gzipperR/   R   R   R   R8   R9   t   charsett   checkCharsetR   t   UnicodeDecodeErrort   r_userGroupsR7   R  Rf   t   uGR1   Rc  (   R   R   R5  R   Rf  RF  R   RX  R9   RY  RO  R7   R   R/  RK  R8   R   R]  Rj  R;  R   RU  RL  RH  R9  RA  R)  RV  (    (    R   R     s     
	  
&
	
#	 )c         C   s  | |  i i   j ot |  d  od } x t o t   |  i d |  i	   t
 i |  i d  i d d  i |  i     | f  a t t d t i d t d	  a t i d j o_ t d
 |  i   |  i	   | | f  t i | d  | d 9} | d j o
 d } q0 q0 n Pq0 Wt i i i   } | o | |  i | <qd |  i | <t o t d  n t   |  i |  i d  d  } t! i" d  } x0 | i$ |  D] \ } } | |  i t' |  <qWt |  _( n |  i | d j o t) d | |  f   n |  i | S(   s0   Return the MediaWiki message text for key "key" t
   _phploadedi   s   %s?title=%s:%s&action=editi   R   Ra   R   R   t   textareauw   WARNING: No text area found on %s%s?title=MediaWiki:%s&action=edit.
Maybe the server is down. Retrying in %i minutes...i<   i   i   u6   Retrieving mediawiki messages from Special:Allmessagess   Special:Allmessagess   &ot=phps"   (?ms)'([^']*)' =&gt; '(.*?[^\\])',s'   MediaWiki key '%s' does not exist on %sN(*   R%  R   R  RA   Rv   R   R5   R   R   R   R^   R_   RQ   Rc   R\   RM   t   mwpageR   R   R   t   treeR_  R$   RE   R   R   R   R  R1   R&  R   R   t   phppageR/   R   t   RphpvalsR  t   phpkeyt   phpvalRo   R^  Rd   (   R   R%  Rc  R   Rb  Rd  R&  Re  (    (    R   R     sF      ' O	&

 c         C   s5   y |  i |  } t SWn t j
 o t Sn Xd S(   sD   Return True iff this site defines a MediaWiki message for key "key" N(   R   R   R%  t   vR5   Rd   R"   (   R   R%  Rf  (    (    R   R     s     i
   c         c   s-  | o
 t } n t   } xt o|  i d |  } t	   |  i
 |  }	 t i d  } x | i |	  D] } | i d  } | i d  } | i d d  } t | i d   } d } | i d	  }
 d } | | j o6 | i |  t |  |  } | | | | |
 | f Vqk qk W| p Pq q Wd
 S(   s  Generator which yields new articles subsequently.
           It starts with the article created 'number' articles
           ago (first argument). When these are all yielded
           and repeat is True,
           it fetches NewPages again. If there is no new page,
           it blocks until there is one, sleeping between subsequent
           fetches of NewPages.

           The objects yielded are dictionairies. The keys are
           date (datetime object), title (pagelink), length (int)
           user_login (only if user is logged in, string), comment
           (string) and user_anon (if user is not logged in, string).

        t   ns   <li[^>]*>(?P<date>.+?) \S*?<a href=".+?" title="(?P<title>.+?)">.+?</a>.+?[\(\[](?P<length>\d+)[^\)\]]*[\)\]] .?<a href=".+?" title=".+?:(?P<username>.+?)">Rw   R*   s   &quot;Rw  t   lengthu    R   N(   t   repeatR5   R   R   t   seenR   t   newpages_addressR  R   R   R   R  R/   R   t   entryRR  R8   R9   Rw   R*   Rc   R   Rh  t   loggedInR   R2  R  R   R
  (   R   R  R   Ri  R2  Rm  Rj  Rl  R*   R  R   Rw   R   R   R8   Rh  R
  (    (    R   t   newpages  s2     
	  c         c   s   t  } t   }
 x t  o |  i d |  }	 t   |  i	 |	  } t i d  } xr | i |  D]a } | i d  } t | i d   } | |
 j o* |
 i |  t |  |  } | | f Vq` q` W| p Pq q Wd  S(   NRg  u{   <li>\(<a href=".+?" title=".+?">hist</a>\) ‎<a href=".+?" title="(?P<title>.+?)">.+?</a> ‎\[(?P<length>\d+)(.+?)\]</li>R*   Rh  (   R5   R   R   Rj  R   t   longpages_addressR  R   R   R   R  R/   R   Rl  R  R8   R9   R*   R   Rh  R  R   R
  Ri  (   R   R  Ri  Rl  R   R*   R8   R
  Rh  R   Rj  R  (    (    R   t	   longpages  s$    	  c         c   s   t  } t   }
 x t  o |  i d |  }	 t   |  i	 |	  } t i d  } xr | i |  D]a } | i d  } t | i d   } | |
 j o* |
 i |  t |  |  } | | f Vq` q` W| p Pq q Wd  S(   NRg  u{   <li>\(<a href=".+?" title=".+?">hist</a>\) ‎<a href=".+?" title="(?P<title>.+?)">.+?</a> ‎\[(?P<length>\d+)(.+?)\]</li>R*   Rh  (   R5   R   R   Rj  R   t   shortpages_addressR  R   R   R   R  R/   R   Rl  R  R8   R9   R*   R   Rh  R  R   R
  Ri  (   R   R  Ri  Rl  R   R*   R8   R
  Rh  R   Rj  R  (    (    R   t
   shortpages  s$    	  c         c   s   t  } t   }	 x t  o |  i d |  } t   |  i	 |  }
 t i d  } xW | i |
  D]F } | i d  } | |	 j o$ |	 i |  t |  |  } | Vq` q` W| p Pq q Wd  S(   NRg  s5   <li><a href=".+?" title="(?P<title>.+?)">.+?</a></li>R*   (   R5   R   R   Rj  R   t   categories_addressR  R   R   R   R  R/   R   Rl  R  R8   R9   R*   R  R   R
  Ri  (   R   R  Ri  Rl  R   R*   R8   R
  R   Rj  R  (    (    R   R    s"    	  c         c   s   t  } t   }	 x t  o |  i d |  } t   |  i	 |  }
 t i d  } xW | i |
  D]F } | i d  } | |	 j o$ |	 i |  t |  |  } | Vq` q` W| p Pq q Wd  S(   NRg  s5   <li><a href=".+?" title="(?P<title>.+?)">.+?</a></li>R*   (   R5   R   R   Rj  R   t   deadendpages_addressR  R   R   R   R  R/   R   Rl  R  R8   R9   R*   R  R   R
  Ri  (   R   R  Ri  Rl  R   R*   R8   R
  R   Rj  R  (    (    R   t   deadendpages1  s"    	  c         c   s   t  } t   }
 x t  o |  i d |  } t   |  i	 |  } t i d  } xl | i |  D][ } | i d  } | i d  }	 | |
 j o* |
 i |  t |  |  } | |	 f Vq` q` W| p Pq q Wd  S(   NRg  sC   <li><a href=".+?" title="(?P<title>.+?)">.+?</a> (?P<date>.+?)</li>R*   Rw   (   R5   R   R   Rj  R   t   ancientpages_addressR  R   R   R   R  R/   R   Rl  R  R8   R9   R*   Rw   R  R   R
  Ri  (   R   R  Ri  Rl  R   R*   R8   R
  R   Rw   Rj  R  (    (    R   t   ancientpagesC  s$    	  c         c   s   t  } t   }	 x t  o |  i d |  } t   |  i	 |  }
 t i d  } xW | i |
  D]F } | i d  } | |	 j o$ |	 i |  t |  |  } | Vq` q` W| p Pq q Wd  S(   NRg  s5   <li><a href=".+?" title="(?P<title>.+?)">.+?</a></li>R*   (   R5   R   R   Rj  R   t   lonelypages_addressR  R   R   R   R  R/   R   Rl  R  R8   R9   R*   R  R   R
  Ri  (   R   R  Ri  Rl  R   R*   R8   R
  R   Rj  R  (    (    R   t   lonelypagesV  s"    	  c         c   s   t  } t   }	 x t  o |  i d |  } t   |  i	 | d t  }
 t i d  } xW | i |
  D]F } | i d  } | |	 j o$ |	 i |  t |  |  } | Vqf qf W| p Pq q Wd  S(   NRg  R   s8   <li><a href=".+?" title="(?P<title>.+?)">.+?</a>.+?</li>R*   (   R5   R   R   Rj  R   t   unwatchedpages_addressR  R   R   R   R  R/   R   Rl  R  R8   R9   R*   R  R   R
  Ri  (   R   R  Ri  Rl  R   R*   R8   R
  R   Rj  R  (    (    R   t   unwatchedpagesh  s"    	  c         c   s   t  } t   }	 x t  o |  i d |  } t   |  i	 |  }
 t i d  } xW | i |
  D]F } | i d  } | |	 j o$ |	 i |  t |  |  } | Vq` q` W| p Pq q Wd  S(   NRg  s5   <li><a href=".+?" title="(?P<title>.+?)">.+?</a></li>R*   (   R5   R   R   Rj  R   t   uncategorizedcategories_addressR  R   R   R   R  R/   R   Rl  R  R8   R9   R*   R  R   R
  Ri  (   R   R  Ri  Rl  R   R*   R8   R
  R   Rj  R  (    (    R   t   uncategorizedcategoriesy  s"    	  c         c   s   t  } t   }	 x t  o |  i d |  } t   |  i	 |  }
 t i d  } xW | i |
  D]F } | i d  } | |	 j o$ |	 i |  t |  |  } | Vq` q` W| p Pq q Wd  S(   NRg  s5   <li><a href=".+?" title="(?P<title>.+?)">.+?</a></li>R*   (   R5   R   R   Rj  R   t   uncategorizedpages_addressR  R   R   R   R  R/   R   Rl  R  R8   R9   R*   R  R   R
  Ri  (   R   R  Ri  Rl  R   R*   R8   R
  R   Rj  R  (    (    R   t   uncategorizedpages  s"    	  c         c   s   t  } t   }	 x t  o |  i d |  } t   |  i	 |  }
 t i d  } xW | i |
  D]F } | i d  } | |	 j o$ |	 i |  t |  |  } | Vq` q` W| p Pq q Wd  S(   NRg  s5   <li><a href=".+?" title="(?P<title>.+?)">.+?</a></li>R*   (   R5   R   R   Rj  R   t   unusedcategories_addressR  R   R   R   R  R/   R   Rl  R  R8   R9   R*   R  R   R
  Ri  (   R   R  Ri  Rl  R   R*   R8   R
  R   Rj  R  (    (    R   t   unusedcategories  s"    	  c         c   s   t  } t   }	 x t  o |  i d |  } t   |  i	 |  }
 t i d  } xW | i |
  D]F } | i d  } | |	 j o$ |	 i |  t |  |  } | Vq` q` W| p Pq q Wd  S(   NRg  s5   <li>\(<a href=".+?" title="(?P<title>.+?)">.+?</a>\) R*   (   R5   R   R   Rj  R   t   unusedfiles_addressR  R   R   R   R  R/   R   Rl  R  R8   R9   R*   R  R  R
  Ri  (   R   R  Ri  Rl  R   R*   R8   R
  R   Rj  R  (    (    R   t   unusedfiles  s"    	  c         c   s   t  } t   }	 x t  o |  i d |  } t   |  i	 |  }
 t i d  } xW | i |
  D]F } | i d  } | |	 j o$ |	 i |  t |  |  } | Vq` q` W| p Pq q Wd  S(   NRg  s5   <li><a href=".+?" title="(?P<title>.+?)">.+?</a></li>R*   (   R5   R   R   Rj  R   t   withoutinterwiki_addressR  R   R   R   R  R/   R   Rl  R  R8   R9   R*   R  R   R
  Ri  (   R   R  Ri  Rl  R   R*   R8   R
  R   Rj  R  (    (    R   t   withoutinterwiki  s"    	  t   !i    c      	   c   sr  xkt  oc| i |  i    } t i |  } |  i | |  }	 t
 d t |   | | f  |  i |	  } yX |  i   d j o d } d } n d } d } | i |  }
 | i | |
 d  } Wn t j
 o t d   n X| |
 | !} |  i   d j o t i d	  } np |  i   d
 j  o t i d  } nJ | p t i d  } n0 | d j o t i d  } n t i d  } d } x} | i |  D]l } | d } |  i   d j o# t |  t | d |  d |   Vn t |  |  Vt |  |  i   d } qW| d j  oN | p | d j o4 t i d  } t  | i |   d j  o PqeqiPq q Wd S(   s  Generator which yields all articles in the home language in
           alphanumerical order, starting at a given page. By default,
           it starts at '!', so it should yield all pages.

           If includeredirects is False, redirects will not be found.
           If includeredirects equals the string 'only', only redirects
           will be found. Note that this has not been tested on older
           versions of the MediaWiki code.

           The objects returned by this generator are all Page()s.

           It is advised not to use this directly, but to use the
           AllpagesPageGenerator from pagegenerators.py instead.
        u=   Retrieving Allpages special page for %s from %s, namespace %ii   s   </table><hr /><tables   </tables   <tablei   sQ   Couldn't extract allpages special page. Make sure you're using the MonoBook skin.i   s!   /wiki/(.*?)" *class=['"]printablei   s   title ?="(.*?)"s%   \<td\>\<a href="\S*" +title ?="(.*?)"t   onlysA   \<td>\<[^\<\>]*allpagesredirect"\>\<a href="\S*" +title ?="(.*?)"i    i   R   R(   R  id   N(!   R5   R   R\   R   RM   R^   R_   t   allpages_addressRQ   R   RE   t   reprR   t   returned_htmlR  t   begin_st   end_sR  R  R  RH   R   R/   R   R   t   includeredirectsRg  R  t   hitR   R  Rg   RN   (   R   R   RQ   R  R   R  R  R  R   R   R  Rg  R  R  (    (    R   t   allpages  sT      
 
#	c         c   s  | i d  o | d } n x | d | g D] } |  i i |  i |  } t   |  i	 |  } | i d  } | d j o | | } n | i d  } | d j o | |  } n t i d  } x5 | i |  D]$ } | | j o t |  |  Vq q Wq/ Wd  S(   Ns   *.i   s   <div class="mw-spcontent">is   <div class="printfooter">s   title ?="(.*?)"(   t   siteurlR2   R   R   R?   t   linksearch_addressRB   R   R   R   R  RI   t   locR/   R   R   R  R*   R   (   R   R  R  R   R*   R  R   R   (    (    R   t
   linksearch  s$      c         C   s   |  i i d |  i S(   NR    (   R   R?   RC   RB   (   R   (    (    R   Rp   0  s    c         C   s;   | o( | i |  i j o d |  i | f Sn	 d | Sd  S(   Ns	   [[%s:%s]]s   [[%s]](   R  RB   R   R*   (   R   R*   R  (    (    R   R  3  s    c         C   s  | i d  } d | j o t Sn | i d d  \ } } | i   i   } |  i	 i
 o t |  i	 i
  } n
 |  i	 } |  i |  o t Sn | | i j o) | |  i j o |  i |  Sq t Sn | |  i	 i j o, | |  i	 i j o |  i |  Sq
t Sn t S(   s6  
        Try to check whether s is in the form "foo:bar" or ":foo:bar"
        where foo is a known language code or family. In such a case
        we are dealing with an interwiki link.
        Called recursively if the first part of the link refers to this
        site's own family and/or language.
        R    i   N(   R  t   lstripR"   Rf   t   firstt   restR;   R1   R   R?   t   interwiki_forwardR  t   interlangTargetFamilyR=   R@   RB   R   R5   RD   RC   (   R   R  R  R  R  (    (    R   R   9  s(     	c         C   s   |  i i |  i  S(   N(   R   R?   t   code2encodingRB   (   R   (    (    R   RM   Z  s    c         C   s   |  i i |  i  S(   N(   R   R?   t   code2encodingsRB   (   R   (    (    R   R  ]  s    c         C   sA   | o |  i i i |  i d  Sn |  i i i |  i d  Sd S(   s   
        Gives the localized redirect tag for the site. Falls back
        to 'REDIRECT' if the site has no special redirect tag.
        t   REDIRECTN(   t   defaultR   R?   t   redirectR   RB   R$   (   R   R  (    (    R   R  `  s     c         C   sz   y5 d g |  i i |  i } d d i |  d } Wn t j
 o d } n Xt i	 d | d t i
 t i Bt i B S(	   sj   
        Regular expression recognizing redirect pages, with a
        group on the target title.
        u   redirects   (?:R   t   )R  Rz   s   .*?\[\[(.*?)(?:\]|\|)N(   R   R?   R  RB   t   redirKeywordsR  t   redirKeywordsRRd   R/   R   R  R  R  (   R   R  R  (    (    R   R   j  s     c         C   s   |  i i |  i  S(   N(   R   R?   t   category_namespaceRB   (   R   (    (    R   R  |  s    c         C   s   |  i i |  i  S(   N(   R   R?   R  RB   (   R   (    (    R   R    s    R  c         C   s   |  i i |  i |  S(   N(   R   R?   R  RB   t   fallback(   R   R  (    (    R   R    s    c         C   s   |  i i |  i |  S(   N(   R   R?   t   template_namespaceRB   R  (   R   R  (    (    R   R    s    c         C   s   |  i i |  i  S(   N(   R   R?   Rs  RB   (   R   (    (    R   Rs    s    c         C   s   |  i i |  i  S(   N(   R   R?   t   query_addressRB   (   R   (    (    R   R    s    c         C   s   |  i i |  i  S(   N(   R   R?   R  RB   (   R   (    (    R   R    s    c         C   s   |  i i |  i  S(   N(   R   R?   t   apipathRB   (   R   (    (    R   R    s    c         C   s   |  i i |  i  S(   N(   R   R?   R   RB   (   R   (    (    R   R     s    c         C   s   |  i i |  i  S(   N(   R   R?   R   RB   (   R   (    (    R   R     s    c         C   s   |  i i |  i  S(   N(   R   R?   R   RB   (   R   (    (    R   R     s    c         C   s   |  i i |  i  S(   N(   R   R?   t   dbNameRB   (   R   (    (    R   R    s    c         C   s   |  i i |  i  S(   N(   R   R?   R  RB   (   R   (    (    R   R    s    c         C   s   |  i i |  i |  S(   N(   R   R?   R  RB   R  (   R   R  (    (    R   R    s    R   c         C   s   |  i i |  i | |  S(   N(   R   R?   R   RB   R  R  (   R   R  R  (    (    R   R     s    c         C   s   |  i i |  i  S(   N(   R   R?   R  RB   (   R   (    (    R   R    s    c         C   s   |  i i |  i |  S(   N(   R   R?   R  RB   R  (   R   R  (    (    R   R    s    c         C   s   |  i i |  i |  S(   N(   R   R?   R  RB   R  (   R   R  (    (    R   R    s    c         C   s   |  i i |  i |  S(   N(   R   R?   RZ  RB   R  (   R   R  (    (    R   RZ    s    c         C   s   |  i i |  i |  S(   N(   R   R?   R   RB   R  (   R   R  (    (    R   R     s    c         C   s   |  i i |  i |  S(   N(   R   R?   t   nice_get_addressRB   R  (   R   R  (    (    R   R    s    c         C   s   |  i i |  i |  S(   N(   R   R?   R   RB   R  (   R   R  (    (    R   R     s    c         C   s   |  i i |  i |  S(   N(   R   R?   t   purge_addressRB   R  (   R   R  (    (    R   R    s    c         C   s   |  i i |  i  S(   N(   R   R?   t   block_addressRB   (   R   (    (    R   R    s    c         C   s   |  i i |  i  S(   N(   R   R?   t   unblock_addressRB   (   R   (    (    R   R    s    c         C   s   |  i i |  i |  S(   N(   R   R?   t   blocksearch_addressRB   R  (   R   R  (    (    R   R    s    i  c         C   s"   |  i i |  i | d | d | S(   Nt   limitt   offset(   R   R?   R  RB   R  R  R  (   R   R  R  R  (    (    R   R    s    c         C   s   t  |  d  p | |  _ n |  i i   | i   j p  t d t |   |  i | f  |  i   i   | i   j o) t d t |   | |  i   f   n d  S(   NRY  s$   charset for %s changed from %s to %ssC   code2encodings has wrong charset for %s. It should be %s, but is %s(   Rv   R   RY  R;   R.  R  RM   RH   (   R   RY  (    (    R   RZ    s
    <c         C   s   |  i i |  i d | d | S(   NR   RQ   (   R   R?   R  RB   R  R>   (   R   R  R>   (    (    R   R    s    i2   c         C   s   |  i i |  i |  S(   N(   R   R?   Rk  RB   Rg  (   R   Rg  (    (    R   Rk    s    c         C   s   |  i i |  i |  S(   N(   R   R?   Ro  RB   Rg  (   R   Rg  (    (    R   Ro    s    c         C   s   |  i i |  i |  S(   N(   R   R?   Rq  RB   Rg  (   R   Rg  (    (    R   Rq    s    c         C   s   |  i i |  i |  S(   N(   R   R?   R  RB   Rg  (   R   Rg  (    (    R   R    s    c         C   s   |  i i |  i |  S(   N(   R   R?   Rs  RB   Rg  (   R   Rg  (    (    R   Rs    s    c         C   s   |  i i |  i |  S(   N(   R   R?   Rt  RB   Rg  (   R   Rg  (    (    R   Rt    s    c         C   s   |  i i |  i |  S(   N(   R   R?   Rv  RB   Rg  (   R   Rg  (    (    R   Rv    s    c         C   s   |  i i |  i |  S(   N(   R   R?   Rx  RB   Rg  (   R   Rg  (    (    R   Rx    s    c         C   s   |  i i |  i |  S(   N(   R   R?   Rz  RB   Rg  (   R   Rg  (    (    R   Rz    s    c         C   s   |  i i |  i |  S(   N(   R   R?   R|  RB   Rg  (   R   Rg  (    (    R   R|    s    c         C   s   |  i i |  i |  S(   N(   R   R?   R~  RB   Rg  (   R   Rg  (    (    R   R~    s    c         C   s   |  i i |  i |  S(   N(   R   R?   R  RB   Rg  (   R   Rg  (    (    R   R    s    c         C   s   |  i i |  i |  S(   N(   R   R?   R  RB   Rg  (   R   Rg  (    (    R   R    s    c         C   s   |  i i |  i |  S(   N(   R   R?   R   RB   R  (   R   R  (    (    R   R     s    c         C   s   |  i i |  i  S(   N(   R   R?   t   allmessages_addressRB   (   R   (    (    R   R    s    c         C   s   |  i i |  i  S(   N(   R   R?   t   upload_addressRB   (   R   (    (    R   R    s    c         C   s   |  i i |  i | |  S(   N(   R   R?   t   maintenance_addressRB   R0   t   default_limit(   R   R0   R  (    (    R   R    s    c         C   s   |  i i |  i |  S(   N(   R   R?   t   double_redirects_addressRB   R  (   R   R  (    (    R   R    s    c         C   s   |  i i |  i |  S(   N(   R   R?   t   broken_redirects_addressRB   R  (   R   R  (    (    R   R    s    c         C   s   t  t |    S(   N(   R  R  R   (   R   (    (    R   R    s    c         C   s   |  i i |  i  S(   N(   R   R?   t   versionRB   (   R   (    (    R   R    s    c         C   s   |  i i |  i  S(   N(   R   R?   R  RB   (   R   (    (    R   R    s    c         C   s   t  |  d  p |  i |  i d   } t | d d a t i d d  d i i	 } t i d t |   } | o= t | i d   t | i d	   | i d
  f |  _ q |  i i |  i  i d  |  _ n |  i S(   s   Return the 'real' version number found on [[Special:Versions]]
           as a tuple (int, int, str) of the major and minor version numbers
           and any other text contained in the version.
        t   _mw_versions   Special:VersionR   R  R   t	   MediaWikii   s   ^: ([0-9]+)\.([0-9]+)(.*)$i   i   R  N(   Rv   R   R   R   t   versionpageR   t   htmldatat   findAllR  t   nextSiblingt   versionstringR/   R7   Ro   R8   R   R9   R  R?   R  RB   Rf   (   R   R8   R  R  (    (    R   t   live_version  s      =%c         C   s   |  i i |  i  S(   N(   R   R?   t   shared_image_repositoryRB   (   R   (    (    R   R  *  s    c         C   s[   t  | t  p d Sn |  i | i j o t |  i | i  Sn t |  i i | i i  S(   sX   Pseudo method to be able to use equality and inequality tests on
           Site objectsi   N(   R  R  R  R   R?   R  RB   RC   (   R   R  (    (    R   R  -  s     c         C   s   |  i |  i i j S(   N(   R   RB   R?   R  (   R   (    (    R   R  6  s    c         C   s   |  i i i |  i d   S(   N(   R   R?   R  R   RB   R$   (   R   (    (    R   R  9  s    c         C   s   |  i i i |  i  o t |  |  i i |  i d j o g  } x! | D] } | i | i	    qJ Wg  } xS |  i i |  i d D]: } y | i | | i |   Wq t j
 o q Xq W| Sq t Sn t Sd  S(   Ni    i   (   R   R?   R  R  RB   RN   t   list_of_linkst   list_of_links2Rc  Ry   R&  R  RH   R"   (   R   R  RB   R  R&  (    (    R   R  <  s     $  	c         C   s   |  i i |  i  S(   N(   R   R?   t   login_addressRB   (   R   (    (    R   R  N  s    c         C   s   |  i i |  i  S(   N(   R   R?   t   watchlist_addressRB   (   R   (    (    R   R  Q  s    c         C   s   |  i i |  i | | |  S(   N(   R   R?   t   contribs_addressRB   R  R  R  (   R   R  R  R  (    (    R   R  T  s    c         C   s   t  d | d |  i d |  i  S(   NR  R_  R  (   R%   R  R   R?   R  (   R   R  (    (    R   R%   W  s    c         C   s   |  i i |  i | d | S(   NR   (   R   R?   RQ   RB   R#  R   (   R   R#  R   (    (    R   RQ   Z  s    c         C   s   |  i i |  i |  S(   N(   R   R?   t   normalizeNamespaceRB   R&  (   R   R&  (    (    R   R  ]  s    c         C   s   t  i |   o t  |  Sn g  } xy |  i i D]k } y |  i i |  i |  } Wn t
 j
 o
 q/ n X| d  j	 o# | i |  i i |  i |   q/ q/ W| t  |  <| Sd  S(   N(   t   _namespaceCacheR  R   t   nslistR?   R)  Rg  RQ   RB   R>   Rd   R$   Rc  (   R   R  Rg  R>   (    (    R   R)  `  s     '
c         C   s   |  i i |  i |  S(   N(   R   R?   R=   RB   RQ   (   R   RQ   (    (    R   R=   p  s    c         C   s   |  i i |  i  S(   N(   R   R?   t	   linktrailRB   (   R   (    (    R   R  s  s    c         C   s   |  i S(   N(   R   RB   (   R   (    (    R   Ry   v  s    c         C   s   |  i S(   N(   R   R?   (   R   (    (    R   R_  y  s    c         C   s   |  i i d |  i S(   NR    (   R   R?   RC   RB   (   R   (    (    R   R  |  s    c         C   s   |  i i i   S(   N(   R   R?   R@   RA   (   R   (    (    R   R    s    c         C   s   |  i S(   N(   R   R  (   R   (    (    R   R    s    c         C   s[   d  k  } y2 | i |  |  i d  d |  i i |  i  SWn t j
 o t  n Xd  S(   Ni   R    (	   R  R  R   RQ   R?   t   disambcatnameRB   Rd   R   (   R   R  (    (    R   t   disambcategory  s
    	2c         C   s   | p, | o | o |  i p | og |  i o\ t d  y# |  i i d t	 d t	 d |  Wq t
 j
 o
   q t j
 o q Xn | o |  i p t Sq |  i Sn |  i p t Sn |  i Sd  S(   Nu   Getting page to get a token.R   R   R   (   RE  R   R   R   R  R  RE   R#  R   R5   R   R   R"   (   R   R   RE  R   (    (    R   R     s    3
#	

c         C   s!   | o | |  _ n
 | |  _ d  S(   N(   R   R&  R   R  R  (   R   R&  R   (    (    R   R     s    	(s   R   R   R$   R   Re  R"   R5   Rk  R(  R   R6  R0  R:  R/   R   R\  R   R   R   Rn  Rp  Rr  R  Ru  Rw  Ry  R{  R}  R  R  R  R  R  R  Rp   R  R   RM   R  R  R   R  R  R  R  Rs  R  R  R  R   R   R   R  R  R  R   R  R  R  RZ  R   R  R   R  R  R  R  R  RZ  R  Rk  Ro  Rq  R  Rs  Rt  Rv  Rx  Rz  R|  R~  R  R  R   R  R  R  R  R  R  R  R  R  R  R  R  R  R  R  R  R  R%   RQ   R  R)  R=   R  Ry   R_  R  R  R  R  R   R   (    (    (    R   R  >  s   9	1 	5		*J			!		
																																																			c      	   C   s   |  d  j o
 t }  n | d  j o
 t } n d | |  | | f } t i	 |  p) t
 d |  d | d | d |  t | <n t | S(   Ns   %s:%s:%s:%sR  R_  R  R  (   R  R$   t   default_codeR_  t   default_familyR  R  R%  t   _sitesR  R  (   R  R_  R  R  R%  (    (    R   R%     s    

)c         C   s   |  i   a |  i a d  S(   N(   R   Ry   R  R?   R  (   R   (    (    R   t   setSite  s     c          C   sH   t  i }  y |  d |  d i d   SWn t j
 o |  d Sn Xd S(   s   
    Gets the name of the module calling this function. This is
    required because the -help option loads the module's docstring
    and because the module name will be used for the filename of the
    log.
    i    R  N(   RY   t   argvR   R   RH   (   R   (    (    R   t   calledModuleName  s     	c          C   s  t  i } t   }  g  } x| d D]} t  i d j o t | d  } n t | t	 i
  } | d j o t |   t  i d  q# | i d  o | d a q# | i d  o | d	 a q# | i d
  o! t i t | d  d t q# | i d  o! t i t | d  d t q# | d j o t t  q# | i d  o t t | d  q# | d j o t t  q# | d j p | d j o< d k } t d | i    t d t  i  t d 7a q# | i |  q# W| S(   s0  
    Takes the commandline arguments, converts them to Unicode, processes all
    global parameters such as -lang or -log. Returns a list of all arguments
    that are not global. This makes sure that global arguments are applied
    first, regardless of the order in which the arguments were given.
    i   t   win32s   windows-1252s   -helpi    s   -family:i   s   -lang:i   s   -putthrottle:i   R  s   -pt:i   s   -logs   -log:i   s   -nologs   -verboses   -vNs   Pywikipediabot %ss	   Python %s(   RY   R  R   R  t
   moduleNamet   nonGlobalArgsR   t   platformR   Rk   Rl   t   showHelpR  R2   R  R  Ra  R  R   R5   t   setLogfileStatusR"   R  RE   t
   getversionR   Rc  (   R  R   R  R   R  (    (    R   t
   handleArgs  sH      		 
  !!	t   userinterfacess   import %s_interface as uiModulei    u'  Please create a file user-config.py, and put in there:

One line saying "mylang='language'"
One line saying "usernames['wikipedia']['language']='yy'"

...filling in your username and the language code of the wiki you want to work
on.

For other possible configuration variables check config.py.
i   c         C   s(  |  d j o d g Sn |  d d g j o d g Sn |  d j o d d g Sn |  d j o d	 g Sn |  d
 d d g j o d g Sn |  d d g j o d d g Sn |  d j o d g Sn |  d d d d d d d g j o d g Sn |  d g j o d d g Sn |  d j o d d g Sn |  d d g j o d d g Sn |  d  j o d d! g Sn |  d" j o d d# g Sn |  d$ d% d& d' d( d) d* g j o d g Sn |  d+ d, g j o d+ d, d g Sn |  d- d. g j o d d/ g Sn |  d0 j o d# d g Sn |  d1 j o d2 g Sn |  d3 d4 d5 d6 d7 d8 d9 d: d; g	 j o d/ g Sn |  d< j o d/ d d g Sn |  d= d> g j o d? g Sn |  d@ j o dA d d d/ g Sn |  dB j o dC d g Sn |  dC j o dB dD g Sn |  dE dF dG dH g j o dD g Sn |  dI j o dD d g Sn |  dJ j o dK g Sn |  dL dM g j o d! g Sn |  dN dO g j o dP g Sn |  dQ dR dS dT dU dV dW dX dY dZ d[ g j o d\ g Sn |  d] d^ g j o d] d^ d\ g Sn |  d_ d` da g j o d d\ g Sn |  db dc dd g j o d g Sn |  de df dg dh g j o dg di dj dh g Sn |  dk dl dm dn do dp dj di dq g	 j o dg dh dj di g Sn |  dr j o ds dt g Sn |  du dt ds dv g j o dt ds dv dr dw g Sn |  dw j o dr dt ds g Sn |  dx j o dt ds dw dv dy dr g Sn |  dz d{ d| d} d~ d g j o d{ d~ d| g Sn |  d d d g j o d d d d g Sn |  d d g j o d d d d g Sn |  d d d d g j o d d g Sn |  d j o d g Sn |  d j o d g Sn |  d j o d g Sn |  d j o d d g Sn g  S(   Nt   aat   amt   fat   soR  t   kut   trt   skt   cst   bart   hsbt   ksht   det   alst   lbt   frt   ioR   t   ant   astt   ayt   cat   gnt   naht   qut   ess   cbk-zamt   tlt   eut   glkt   mznt   glt   ptt   ladt   het   brt   htt   kabt   lnt   lot   nrmt   wat   iet   oct   cot   frpt   itt   yit   sat   hit   emlt   lijt   lmot   napt   pmss   roa-tarat   sct   scnt   vect   rms   bat-smgt   ltgt   ltt   iat   lat   ndss   nds-nlt   nlt   fyt   papt   vlst   zeaR  t   csbRM  t   fabt   tett   mos   roa-rupt   rot   avt   bxrt   cvt   hyt   lbes   ru-sibt   tgt   ttt   udmt   ukt   xalt   rut   bes   be-x-oldt   kkt   kyt   tkt   diqt   ugt   uzt   jat   minnant   zhs   zh-cns   zh-tws   zh-classicalt   bot   cdot   hakt   wuut   zas   zh-cdos   zh-yuet   dat   nbt   not   ist   nnt   svt   set   fit   bugR   t   jvs   map-bmst   mst   sut   bst   hrt   sht   srt   mkt   cebt   pagt   wart   bit   tpiR=  t   net   nov(   R  (   R  (    (    R   t   altlang$  s    ""(.(c         C   s   t  |  d  o |  i }  n | i |   o | |  Sn x0 t |   D]" } | i |  o | | SqF qF W| i d  o | d Sn | i   d S(   s  
    Given a language code and a dictionary, returns the dictionary's value for
    key 'code' if this key exists; otherwise tries to return a value for an
    alternative language that is most applicable to use on the Wikipedia in
    language 'code'.
    The language itself is always checked first, then languages that
    have been defined to be alternatives, and finally English. If none of
    the options gives result, we just take the first language in the
    list.
    RB   t   eni    N(   Rv   R  RB   t   dictR  RQ  t   altR  (   R  RS  RT  (    (    R   R?    s    
  c         C   sx  h  d d <d d <} d }
 g  } d }	 x]t i |  i   | i    D]=} | i d  o g  } |	 D] } | d qj ~ } | |	 d | d <xP t t t |  t |	    D]- } | | d j o | |	 d | | <q q W|
 |	 d	 7}
 | | d g 7} n^ |	 oV |
 |	 d	 7}
 g  } |	 D] } | d q(~ } | |	 d | d <| | d g 7} n d }	 | d d j o
 | }	 qI qI W|	 oV |
 |	 d	 7}
 g  } |	 D] } | d q~ } | |	 d | d <| | d g 7} n d } d } xt t t |
   D]` } | | | j o1 | d j o | d
 | | 7} qN| d 7} n | | } | |
 | 7} qWt |  d S(   s   
    Prints a string showing the differences between oldtext and newtext.
    The differences are highlighted (only on Unix systems) to show which
    changes were made.
    t   +t
   lightgreent   -t   lightredu    t   ?i    R   s   
s   {%s}s
   {default}N(   RU  RW  (   t   colort   difft   colorsR$   t   lastlinet   difflibt   ndiffR  t
   splitlinesR1  R$  R2   R  R  t
   lastcolorsR  t   minRN   R  Ry  t	   lastcolorRE   (   R  R1  Rc  RZ  R  R  R  R\  Ry  R]  R[  R$  Ra  (    (    R   t   showDiff  sP      !" !! 
c         C   si   d k  l } d k l } l } l } l } | | |    } | |  p | |  n | | |    S(   s   creates missing directories for the given path and
        returns a normalized absolute version of the path.

    - if the given path already exists in the filesystem
      the filesystem is not modified.

    - otherwise makepath creates directories along the given path
      using the dirname() of the path. You may append
      a '/' to the path if you want it to be a directory path.

    from holger@trillke.net 2002/03/18
    (   s   makedirs(   s   normpaths   dirnames   existss   abspathN(	   R?  t   makedirst   os.patht   normpatht   dirnameR   t   abspathR   t   dpath(   R   R   Re  Rj  Rg  Rh  Ri  (    (    R   t   makepath  s      c         C   s   |  o{ | p d t   } n d  k } | i d |  } y t i | d d  a	 Wq t
 j
 o t i | d d  a	 q Xn d  a	 d  S(   Ns   %s.logt   logsR  s   utf-8R  (   t   enabledt   lognameR  R  R  R  R  t   codecsR:  t   logfileR  R$   (   Rm  Rn  R  R  (    (    R   R    s     	s   {.*?}c         C   s8   t  o- t i d |   } t  i |  t  i   n d S(   s/   
    Writes the given text to the logfile.
    R   N(   Rp  t	   colorTagRR0   R   t	   plaintextR  t   flush(   R   Rr  (    (    R   R    s
     c         C   s  t  i   z | o t |  |  }  nv t |   t d  j o\ t o d GHt i   GHd GHn y t |  d  }  Wq t	 j
 o t |  d  }  q Xn | o |  d 7}  n t |   t i   o t |  d | n t i |  d | Wd t  i   Xd S(	   s  
    Works like print, but uses the encoding used by the user's console
    (console_encoding in the configuration file) instead of ASCII.
    If decoder is None, text should be a unicode string. Otherwise it
    should be encoded in the given encoding.

    If newline is True, a linebreak will be added after printing the text.

    If toStdout is True, the text will be sent to standard output,
    so that it can be piped to another process. All other text will
    be sent to stderr. See: http://en.wikipedia.org/wiki/Pipeline_%28Unix%29

    text can contain special sequences to create colored output. These
    consist of the escape character  and the color name in curly braces,
    e. g. {lightpurple}. {default} resets the color.
    u    sA   DBG> BUG: Non-unicode passed to wikipedia.output without decoder!s:   DBG> Attempting to recover, but please report this problems   utf-8s	   iso8859-1u   
t   toStdoutN(   t   output_lockR,  t   decoderR   R   R&   R   RR  R  R[  RS  R  t
   input_lockt   lockedt   cache_outputRt  t   uiRE   R/  (   R   Rv  RS  Rt  (    (    R   RE     s,     
	
 c          O   s   t  i |  | f  d  S(   N(   t   output_cacheRc  R   t   kwargs(   R   R|  (    (    R   Ry  9  s    c          C   s8   x1 t  o) t  i d  \ }  } t i |  |   q Wd  S(   Ni    (   R{  t   popR   R|  Rz  RE   (   R   R|  (    (    R   t   flush_output_cache<  s     c         C   s9   t  i   z t i |  |  } Wd t   t  i   X| S(   sq  
    Asks the user a question, then returns the user's answer.

    Parameters:
    * question - a unicode string that will be shown to the user. Don't add a
                 space after the question mark/colon, this method will do this
                 for you.
    * password - if True, hides the user's input (for password entry).

    Returns a unicode string.
    N(	   Rw  R,  Rz  R  t   questiont   passwordRf  R~  R/  (   R  R  Rf  (    (    R   R  A  s     
 c         C   sE   t  i   z" t i |  | | |  i   } Wd t
   t  i   X| S(   s  
    Asks the user a question and offers several options, then returns the
    user's choice. The user's input will be case-insensitive, so the hotkeys
    should be distinctive case-insensitively.

    Parameters:
    * question - a unicode string that will be shown to the user. Don't add a
                 space after the question mark, this method will do this
                 for you.
    * answers  - a list of strings that represent the options.
    * hotkeys  - a list of one-letter strings, one for each answer.
    * default  - an element of hotkeys, or None. The default choice that will
                 be returned when the user just presses Enter.

    Returns a one-letter string in lowercase.
    N(   Rw  R,  Rz  R  R  t   answerst   hotkeysR  R;   Rf  R~  R/  (   R  R  R  R  Rf  (    (    R   R  V  s     
" c         B   s  |  p e i d e i d i d   }  y |  |  i d  d }  Wn e j
 o n Xd } e |  y{ d |  d  Ue i i	 d  } e e d  o? x< e i i   D]' \ } } | i | | i d	   } q Wn e |  Wn   e d
 |   n Xd  S(   Ni    R  s   \i   uz  

Global arguments available for all bots:

-lang:xx          Set the language of the wiki you want to work on, overriding
                  the configuration in user-config.py. xx should be the
                  language code.

-family:xyz       Set the family of the wiki you want to work on, e.g.
                  wikipedia, wiktionary, wikitravel, ...
                  This will override the configuration in user-config.py.

-log              Enable the logfile. Logs will be stored in the logs
                  subdirectory.

-log:xyz          Enable the logfile, using xyz as the filename.

-nolog            Disable the logfile (if it is enabled by default).

-putthrottle:nn   Set the minimum time (in seconds) the bot will wait between
-pt:n             saving pages.

-verbose          Have the bot provide additional output that may be useful in
-v                debugging.
s   import %s as modules   utf-8t   docuReplacementss   
u   Sorry, no help available for %s(   R  RY   R  R   RH   t
   globalHelpRE   t   moduleR   R  t   helpTextRv   R  R|  R%  R&  Rc   R1   (   R  R  R  R&  R%  (    (    R   R  p  s$    (
 #c    	      C   s  xt  ot i   \ } } }  } } } } | d j o d Sn y# | i | |  | | |  d } Wn t j
 o	 } n X| d j	 o | | |  q n t | t  o! t d | i   | i f  q t | t  o! t d | i   | i f  q t | t  o t d | i    q t | t  o t d | i    q | d j	 o< t i t i     } t d | i   d i |  f  q q Wd S(   sT   
    Daemon that takes pages from the queue and tries to save them on the wiki.
    Nu/   Saving page [[%s]] prevented by spam filter: %su   Saving page [[%s]] failed: %su!   Page [[%s]] is locked; not saved.u1   Page [[%s]] not saved; sysop privileges required.u   Saving page [[%s]] failed:
%sR   (   R5   R*  R   R
  R1  R2  R3  R4  R   R5  R$   R0  R  RQ  R  R   RE   R*   R   R   t   messageR   R   RR  RS  RY   RT  t   tbR  (	   R2  R   R3  R  R5  R  R1  R
  R4  (    (    R   t	   async_put  s2      !
!!R  s
   Put-Threadc           C   s   t  i   d S(   s   This should be run when a bot does not interact with the Wiki, or
       when it has stopped doing so. After a bot has run stopme() it will
       not slow down other bots any more.
    N(   R   R  (    (    (    R   t   stopme  s     c          C   s  t  i   d j oF d k } | i d t  i   t i  } t d t  i   | f  n t  i d  x t
 i   o y t
 i d  Wqi t j
 ol t d t  i   | i d t  i   t i  f d d g d	 d
 g d
  }  |  d	 d g j o d Sqqi Xqi Wt i   d S(   sg   Wait for the page-putter to flush its queue;
       called automatically upon exiting from Python.
    i    Nt   secondss<   Waiting for %i pages to be put. Estimated time remaining: %si   uT   There are %i pages remaining in the queue. Estimated time remaining: %s
Really exit?t   yesR;  R  R  R  (   NNNNNNN(   R*  t   qsizeRA  t	   timedeltaRk   Ra  t	   remainingRE   R0  R$   R-  t   isAliveR  RP  R  R  R   R  (   R  RA  R  (    (    R   t   _flush  s      	 /c         C   s   d  k  } t |   }  t |  } t t |  i d d   } d |  | | i   f } | i d d  i d d  } t	 | d  } | i d	 |  y | i | i d
   Wn  t j
 o | i |  n X| i   t d |  | | f  d  S(   Nu   :u   _s   %s_%s__%s.dumpR   Ra   R    RW  t   wbu   Error reported: %s

t   utf8u+   ERROR: %s caused error %s. Dump %s created.(   R   R   RC   R  R  R   Rc   t   asctimet   filenamet   fileR;  R  Rf  R\   R[  R  RE   (   RC   R   R  Rf  R;  R   R  (    (    R   Rb    s    	
R8  c           B   s   t  Z d Z RS(   Ns   PythonWikipediaBot/1.0(   R   R   R  (    (    (    R   R8    s   s
   login-datas   cookies.lwpt   __main__s   Pywikipediabot %ss	   Python %s(   R   t
   __future__t
   generatorst   __version__R?  RY   Rl  RQ  R^   RR  R   R{  t   QueueR  R/   R<  Ro  R^  t   localet   xml.saxR\  t   xml.sax.handlerR  R  R-   Rk   R7  RU  R   R  t	   setlocalet   LC_ALLR   t	   NameErrort   setst   SetR  R5   R  RH   R"   R   RQ  R   R   R   R	   R
   R   R   R   R   R   R   R   R   R   R   R   R]  R_  R`  t   SaxErrorR   R6   t   objectR   R  RL  R   R   Rx  Ry  Rz  R  R  R$   Rz  R   R  R  R  R  R   R  R  R  R  R   RC  RL   R  R,   R  R)   R  R  R  R  R%   R  R  R  R  R  R   Rc  R  t   userinterfacet   uiModulet   UIRz  R   R?   R  R;  R  Rp  Rd   R  RQ  R?  Rd  Rk  R  R  R  Rq  t   LockRu  Rw  R{  RE   Ry  R~  R  R  R  R*  R  t   ThreadR-  t   setNamet	   setDaemonR  R  t   atexitt   registerRb  R  R  R   Ra  t   FancyURLopenerR8  Rb  Rg  t	   cookielibt
   COOKIEFILEt   LWPCookieJart   cjt   isfilet   loadt   HTTPPasswordMgrWithDefaultRealmt   passmanRA   R   t   add_passwordt   HTTPBasicAuthHandlert   authhandlerRN  t   HTTPCookieProcessorRI  t   install_openerR   R  t   doctestR  t   testmod(w   R  R   Rx  R  RQ  R  R\  R   R  R  R  Rb  R  R~  R{  R  Rl  R  Rk   Rk  RU  R{  R,   RE   R)   R  R   R   R  R  R  Rd  R   RC  R6   R  R   R   R  R^   Rw  R/   R  R8  R^  R  Rz  R  R   R  Rz  R  R  Ro  Ry  R<  R   RQ  R   RR  R  R  Ru  R   R   R7  R?  R*  R   R  R   R  R
   R  R  R   R?  R  R  R  R-  R   R  R   R  R  R-   R  R  RI  Rz  Rq  R  R  RL   R  R%   R  R  RL  R	   R  Ry  R  R   Ra  R   R  R  Rg  RY   R  R   R   R  R  R   R   R   (    (    R   RY  k   s:  		-					

	       eJ		
	
e##5		)		0			
	%    o
			;			
	b		<	#	(		,	%				
	 0
