;ò £Ù½Fc@sXdZdZdkZdkZdkZdkZdkZdkZdkZdk Z ydk l Z Wn e j odk l Z nXdklZeaeaeaeidƒZead„Zd„Zd„Zhd d <d d Z?dZ@e;iAZBe=iCƒZDnEei:d2jo(dkEZEeEi?Z?eEi@Z@eEiBZBn eFd3ƒ‚ei:d1jod4„ZGd5„ZHn'ei:d2jod6„ZGd7„ZHndS(8sG Tools module The swiss army knife for all things pyblosxom @var month2num: A dict of literal months to its number format @var num2month: A dict of number month format to its literal format @var MONTHS: A list of valid literal and numeral months @var VAR_REGEXP: Regular expression for detection and substituion of variables s$Revision: 1099 $N(sescape(s plugin_utilsu-(?Ossdonefunccs|o|dˆdjS(Nsmtimei(sxsMT(sx(sMT(s./Pyblosxom/tools.pysPss defaultfunccCs|S(N(sx(sx((s./Pyblosxom/tools.pysQsN(srequestsgetDatasdatas setdefaultsfilestat_cacheshas_keysfilenamesargdictsstatsST_MTIMEsMTs run_callbacksosstimes localtimes timetuple(srequestsfilenamesfilestat_cachesMTsargdicts timetuplesdata((sMTs./Pyblosxom/tools.pysfilestat3s"   (    cCs<x1|D])}tii|d|ƒo|SqqWtSdS(sŒ Takes in a filepath and a list of extensions and tries them all until it finds the first extension that works. @param extensions: the list of extensions to test @type extensions: list of strings @param filepath: the complete file path (minus the extension) to test @type filepath: string @return: the extension that was successful or None @rtype: string s.N(s extensionssextsosspathsisfilesfilepathsNone(s extensionssfilepathsext((s./Pyblosxom/tools.pyswhat_ext^s  cCs`| odSnt|ƒdjo*|iƒo|idƒp |idƒodSndSdS(s… Checks to see if the string is likely to be a year or not. In order to be considered to be a year, it must pass the following criteria: 1. four digits 2. first two digits are either 19 or 20. @param checks: the string to check for "year-hood" @type checks: string @return: 1 if checks is likely to be a year or 0 if it is not @rtype: boolean iis19s20iN(schecksslensisdigits startswith(schecks((s./Pyblosxom/tools.pysis_yearrs @cCs`y"t|tƒtƒ|gƒ}Wntj o tSnXyt|ƒ|SWn tSnXdS(s† Imports modules for modules that can only be determined during runtime. @param modulename: The base name of the module to import from @type modulename: string @param name: The name of the module to import from the modulename @type name: string @returns: If successful, returns an imported object reference, else C{None} @rtype: object N( s __import__s modulenamesglobalsslocalssnamesmodules ImportErrorsNonesvars(s modulenamesnamesmodule((s./Pyblosxom/tools.pys importname‰s" ii cCs†dk}dk}|i|i}g}|i||ƒ}d}x2||jo$|i |i |ƒƒ|d7}qCWdi |ƒSdS(sn Generate a random string Tool to generate a random string between C{minlen} to C{maxlen} characters. @param minlen: The minimum length the string should be @type minlen: integer @param maxlen: The maximum length the string could be @type maxlen: integer @returns: A string containing random characters @rtype: string Niis(srandomsstringsletterssdigitsscharssrandstrsrandintsminlensmaxlens randstr_sizesxsappendschoicesjoin(sminlensmaxlensstringscharssrandoms randstr_sizesrandstrsx((s./Pyblosxom/tools.pysgenerateRandStr¢s cCs|S(N(sx(sxsy((s./Pyblosxom/tools.pys¾scCsdS(Ni((sx((s./Pyblosxom/tools.pys¿scCsti|ƒ}t}xA|D]9}||ƒ}||ƒdjoPn|||ƒ}qWt |ƒo||ƒdjo||ƒSn|SdS(s£ Executes a callback chain on a given piece of data. passed in is a dict of name/value pairs. Consult the documentation for the specific callback chain you're executing. Callback chains should conform to their documented behavior. This function allows us to do transforms on data, handling data, and also callbacks. The difference in behavior is affected by the mappingfunc passed in which converts the output of a given function in the chain to the input for the next function. If this is confusing, read through the code for this function. @param chain: the callback chain to run @type chain: string @param input: data is a dict filled with name/value pairs--refer to the callback chain documentation for what's in the data dict. @type input: dict @param mappingfunc: the function that maps output arguments to input arguments for the next iteration. It must take two arguments: the original dict and the return from the previous function. It defaults to returning the original dict. @type mappingfunc: function @param donefunc: this function tests whether we're done doing what we're doing. This function takes as input the output of the most recent iteration. If this function returns true (1) then we'll drop out of the loop. For example, if you wanted a callback to stop running when one of the registered functions returned a 1, then you would pass in: donefunc=lambda x:x . @type donefunc: function @param defaultfunc: if this is set and we finish going through all the functions in the chain and none of them have returned something that satisfies the donefunc, then we'll execute the defaultfunc with the latest version of the input dict. @type defaultfunc: function @returns: the transformed dict @rtype: dict iN( s plugin_utilssget_callback_chainschainsNonesoutputsfuncsinputsdonefuncs mappingfuncscallables defaultfunc(schainsinputs mappingfuncsdonefuncs defaultfuncsfuncsoutput((s./Pyblosxom/tools.pys run_callback½s3  cCsd„} gi} |iƒD]} | d| || fƒq~ } | |ƒdi| ƒ|}t i i||ƒ}t i i|ƒ ot i|ƒnt i i|ƒ otd|ƒ‚nt i i|||ƒ}t|dƒ} | i|ƒ| iƒt i|||fƒdS(sl Creates a new entry in the blog. This is primarily used by the testing system, but it could be used by scripts and other tools. @param datadir: the directory of the datadir where the blog entries are stored. @type datadir: string @param category: the category of the entry. @type category: string @param filename: the name of the blog entry (filename and extension). @type filename: string @param mtime: the mtime for the entry (seconds since the epoch). @type mtime: float @param title: the title for the entry. @type title: string @param metadata: any metadata for this entry. @type metadata: dict @param body: the content of the entry. @type body: string @raises IOError: if the datadir + category directory exists, but isn't a directory. cCs%|idƒ o |dSn|SdS(Ns (sssendswith(ss((s./Pyblosxom/tools.pysaddcr2s s#%s %ss s!%s exists, but isn't a directory.swN(saddcrsappends_[1]smetadataskeysskeys metadatalinesstitlesjoinsbodysentrysosspathsdatadirscategorysdsexistssmakedirssisdirsIOErrorsfilenamesfnsopensfswritesclosesutimesmtime(sdatadirscategorysfilenamesmtimestitlesmetadatasbodysentrysdsfsaddcrs_[1]skeys metadatalinessfn((s./Pyblosxom/tools.pys create_entrys ;  cCs|iƒ}|iddƒ}| o_|iƒ}|iddƒ}|iddƒ}t d|ƒ}|i ||ƒ}||d|D]6}|idd|dƒ|i|d|dƒqDWx&|D]}t||d|d ƒq…WdS( s6 This is a utility function that allows plugins to easily update statically rendered entries without going through all the rigamarole. First we figure out whether this blog is set up for static rendering. If not, then we return--no harm done. If we are, then we call render_url for each static_flavour of the entry and then for each static_flavour of the index page. @param cdict: the config.py dict @type cdict: dict @param entry_filename: the filename of the entry (ex. /movies/xmen2) @type entry_filename: string s static_dirsNsstatic_flavoursshtmls/indexs.ii( scdictsgets staticdirsstaticflavourssrendermesmemsappendsentry_filenamesrender_url_statically(scdictsentry_filenames staticdirsstaticflavourssmemsrenderme((s./Pyblosxom/tools.pysupdate_static_entrylscCs»|iddƒ}t|||ƒ}|idƒti i |ti |ƒ}ti i ti i|ƒƒ otiti i|ƒƒnt|dƒ}|i|iƒƒ|iƒdS(Ns static_dirsisw(scdictsgets staticdirs render_urlsurlsqsresponsesseeksosspathsnormpathssepsfnsisdirsdirnamesmakedirssopensfswritesreadsclose(scdictsurlsqs staticdirsfsresponsesfn((s./Pyblosxom/tools.pysrender_url_staticallys  cCsó|iddƒ}| otdƒ‚ndkl}hdd<dd<d d <d |<d |<d |d|<d |<dd<dd<dd<dti <dt <}hdd<}||||ƒ}|idtƒ|iƒSdS(sî Takes a url and a querystring and renders the page that corresponds with that by creating a Request and a PyBlosxom object and passing it through. It then returns the resulting Response. @param cdict: the config.py dict @type cdict: dict @param pathinfo: the path_info string. ex: /dev/pyblosxom/firstpost.html @type pathinfo: string @param querystring: the querystring (if any). ex: debug=yes @type querystring: string @returns: Response s static_dirss,You must set static_dir in your config file.(s PyBlosxomsHTTP_USER_AGENTsstatic renderersREQUEST_METHODsGETs HTTP_HOSTs localhosts PATH_INFOs QUERY_STRINGs REQUEST_URIs?s HTTP_REFERERs REMOTE_ADDRs SCRIPT_NAMEs wsgi.errorss wsgi.inputsSTATICisstaticN(scdictsgets staticdirs Exceptions pyblosxoms PyBlosxomspathinfos querystringssyssstderrsNonesenvsdataspsrunsTrues getResponse(scdictspathinfos querystrings PyBlosxoms staticdirspsenvsdata((s./Pyblosxom/tools.pys render_urls }swhatevers LogFiltercBs#tZdZed„Zd„ZRS(sk Filters out messages from log-channels that are not listed in the log_filter config variable. cCs$|tjo g}n||_dS(sÕ Initializes the filter to the list provided by the names argument (or [] if names is None). @param names: list of name strings to filter out @type names: list of strings N(snamessNonesself(sselfsnames((s./Pyblosxom/tools.pys__init__ås  cCs#|i|ijodSndSdS(Nii(srecordsnamesselfsnames(sselfsrecord((s./Pyblosxom/tools.pysfilterñs(s__name__s __module__s__doc__sNones__init__sfilter(((s./Pyblosxom/tools.pys LogFilteràs  cCsHt} |tjoŽtiddƒ}tidƒ} | i i }| i d}d}x5tidgƒD]!}|i|ƒo |}PqfqfWtiddƒ}n/t} tiitii|ƒƒd }d }ti|ƒ}d |_d ||f}|tj o;|djotitiƒ}nm|d jo$tid jo d}qYd}nyti |ƒ}Wn%t!j otitiƒ}nX|o d} nd} |i#ti$| ƒƒ|i%|ƒt&t|i'ƒƒ} |i)| ƒ| o:tidtƒ} | ot+| ƒ}|i-|ƒq2ntt|=2.3, L{Pyblosxom._logging.Logger} for Python <2.3 slog_filesstderris__name__ss plugin_dirss log_levelswarningisdebugs%s|%ssNONEsntsNULs /dev/nulls1%(asctime)s [%(levelname)s] %(name)s: %(message)ss(%(asctime)s [%(levelname)s]: %(message)ss log_filterN(.sFalsescustom_log_fileslog_filesNones_configsgetssyss _getframesfsf_codes co_filenamesfilenames f_globalssmoduleslog_namespaths startswiths log_levelsTruesosssplitextsbasenamesloggings getLoggersloggers propagateskeys_loghandler_registrys StreamHandlersstderrshdlrsnames FileHandlersIOErrorsfmtr_ss setFormatters Formatters addHandlersgetattrsuppers int_levelssetLevels log_filters LogFilterslfilters addFilter(slog_fileslog_namesmodulespathshdlrs log_levelsfilenamesloggerskeysfmtr_ss int_levelsfscustom_log_files log_filterslfilter((s./Pyblosxom/tools.pys getLoggerös\     "         cCst|ƒ}|idƒdS(sÒ Logs an exception to the given file. Uses the system-wide log_file as defined in config.py if none is given here. @param log_file: optional, the file to log to @type log_file: C{str} sException occured:N(s getLoggerslog_fileslogs exception(slog_fileslog((s./Pyblosxom/tools.pys log_exceptionQs icCsfti|ƒ}|id}|ii}|i }|ii }t |ƒ}|id||||ƒdS(s‘ Logs some info about the calling function/method. Useful for debugging. Usage:: import tools tools.log_caller() # logs frame 1 tools.log_caller(2) tools.log_caller(3, log_file="/path/to/file") @param frame_num: optional, index of the frame @type frame_num: C{int} @param log_file: optional, the file to log to @type log_file: C{str} s__name__s8 module: %s filename: %s line: %s subroutine: %sN(ssyss _getframes frame_numsfs f_globalssmodulesf_codes co_filenamesfilenamesf_linenoslinesco_namessubrs getLoggerslog_fileslogsinfo(s frame_numslog_filessubrslogsfsmodulesfilenamesline((s./Pyblosxom/tools.pys log_caller^s      sntsposixs3PortaLocker only defined for nt and posix platformscCs2ti|iƒƒ}ti||ddtƒdS(Niiÿÿ(s win32files_get_osfhandlesfsfilenoshfiles LockFileExsflagss __overlapped(sfsflagsshfile((s./Pyblosxom/tools.pyslock´scCs/ti|iƒƒ}ti|ddtƒdS(Niiÿÿ(s win32files_get_osfhandlesfsfilenoshfiles UnlockFileExs __overlapped(sfshfile((s./Pyblosxom/tools.pysunlock¸scCsti|iƒ|ƒdS(N(sfcntlsflocksfsfilenosflags(sfsflags((s./Pyblosxom/tools.pyslock½scCsti|iƒtiƒdS(N(sfcntlsflocksfsfilenosLOCK_UN(sf((s./Pyblosxom/tools.pysunlockÀs(Is__doc__s __revision__ssgmllibsresosstimesos.pathsstatssyssurllibsxml.sax.saxutilssescapes ImportErrorscgis Pyblosxoms plugin_utilssNones month2nums num2monthsMONTHSscompiles VAR_REGEXPs_configs initializescleanups parse_argssQUOTESs escape_textsurlencode_texts VariableDicts SGMLParsersStrippersReplacersparseswalksWalks__walk_internalsfilestatswhat_extsis_years importnamesgenerateRandStrs run_callbacks create_entrys get_cachesupdate_static_entrysrender_url_staticallys render_urlsFalses_use_custom_loggersloggings_loggings_loghandler_registrysobjects LogFilters getLoggers log_exceptions log_callersnameswin32cons win32files pywintypessLOCKFILE_EXCLUSIVE_LOCKsLOCK_EXsLOCK_SHsLOCKFILE_FAIL_IMMEDIATELYsLOCK_NBs OVERLAPPEDs __overlappedsfcntls RuntimeErrorslocksunlock(3s __overlappedsfcntlsis_yearslocksgenerateRandStrsfilestatswalksparses win32filesescapesLOCK_EXs VAR_REGEXPssgmllibsupdate_static_entrys __revision__swhat_exts VariableDictsurllibsrescleanupsLOCK_NBswin32cons get_cachesLOCK_SHsurlencode_texts importnamesstats__walk_internals create_entrys escape_texts log_exceptions_use_custom_loggerssyssQUOTESs run_callbacks initializesloggings pywintypess render_urls parse_argss plugin_utilssunlocksWalks getLoggersrender_url_staticallystimesReplacersoss LogFilters log_callersStripper((s./Pyblosxom/tools.pys?s–          =    x$J > % +   T ?  !  5  [ D