o uaL@sUdZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl m Z ddl m Z ddlmZddlmZmZddlmZmZmZmZmZmZmZmZmZmZmZmZmZddl m!Z!m"Z"m#Z#m$Z$m%Z%dd l&m'Z'dd l(m)Z)m*Z*m+Z+dd l,m-Z-dd l.m/Z/dd l0m1Z1m2Z2m3Z3m4Z4ddl5m6Z6ddl7m8Z8m9Z9m:Z:m;Z;ddlZ>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEddlFmGZGerddlHmIZIe/JeKZLeMdZNeeOd<eMdZPeeOd<deQdeQdeQfddZRdeQdeQfddZS d~d eQd!eeGd"fdeeQfd#d$ZTd%eeQeQfd&eQdeQfd'd(ZUGd)d*d*eVZWdd,d-ZXdd.d/ZYGd0d1d1eVZZd2Z[d3d4deQfd5d6Z\d7eQd8eQdeQfd9d:Z]eMd;Z^Gdd?d?Z`d@eQdAeadeeafdBdCZbdDeQdEeQdeQfdFdGZcdHeQdIeQdeeQeQffdJdKZddLeadMeQdNeQdeeQfdOdPZedMeQdNeQdeeQfdQdRZfddTeadeQfdUdVZgddWeQdXeQdefdYdZZhd[eQdeeeQeQffd\d]Zid^eQdeQfd_d`ZjdaeQdekfdbdcZlddedeQfdedfZmdgemfdhedieQdjeQdkeegeQfdef dldmZndgddemfdhedieQdjeQdneadoeadkeegeQfdefdpdqZoGdrdsdsepZqGdtduduZrdvesdeQfdwdxZtdyeQdesfdzd{Zudefd|d}ZvdS)z sphinx.util ~~~~~~~~~~~ Utility functions for Sphinx. :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. N)datetime) import_module)pathmktimestrptime) IO TYPE_CHECKINGAnyCallableDictIterableIteratorListOptionalPatternSetTupleType) parse_qsl quote_plus urlencodeurlsplit urlunsplit)RemovedInSphinx50Warning)ExtensionErrorFiletypeNotFoundErrorSphinxParallelError)__)logging)boldcolorize strip_colorsterm_width_line) patfilter)caption_ref_reexplicit_title_renested_parse_with_titlessplit_explicit_title) SEPcopyfile copytimes ensuredir make_filenamemovefilemtimes_of_filesos_path relative_uri) PathMatcher)Sphinxz\s+ws_rez(?P.+)://.*url_re basedocnamedocnamereturncCs ttd|d|ddS)N/z..) posixpathnormpathjoin)r6r7r>6/usr/lib/python3/dist-packages/sphinx/util/__init__.py docname_join8s r@filepathcCs|tjjt}td|S)z+Normalize path separator and unicode stringNFC)replaceosrsepr) unicodedata normalize)rAnewpathr>r>r?path_stabilize=s rIr>dirnameexclude_matchers.c #stt|}t|d}tj|ddD]S\}}||dtfddD}tfdd|D}|D]fdd |D}fd d |D}q9tfd d|Ddd<t|D]\}}|VqaqdS) z}Get all file names in a directory, recursively. Exclude files and dirs matching some matcher in *exclude_matchers*. r:T) followlinksNc3 |] }tt|VqdSNrIrr=).0dn relativerootr>r? Pz%get_matching_files..c3rMrNrO)rPfnrRr>r?rTRrUcg|] }|ds|qSr:r>rPentrymatcherr>r? Uz&get_matching_files..crWrXr>rYr[r>r?r]Vr^c3s|] \}}|VqdSrNr>)rPi_)dirsr>r?rTXs)rr<abspathlenrDwalk enumeratesorted) rJrKdirlenrootfilesqdirsqfilesr_filenamer>)rar\rSr?get_matching_filesCs&    rm source_suffixrlcCs,|D]\}}||r|pdSqt)Nrestructuredtext)itemsendswithr)rnrlsuffixfiletyper>r>r? get_filetype^s   rtc@seZdZdZdddZdededefdd Zdeddfd d Zd eed e ee eee ffddfddZ deefddZ deeddfddZdS)FilenameUniqDictz A dictionary that automatically generates unique names for its keys, interpreted as filenames, and keeps track of a set of docnames they appear in. Used for images and downloadable files in the environment. r8NcCs t|_dSrN)set _existingselfr>r>r?__init__ms zFilenameUniqDict.__init__r7newfilecCs||vr||d|||dSt|}t|\}}d}||jvr6|d7}d|||f}||jvs&|h|f||<|j||S)Nrr:z%s%s%s)addrbasenamesplitextrw)ryr7r{ uniquenamebaseextr_r>r>r?add_fileps     zFilenameUniqDict.add_filecCs>t|D]\}\}}|||s||=|j|qdSrN)listrpdiscardrw)ryr7rldocsuniquer>r>r? purge_doc~s  zFilenameUniqDict.purge_docdocnamesothercC8|D]\}\}}|t|@D]}|||qqdSrNrprvr)ryrrrlrrdocr>r>r? merge_other zFilenameUniqDict.merge_othercCs|jSrNrwrxr>r>r? __getstate__szFilenameUniqDict.__getstate__statecC ||_dSrNr)ryrr>r>r? __setstate__ zFilenameUniqDict.__setstate__r8N)__name__ __module__ __qualname____doc__rzstrrrrr rr rrrr>r>r>r?rugs .rucKBz tj|fi|WSty tj|fi|ddiYSw)a3Wrapper around hashlib.md5 Attempt call with 'usedforsecurity=False' if we get a ValueError, which happens when OpenSSL FIPS mode is enabled: ValueError: error:060800A3:digital envelope routines:EVP_DigestInit_ex:disabled for fips See: https://github.com/sphinx-doc/sphinx/issues/7611 usedforsecurityF)hashlibmd5 ValueErrordatakwargsr>r>r?rs   rcKr)zWrapper around hashlib.sha1 Attempt call with 'usedforsecurity=False' if we get a ValueError See: https://github.com/sphinx-doc/sphinx/issues/7611 rF)rsha1rrr>r>r?rs  rc@sfeZdZdZdededefddZdeddfdd Zd eed eee eee ffddfd d Z dS) DownloadFileszA special dictionary for download files. .. important:: This class would be refactored in nearly future. Hence don't hack this directly. r7rlr8cCsX||vrt|}d|tj|f}t|f||<||d|||dS)Nz%s/%srr:)rencode hexdigestrDrr}rvr|)ryr7rldigestdestr>r>r?rs  zDownloadFiles.add_fileNcCs2t|D]\}\}}|||s||=qdSrN)rrpr)ryr7rlrrr>r>r?rs  zDownloadFiles.purge_docrrcCrrNr)ryrrrlrrr7r>r>r?rrzDownloadFiles.merge_other) rrrrrrrrr rr rr>r>r>r?rs  2rz# Sphinx version: %s # Python version: %s (%s) # Docutils version: %s %s # Jinja2 version: %s # Last messages: %s # Loaded extensions: appr3c Csddl}ddl}ddl}ddl}td}t|tr!d|j}nt }t dd\}}d} |dur>d d d |j D} t|t|j|||j|j|j| f|dur~|jD]} t| jd d } | jd kr}t|d| j| j| fq`t||t||S)z;Save the current exception's traceback in a temporary file.rNr:z(Error in parallel process) z.logz sphinx-err- css |] }dt|VqdS)z# %sN)r"strip)rPsr>r>r?rTs  z!save_traceback..__file__unknownbuiltinz# %s (%s) from %s )platformdocutilsjinja2sphinxsysexc_info isinstancer traceback format_exctempfilemkstempr= messagelogrDwrite _DEBUG_HEADER__display_version__python_versionpython_implementation __version____version_details__r extensionsvaluesgetattrmoduleversionnameclose) rrrrrexc exc_formatfdr last_msgsrmodfiler>r>r?save_tracebacksL       rmodname attributecCsB|durdSt|}|}|dD] }|rt||}qt|ddS)N.r)rsplitr)rrrvalueattrr>r>r?get_full_modnames  rzcoding[:=]\s*([-\w.]+)c@s<eZdZdZdeddfddZdedeeeffdd Z dS) UnicodeDecodeErrorHandlerz8Custom error handler for open() that warns and replaces.r7r8NcCrrN)r7)ryr7r>r>r?rzrz"UnicodeDecodeErrorHandler.__init__errorcCs|jdd|j}|jd|j}|dkrt|j}|jdd|jd}tjtd|j|d|jd|j|j|j d|j|j ||j |fdd |j fS) N rr:z5undecodable source characters, replacing with "?": %rs>>>s<<<)location?) objectrfindstartfindrccountloggerwarningrendr7)ryr linestartlineendlinenor>r>r?__call__s    z"UnicodeDecodeErrorHandler.__call__) rrrrrrzUnicodeDecodeErrorrintrr>r>r>r?rsrc@sBeZdZdZdededdfddZdeddfd d Zd d d ZdS)Teez2 File-like object writing to two streams. stream1stream2r8NcCs||_||_dSrN)rr)ryrrr>r>r?rz*s z Tee.__init__textcCs|j||j|dSrN)rrr)ryrr>r>r?r.s z Tee.writecCs4t|jdr |jt|jdr|jdSdS)Nflush)hasattrrrrrxr>r>r?r2s   z Tee.flushr) rrrrrrzrrrr>r>r>r?r&s rspectotalc Cst}|d}|D]d}zO|d}ddg|krtt|dkr.|t|ddn,t|dkrXt|dp:d}t|dpEt||}||krMt|t |d|ntWq t yn}ztd||d}~ww|S) z_Parse a line number spec (such as "1,2,4-6") and return a list of wanted line numbers. ,-rr:rzinvalid line number spec: %rN) rrrrrcappendrmaxextendrange Exception) rrrppartspartbegendrrrr>r>r? parselinenos9s,    rstringencodingcCs`tjdtddt|tr.z|r||}W|S|}W|Sty-|d}Y|Sw|S)z2Forcibly get a unicode string out of a bytestring.zforce_decode() is deprecated.r stacklevellatin1)warningswarnrrbytesdecode UnicodeError)rrr>r>r? force_decodeTs    r rtcCsJtjdtdd||}|dkr!|d|||t|dfSd|fS)zESimilar to str.rpartition from 2.5, but doesn't return the separator.zrpartition() is now deprecated.rrrNr)rrrrrc)rr r_r>r>r? rpartitiones   r ntypercCsDdd|d|dD}tdd|D|kr td||f|S)z@Split an index entry into a given number of parts at semicolons.cSsg|]}|qSr>)r)rPxr>r>r?r]pszsplit_into..;r:css|]}|rdVqdS)r:Nr>)rPrr>r>r?rTqszsplit_into..invalid %s index entry %r)rsumr)rrrrr>r>r? split_intonsrcCs|dkrz tdd|}W|Stytdd|}Y|Sw|dkr*tdd|}|S|dkr6tdd|}|S|dkrBtdd|}|S|dkrNtdd|}|Std ||f) Nsinglerr:pairtripleseeseealsor)rr)rrresultr>r>r?split_index_msgvs*       rr:rcCsHt\}}}g}t|}||| d7}|t||7}d|S)z?Format an exception with traceback, but only the last x frames.Nr)rrr format_tbformat_exception_onlyr=)rtypvaltbrestbresr>r>r?format_exception_cut_framess   r$objnamesourcec Csz0|d}|d}t|}|D]}|d|7}zt||}Wqty-t|}Yqw|WSttfyR}z|rFtd||f||td|||d}~ww)z!Import python object by qualname.rrz#Could not import %s (needed for %s)zCould not import %sN)rpoprrAttributeError ImportErrorr)r%r&objpathrobjrrr>r>r? import_objects0     r,rc Cs|d}t|dD]O\}}zd|d|}t|Wq tyQ|d|drFd|d|dd||ddfYSdd|fYStyYYq w|dfS)aSplit full qualified name to a pair of modname and qualname. A qualname is an abbreviation for "Qualified name" introduced at PEP-3155 (https://www.python.org/dev/peps/pep-3155/). It is a dotted path name from the module top-level. A "full" qualified name means a string containing both module name and qualified name. .. note:: This function actually imports the module to check its existence. Therefore you need to mock 3rd party modules if needed before calling this function. rr:Nr)rrer=rr) IndexError)rrr_rrr>r>r?split_full_qualified_names   4 r.uricCshtt|}|ddd|d<t|dd|d<tddt|dD}t||d<t|S) Nr:idnaasciirr9css |] \}}||fVqdSrN)r)rPqvr>r>r?rTszencode_uri..r)rrrr rrrr)r/rqueryr>r>r? encode_uris  r5urlcCs|rd|vrdSdS)zCheck *url* is URL or not.z://TFr>)r6r>r>r?isurls r7chunkcCsBt|ttfrt|dkrt|dSd|d|dfSt|S)Nr:rz%s .. %sr)rrtuplercr)r8r>r>r? display_chunks   r: darkgreeniterablesummarycolorstringify_funcccspd}|D]%}|dkrtjt|ddd}tj|||ddtjddd|Vq|dkr6tddSdS)NrTnonlr:)r>rA r)rinfor )r<r=r>r?litemr>r>r?old_status_iteratorsrFlength verbosityc cs|dkrt||||EdHdSd}t|}|D]+}|d7}d|d||t|||f}|r6|d7}nt|}tj|dd|Vq|dkrPtddSdS) Nrr:z %s[%3d%%] %sdrTr@r)rFr r!r#rrC) r<r=r>rGrHr?rDrErr>r>r?status_iterators"  rJc@s eZdZdS)SkipProgressMessageN)rrrr>r>r>r?rKsrKc@sXeZdZdeddfddZdddZdeed ed ede fd d Z d e de fddZ dS)progress_messagemessager8NcCrrN)rM)ryrMr>r>r?rz rzprogress_message.__init__cCstjt|jddddS)Nz... Tr@)rrCr rMrxr>r>r? __enter__szprogress_message.__enter__exc_type exc_valuercCsVt|trttd|jrtj|jdS|r"ttddSttddS)NskippedTfaileddoneF)rrKrrCrargs)ryrOrPrr>r>r?__exit__s  zprogress_message.__exit__fcs*tdtdtdtffdd }|S)NrTrr8cs6|i|WdS1swYdSrNr>)rTrrVryr>r?wrapper s $z*progress_message.__call__..wrapper) functoolswrapsr )ryrVrXr>rWr?rszprogress_message.__call__r) rrrrrzrNrrr boolrUr rr>r>r>r?rL s   rLepochcCs,ddlm}t|}d}|||dddS)z)Convert datetime format epoch to RFC1123.r)format_datetimezEEE, dd LLL yyyy hh:mm:ssen)localez GMT) babel.datesr]r fromtimestamp)r\r]dtfmtr>r>r?epoch_to_rfc1123(s  rdrfc1123cCstt|dS)Nz%a, %d %b %Y %H:%M:%S %Zr)rer>r>r?rfc1123_to_epoch1srfcsdddgdddgddgd d gd d gd dgddgddgddgddgddgddgddgddgg}dd d!d"gd#d$d%gd&d'gg}d/d)td*td+tffd,d- |}|}td.|||fS)0N:AZr`azÀÖØöøu˿uͰuͽuͿu῿u‌u‍u⁰u↏uⰀu⿯u、u퟿u豈u﷏uﷰu�u𐀀u󯿿z\-z\.09·ùuͯu‿u⁀|entriessplitterr8csBg}|D]}t|tr|d|dq||q||S)Nz[%s]r)rrrr=)rurvresultsrZconvertr>r?ryCs    z xmlname_checker..convertz (%s)(%s|%s)*)rt)r rrecompile)name_start_chars name_charsstart_chars_regexname_chars_regexr>rxr?xmlname_checker5s  r)r>)rrXrN)wrrYrrDr;rzrrrrFrr importlibrrtimerrtypingrr r r r r rrrrrrr urllib.parserrrrrsphinx.deprecationr sphinx.errorsrrr sphinx.localer sphinx.utilrsphinx.util.consoler r!r"r#sphinx.util.matchingr$sphinx.util.nodesr%r&r'r(sphinx.util.osutilr)r*r+r,r-r.r/r0r1sphinx.util.typingr2sphinx.applicationr3 getLoggerrrr{r4__annotations__r5rr@rIrmrtdictrurrrrrr _coding_rerrrrr r rrr$r,r.r5r[r7r:rFrJrrKrLfloatrdrfrr>r>r>r?s    <    ,      *  %