__pycache__/__init__.cpython-36.opt-1.pyc000064400000000161147205126200014075 0ustar003 9f@sdS)Nrrr/usr/lib/python3.6/__init__.pys__pycache__/__init__.cpython-36.pyc000064400000000161147205126200013136 0ustar003 9f@sdS)Nrrr/usr/lib/python3.6/__init__.pys__pycache__/appdirs.cpython-36.opt-1.pyc000064400000044153147205126200014011 0ustar003 9ffW@sdZd1ZdjeeeZddlZddlZejddkZ e r>eZ ej j drddl Z e j ddZej drrd Zqej d rd Zqd Znej Zd2ddZd3ddZd4ddZd5ddZd6ddZd7ddZGdddeZddZdd Zd!d"Zd#d$Zed kryddlZeZWnnek rydd%l m!Z!eZWnBek r|yddl"Z#eZWnek rveZYnXYnXYnXe$d&kr~d'Z%d(Z&d8Z'e(d)ee%e&d*d+Z)x$e'D]Z*e(d,e*e+e)e*fqWe(d-ee%e&Z)x$e'D]Z*e(d,e*e+e)e*fqWe(d.ee%Z)x$e'D]Z*e(d,e*e+e)e*fq$We(d/ee%d d0Z)x$e'D]Z*e(d,e*e+e)e*fq^WdS)9zyUtilities for determining application-specific dirs. See for details and usage. .NjavaZWindowswin32ZMacdarwinZlinux2FcCstdkr^|dkr|}|rdpd}tjjt|}|r|dk rNtjj|||}qtjj||}nNtdkrtjjd}|rtjj||}n&tjdtjjd }|rtjj||}|r|rtjj||}|S) aJReturn full path to the user-specific data dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "roaming" (boolean, default False) can be set True to use the Windows roaming appdata directory. That means that for users on a Windows network setup for roaming profiles, this user data will be sync'd on login. See for a discussion of issues. Typical user data directories are: Mac OS X: ~/Library/Application Support/ Unix: ~/.local/share/ # or in $XDG_DATA_HOME, if defined Win XP (not roaming): C:\Documents and Settings\\Application Data\\ Win XP (roaming): C:\Documents and Settings\\Local Settings\Application Data\\ Win 7 (not roaming): C:\Users\\AppData\Local\\ Win 7 (roaming): C:\Users\\AppData\Roaming\\ For Unix, we follow the XDG spec and support $XDG_DATA_HOME. That means, by default "~/.local/share/". rN CSIDL_APPDATACSIDL_LOCAL_APPDATAFrz~/Library/Application Support/Z XDG_DATA_HOMEz~/.local/share)systemospathnormpath_get_win_folderjoin expandusergetenv)appname appauthorversionroamingconstr r/usr/lib/python3.6/appdirs.py user_data_dir-s&   rcs tdkrR|dkr}tjjtd}r|dk rBtjj||}qtjj|}ntdkrztjjd}rtjj|}nttjdtjjdd g}d d |j tjD}r|rtjj|fd d |D}|rtjj|}n|d }|So|rtjj||}|S)aiReturn full path to the user-shared data dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "multipath" is an optional parameter only applicable to *nix which indicates that the entire list of data dirs should be returned. By default, the first item from XDG_DATA_DIRS is returned, or '/usr/local/share/', if XDG_DATA_DIRS is not set Typical user data directories are: Mac OS X: /Library/Application Support/ Unix: /usr/local/share/ or /usr/share/ Win XP: C:\Documents and Settings\All Users\Application Data\\ Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) Win 7: C:\ProgramData\\ # Hidden, but writeable on Win 7. For Unix, this is using the $XDG_DATA_DIRS[0] default. WARNING: Do not use this on Windows. See the Vista-Fail note above for why. rNCSIDL_COMMON_APPDATAFrz/Library/Application SupportZ XDG_DATA_DIRSz/usr/local/sharez /usr/sharecSs g|]}tjj|jtjqSr)r r rrstripsep).0xrrr sz!site_data_dir..csg|]}tjj|gqSr)r rr)rr)rrrr sr) r r r rrrrrpathsepsplit)rrr multipathr pathlistr)rr site_data_dirds4  r%cCsXtdkrt||d|}n&tjdtjjd}|r>tjj||}|rT|rTtjj||}|S)aReturn full path to the user-specific config dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "roaming" (boolean, default False) can be set True to use the Windows roaming appdata directory. That means that for users on a Windows network setup for roaming profiles, this user data will be sync'd on login. See for a discussion of issues. Typical user data directories are: Mac OS X: same as user_data_dir Unix: ~/.config/ # or in $XDG_CONFIG_HOME, if defined Win *: same as user_data_dir For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. That means, by deafult "~/.config/". rrNZXDG_CONFIG_HOMEz ~/.config)rr)r rr rr rr)rrrrr rrruser_config_dirsr&cstd kr*t|}r|rtjj||}ndtjdd}dd|jtjD}rt|rbtjj|fdd|D}|rtjj|}n|d}|S) aReturn full path to the user-shared data dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "multipath" is an optional parameter only applicable to *nix which indicates that the entire list of config dirs should be returned. By default, the first item from XDG_CONFIG_DIRS is returned, or '/etc/xdg/', if XDG_CONFIG_DIRS is not set Typical user data directories are: Mac OS X: same as site_data_dir Unix: /etc/xdg/ or $XDG_CONFIG_DIRS[i]/ for each value in $XDG_CONFIG_DIRS Win *: same as site_data_dir Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False WARNING: Do not use this on Windows. See the Vista-Fail note above for why. rrZXDG_CONFIG_DIRSz/etc/xdgcSs g|]}tjj|jtjqSr)r r rrr)rrrrrr sz#site_config_dir..csg|]}tjj|gqSr)r rr)rr)rrrr sr)rr)r r%r r rrr"r!)rrrr#r r$r)rrsite_config_dirs  r'TcCstdkrd|dkr|}tjjtd}|r|dk rBtjj|||}ntjj||}|rtjj|d}nNtdkrtjjd}|rtjj||}n&tjdtjjd }|rtjj||}|r|rtjj||}|S) aReturn full path to the user-specific cache dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "opinion" (boolean) can be False to disable the appending of "Cache" to the base app data dir for Windows. See discussion below. Typical user cache directories are: Mac OS X: ~/Library/Caches/ Unix: ~/.cache/ (XDG default) Win XP: C:\Documents and Settings\\Local Settings\Application Data\\\Cache Vista: C:\Users\\AppData\Local\\\Cache On Windows the only suggestion in the MSDN docs is that local settings go in the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming app data dir (the default returned by `user_data_dir` above). Apps typically put cache data somewhere *under* the given dir here. Some examples: ...\Mozilla\Firefox\Profiles\\Cache ...\Acme\SuperApp\Cache\1.0 OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. This can be disabled with the `opinion=False` option. rNr FZCacherz~/Library/CachesZXDG_CACHE_HOMEz~/.cache)r r r rrrrr)rrropinionr rrruser_cache_dirs(! r)cCstdkr tjjtjjd|}nNtdkrLt|||}d}|rntjj|d}n"t|||}d}|rntjj|d}|r|rtjj||}|S)aReturn full path to the user-specific log dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "opinion" (boolean) can be False to disable the appending of "Logs" to the base app data dir for Windows, and "log" to the base cache dir for Unix. See discussion below. Typical user cache directories are: Mac OS X: ~/Library/Logs/ Unix: ~/.cache//log # or under $XDG_CACHE_HOME if defined Win XP: C:\Documents and Settings\\Local Settings\Application Data\\\Logs Vista: C:\Users\\AppData\Local\\\Logs On Windows the only suggestion in the MSDN docs is that local settings go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in examples of what some windows apps use for a logs dir.) OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA` value for Windows and appends "log" to the user cache dir for Unix. This can be disabled with the `opinion=False` option. rz~/Library/LogsrFZLogslog)r r r rrrr))rrrr(r rrr user_log_dir:s    r+c@sbeZdZdZdddZeddZedd Zed d Zed d Z eddZ eddZ dS)AppDirsz1Convenience wrapper for getting application dirs.NFcCs"||_||_||_||_||_dS)N)rrrrr#)selfrrrrr#rrr__init__os zAppDirs.__init__cCst|j|j|j|jdS)N)rr)rrrrr)r-rrrrws zAppDirs.user_data_dircCst|j|j|j|jdS)N)rr#)r%rrrr#)r-rrrr%|s zAppDirs.site_data_dircCst|j|j|j|jdS)N)rr)r&rrrr)r-rrrr&s zAppDirs.user_config_dircCst|j|j|j|jdS)N)rr#)r'rrrr#)r-rrrr's zAppDirs.site_config_dircCst|j|j|jdS)N)r)r)rrr)r-rrrr)s zAppDirs.user_cache_dircCst|j|j|jdS)N)r)r+rrr)r-rrrr+s zAppDirs.user_log_dir)NNFF) __name__ __module__ __qualname____doc__r.propertyrr%r&r'r)r+rrrrr,ms      r,cCs:ddl}dddd|}|j|jd}|j||\}}|S)zThis is a fallback technique at best. I'm not sure if using the registry for this guarantees us the correct answer for all CSIDL_* names. rNZAppDatazCommon AppDataz Local AppData)r rr z@Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders)_winregOpenKeyHKEY_CURRENT_USERZ QueryValueEx) csidl_namer4Zshell_folder_namekeydirtyperrr_get_win_folder_from_registrysr;cCsddlm}m}|jdt||dd}y`t|}d}x|D]}t|dkr:d}Pq:W|ryddl}|j|}Wnt k rYnXWnt k rYnX|S)Nr)shellconshellFT) win32com.shellr<r=SHGetFolderPathgetattrunicodeordwin32apiGetShortPathName ImportError UnicodeError)r7r<r=r9 has_high_charcrDrrr_get_win_folder_with_pywin32s$   rJcCsddl}dddd|}|jd}|jjjd|dd|d}x|D]}t|dkrBd }PqBW|r|jd}|jjj|j|dr|}|jS) Nr#)r rr iFr>T) ctypesZcreate_unicode_bufferwindllZshell32ZSHGetFolderPathWrCZkernel32ZGetShortPathNameWvalue)r7rNZ csidl_constbufrHrIZbuf2rrr_get_win_folder_with_ctypess"    rRc Csddl}ddlm}ddlm}|jjd}|jd|}|jj }|j dt |j |d|j j ||jj|jjd}d}x|D]} t| dkr~d }Pq~W|r|jd|}|jj } tj|||r|jj|jjd}|S) Nr)jna)rrIFr>T)arrayZcom.sunrSZcom.sun.jna.platformrZWinDefZMAX_PATHZzerosZShell32ZINSTANCEr@rAZShlObjZSHGFP_TYPE_CURRENTZNativeZtoStringZtostringrrCZKernel32ZkernalrE) r7rVrSrZbuf_sizerQr=r9rHrIZkernelrrr_get_win_folder_with_jnas&       rW)rO__main__ZMyAppZ MyCompanyz%-- app dirs (with optional 'version')z1.0)rz%s: %sz) -- app dirs (without optional 'version')z+ -- app dirs (without optional 'appauthor')z( -- app dirs (with disabled 'appauthor'))r)rrr)NNNF)NNNF)NNNF)NNNF)NNNT)NNNT)rr%r&r'r)r+),r2Z__version_info__rmapstr __version__sysr version_infoZPY3rBplatform startswithZjava_verZos_namer rr%r&r'r)r+objectr,r;rJrRrWr?Zwin32comrrFrNrOZ com.sun.jnaZcomr/rrZpropsprintdirsZproprArrrr s~    7 B ( 3 9 3+         __pycache__/appdirs.cpython-36.pyc000064400000044153147205126200013052 0ustar003 9ffW@sdZd1ZdjeeeZddlZddlZejddkZ e r>eZ ej j drddl Z e j ddZej drrd Zqej d rd Zqd Znej Zd2ddZd3ddZd4ddZd5ddZd6ddZd7ddZGdddeZddZdd Zd!d"Zd#d$Zed kryddlZeZWnnek rydd%l m!Z!eZWnBek r|yddl"Z#eZWnek rveZYnXYnXYnXe$d&kr~d'Z%d(Z&d8Z'e(d)ee%e&d*d+Z)x$e'D]Z*e(d,e*e+e)e*fqWe(d-ee%e&Z)x$e'D]Z*e(d,e*e+e)e*fqWe(d.ee%Z)x$e'D]Z*e(d,e*e+e)e*fq$We(d/ee%d d0Z)x$e'D]Z*e(d,e*e+e)e*fq^WdS)9zyUtilities for determining application-specific dirs. See for details and usage. .NjavaZWindowswin32ZMacdarwinZlinux2FcCstdkr^|dkr|}|rdpd}tjjt|}|r|dk rNtjj|||}qtjj||}nNtdkrtjjd}|rtjj||}n&tjdtjjd }|rtjj||}|r|rtjj||}|S) aJReturn full path to the user-specific data dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "roaming" (boolean, default False) can be set True to use the Windows roaming appdata directory. That means that for users on a Windows network setup for roaming profiles, this user data will be sync'd on login. See for a discussion of issues. Typical user data directories are: Mac OS X: ~/Library/Application Support/ Unix: ~/.local/share/ # or in $XDG_DATA_HOME, if defined Win XP (not roaming): C:\Documents and Settings\\Application Data\\ Win XP (roaming): C:\Documents and Settings\\Local Settings\Application Data\\ Win 7 (not roaming): C:\Users\\AppData\Local\\ Win 7 (roaming): C:\Users\\AppData\Roaming\\ For Unix, we follow the XDG spec and support $XDG_DATA_HOME. That means, by default "~/.local/share/". rN CSIDL_APPDATACSIDL_LOCAL_APPDATAFrz~/Library/Application Support/Z XDG_DATA_HOMEz~/.local/share)systemospathnormpath_get_win_folderjoin expandusergetenv)appname appauthorversionroamingconstr r/usr/lib/python3.6/appdirs.py user_data_dir-s&   rcs tdkrR|dkr}tjjtd}r|dk rBtjj||}qtjj|}ntdkrztjjd}rtjj|}nttjdtjjdd g}d d |j tjD}r|rtjj|fd d |D}|rtjj|}n|d }|So|rtjj||}|S)aiReturn full path to the user-shared data dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "multipath" is an optional parameter only applicable to *nix which indicates that the entire list of data dirs should be returned. By default, the first item from XDG_DATA_DIRS is returned, or '/usr/local/share/', if XDG_DATA_DIRS is not set Typical user data directories are: Mac OS X: /Library/Application Support/ Unix: /usr/local/share/ or /usr/share/ Win XP: C:\Documents and Settings\All Users\Application Data\\ Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) Win 7: C:\ProgramData\\ # Hidden, but writeable on Win 7. For Unix, this is using the $XDG_DATA_DIRS[0] default. WARNING: Do not use this on Windows. See the Vista-Fail note above for why. rNCSIDL_COMMON_APPDATAFrz/Library/Application SupportZ XDG_DATA_DIRSz/usr/local/sharez /usr/sharecSs g|]}tjj|jtjqSr)r r rrstripsep).0xrrr sz!site_data_dir..csg|]}tjj|gqSr)r rr)rr)rrrr sr) r r r rrrrrpathsepsplit)rrr multipathr pathlistr)rr site_data_dirds4  r%cCsXtdkrt||d|}n&tjdtjjd}|r>tjj||}|rT|rTtjj||}|S)aReturn full path to the user-specific config dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "roaming" (boolean, default False) can be set True to use the Windows roaming appdata directory. That means that for users on a Windows network setup for roaming profiles, this user data will be sync'd on login. See for a discussion of issues. Typical user data directories are: Mac OS X: same as user_data_dir Unix: ~/.config/ # or in $XDG_CONFIG_HOME, if defined Win *: same as user_data_dir For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. That means, by deafult "~/.config/". rrNZXDG_CONFIG_HOMEz ~/.config)rr)r rr rr rr)rrrrr rrruser_config_dirsr&cstd kr*t|}r|rtjj||}ndtjdd}dd|jtjD}rt|rbtjj|fdd|D}|rtjj|}n|d}|S) aReturn full path to the user-shared data dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "multipath" is an optional parameter only applicable to *nix which indicates that the entire list of config dirs should be returned. By default, the first item from XDG_CONFIG_DIRS is returned, or '/etc/xdg/', if XDG_CONFIG_DIRS is not set Typical user data directories are: Mac OS X: same as site_data_dir Unix: /etc/xdg/ or $XDG_CONFIG_DIRS[i]/ for each value in $XDG_CONFIG_DIRS Win *: same as site_data_dir Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False WARNING: Do not use this on Windows. See the Vista-Fail note above for why. rrZXDG_CONFIG_DIRSz/etc/xdgcSs g|]}tjj|jtjqSr)r r rrr)rrrrrr sz#site_config_dir..csg|]}tjj|gqSr)r rr)rr)rrrr sr)rr)r r%r r rrr"r!)rrrr#r r$r)rrsite_config_dirs  r'TcCstdkrd|dkr|}tjjtd}|r|dk rBtjj|||}ntjj||}|rtjj|d}nNtdkrtjjd}|rtjj||}n&tjdtjjd }|rtjj||}|r|rtjj||}|S) aReturn full path to the user-specific cache dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "opinion" (boolean) can be False to disable the appending of "Cache" to the base app data dir for Windows. See discussion below. Typical user cache directories are: Mac OS X: ~/Library/Caches/ Unix: ~/.cache/ (XDG default) Win XP: C:\Documents and Settings\\Local Settings\Application Data\\\Cache Vista: C:\Users\\AppData\Local\\\Cache On Windows the only suggestion in the MSDN docs is that local settings go in the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming app data dir (the default returned by `user_data_dir` above). Apps typically put cache data somewhere *under* the given dir here. Some examples: ...\Mozilla\Firefox\Profiles\\Cache ...\Acme\SuperApp\Cache\1.0 OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. This can be disabled with the `opinion=False` option. rNr FZCacherz~/Library/CachesZXDG_CACHE_HOMEz~/.cache)r r r rrrrr)rrropinionr rrruser_cache_dirs(! r)cCstdkr tjjtjjd|}nNtdkrLt|||}d}|rntjj|d}n"t|||}d}|rntjj|d}|r|rtjj||}|S)aReturn full path to the user-specific log dir for this application. "appname" is the name of application. If None, just the system directory is returned. "appauthor" (only used on Windows) is the name of the appauthor or distributing body for this application. Typically it is the owning company name. This falls back to appname. You may pass False to disable it. "version" is an optional version path element to append to the path. You might want to use this if you want multiple versions of your app to be able to run independently. If used, this would typically be ".". Only applied when appname is present. "opinion" (boolean) can be False to disable the appending of "Logs" to the base app data dir for Windows, and "log" to the base cache dir for Unix. See discussion below. Typical user cache directories are: Mac OS X: ~/Library/Logs/ Unix: ~/.cache//log # or under $XDG_CACHE_HOME if defined Win XP: C:\Documents and Settings\\Local Settings\Application Data\\\Logs Vista: C:\Users\\AppData\Local\\\Logs On Windows the only suggestion in the MSDN docs is that local settings go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in examples of what some windows apps use for a logs dir.) OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA` value for Windows and appends "log" to the user cache dir for Unix. This can be disabled with the `opinion=False` option. rz~/Library/LogsrFZLogslog)r r r rrrr))rrrr(r rrr user_log_dir:s    r+c@sbeZdZdZdddZeddZedd Zed d Zed d Z eddZ eddZ dS)AppDirsz1Convenience wrapper for getting application dirs.NFcCs"||_||_||_||_||_dS)N)rrrrr#)selfrrrrr#rrr__init__os zAppDirs.__init__cCst|j|j|j|jdS)N)rr)rrrrr)r-rrrrws zAppDirs.user_data_dircCst|j|j|j|jdS)N)rr#)r%rrrr#)r-rrrr%|s zAppDirs.site_data_dircCst|j|j|j|jdS)N)rr)r&rrrr)r-rrrr&s zAppDirs.user_config_dircCst|j|j|j|jdS)N)rr#)r'rrrr#)r-rrrr's zAppDirs.site_config_dircCst|j|j|jdS)N)r)r)rrr)r-rrrr)s zAppDirs.user_cache_dircCst|j|j|jdS)N)r)r+rrr)r-rrrr+s zAppDirs.user_log_dir)NNFF) __name__ __module__ __qualname____doc__r.propertyrr%r&r'r)r+rrrrr,ms      r,cCs:ddl}dddd|}|j|jd}|j||\}}|S)zThis is a fallback technique at best. I'm not sure if using the registry for this guarantees us the correct answer for all CSIDL_* names. rNZAppDatazCommon AppDataz Local AppData)r rr z@Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders)_winregOpenKeyHKEY_CURRENT_USERZ QueryValueEx) csidl_namer4Zshell_folder_namekeydirtyperrr_get_win_folder_from_registrysr;cCsddlm}m}|jdt||dd}y`t|}d}x|D]}t|dkr:d}Pq:W|ryddl}|j|}Wnt k rYnXWnt k rYnX|S)Nr)shellconshellFT) win32com.shellr<r=SHGetFolderPathgetattrunicodeordwin32apiGetShortPathName ImportError UnicodeError)r7r<r=r9 has_high_charcrDrrr_get_win_folder_with_pywin32s$   rJcCsddl}dddd|}|jd}|jjjd|dd|d}x|D]}t|dkrBd }PqBW|r|jd}|jjj|j|dr|}|jS) Nr#)r rr iFr>T) ctypesZcreate_unicode_bufferwindllZshell32ZSHGetFolderPathWrCZkernel32ZGetShortPathNameWvalue)r7rNZ csidl_constbufrHrIZbuf2rrr_get_win_folder_with_ctypess"    rRc Csddl}ddlm}ddlm}|jjd}|jd|}|jj }|j dt |j |d|j j ||jj|jjd}d}x|D]} t| dkr~d }Pq~W|r|jd|}|jj } tj|||r|jj|jjd}|S) Nr)jna)rrIFr>T)arrayZcom.sunrSZcom.sun.jna.platformrZWinDefZMAX_PATHZzerosZShell32ZINSTANCEr@rAZShlObjZSHGFP_TYPE_CURRENTZNativeZtoStringZtostringrrCZKernel32ZkernalrE) r7rVrSrZbuf_sizerQr=r9rHrIZkernelrrr_get_win_folder_with_jnas&       rW)rO__main__ZMyAppZ MyCompanyz%-- app dirs (with optional 'version')z1.0)rz%s: %sz) -- app dirs (without optional 'version')z+ -- app dirs (without optional 'appauthor')z( -- app dirs (with disabled 'appauthor'))r)rrr)NNNF)NNNF)NNNF)NNNF)NNNT)NNNT)rr%r&r'r)r+),r2Z__version_info__rmapstr __version__sysr version_infoZPY3rBplatform startswithZjava_verZos_namer rr%r&r'r)r+objectr,r;rJrRrWr?Zwin32comrrFrNrOZ com.sun.jnaZcomr/rrZpropsprintdirsZproprArrrr s~    7 B ( 3 9 3+         __pycache__/pyparsing.cpython-36.opt-1.pyc000064400000610513147205126200014362 0ustar003 9f@s dZdZdZdZddlZddlmZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlmZyddlmZWn ek rddlmZYnXydd l mZWn>ek rydd lmZWnek rdZYnXYnXd d d d ddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;dd?d@dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdgdhdidjdkdldmdndodpdqdrgiZee jddsZeddskZer"e jZe Z!e"Z#e Z$e%e&e'e(e)ee*e+e,e-e.g Z/nbe j0Ze1Z2dtduZ$gZ/ddl3Z3xBdvj4D]6Z5ye/j6e7e3e5Wne8k r|wJYnXqJWe9dwdxe2dyDZ:dzd{Z;Gd|d}d}e<Z=ej>ej?Z@d~ZAeAdZBe@eAZCe"dZDdjEddxejFDZGGdd!d!eHZIGdd#d#eIZJGdd%d%eIZKGdd'd'eKZLGdd*d*eHZMGddde<ZNGdd&d&e<ZOe jPjQeOdd=ZRddNZSddKZTddZUddZVddZWddUZXd/ddZYGdd(d(e<ZZGdd0d0eZZ[Gddde[Z\Gddde[Z]Gddde[Z^e^Z_e^eZ_`Gddde[ZaGdd d e^ZbGdd d eaZcGddpdpe[ZdGdd3d3e[ZeGdd+d+e[ZfGdd)d)e[ZgGdd d e[ZhGdd2d2e[ZiGddde[ZjGdddejZkGdddejZlGdddejZmGdd.d.ejZnGdd-d-ejZoGdd5d5ejZpGdd4d4ejZqGdd$d$eZZrGdd d erZsGdd d erZtGddderZuGddderZvGdd"d"eZZwGdddewZxGdddewZyGdddewZzGdddezZ{Gdd6d6ezZ|Gddde<Z}e}Z~GdddewZGdd,d,ewZGdddewZGdddeZGdd1d1ewZGdddeZGdddeZGdddeZGdd/d/eZGddde<ZddfZd0ddDZd1dd@Zdd΄ZddSZddRZdd҄Zd2ddWZddEZd3ddkZddlZddnZe\jdGZeljdMZemjdLZenjdeZeojddZeeeDdddڍjdd܄Zefd݃jdd܄Zefd߃jdd܄ZeeBeBeeeGddydBefde jBZeeedeZe^dedjdee{eeBjddZddcZddQZdd`Zdd^ZddqZedd܄Zedd܄ZddZddOZddPZddiZe<e_d4ddoZe=Ze<e_e<e_ededfddmZeZeefddjdZeefddjdZeefddefddBjdZee_dejjdZdddejfddTZd5ddjZedZedZeeee@eCdjd\ZZeed j4d Zefd d jEejÃd jdZĐdd_ZeefddjdZefdjdZefdjȃjdZefdjdZeefddeBjdZeZefdjdZee{eeeGdɐdeeede^dɃemj΃jdZeeejeBddjd>ZGd drdrZeҐd!k rebd"Zebd#Zeee@eCd$ZeeՐd%dӐd&jeZeeeփjd'Zאd(eBZeeՐd%dӐd&jeZeeeكjd)ZeӐd*eؐd'eeڐd)Zejܐd+ejjܐd,ejjܐd,ejjܐd-ddlZejjeejejjܐd.dS(6aS pyparsing module - Classes and methods to define and execute parsing grammars The pyparsing module is an alternative approach to creating and executing simple grammars, vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you don't need to learn a new syntax for defining grammars or matching expressions - the parsing module provides a library of classes that you use to construct the grammar directly in Python. Here is a program to parse "Hello, World!" (or any greeting of the form C{", !"}), built up using L{Word}, L{Literal}, and L{And} elements (L{'+'} operator gives L{And} expressions, strings are auto-converted to L{Literal} expressions):: from pyparsing import Word, alphas # define grammar of a greeting greet = Word(alphas) + "," + Word(alphas) + "!" hello = "Hello, World!" print (hello, "->", greet.parseString(hello)) The program outputs the following:: Hello, World! -> ['Hello', ',', 'World', '!'] The Python representation of the grammar is quite readable, owing to the self-explanatory class names, and the use of '+', '|' and '^' operators. The L{ParseResults} object returned from L{ParserElement.parseString} can be accessed as a nested list, a dictionary, or an object with named attributes. The pyparsing module handles some of the problems that are typically vexing when writing text parsers: - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) - quoted strings - embedded comments z2.1.10z07 Oct 2016 01:31 UTCz*Paul McGuire N)ref)datetime)RLock) OrderedDictAndCaselessKeywordCaselessLiteral CharsNotInCombineDictEachEmpty FollowedByForward GoToColumnGroupKeywordLineEnd LineStartLiteral MatchFirstNoMatchNotAny OneOrMoreOnlyOnceOptionalOrParseBaseExceptionParseElementEnhanceParseExceptionParseExpressionParseFatalException ParseResultsParseSyntaxException ParserElement QuotedStringRecursiveGrammarExceptionRegexSkipTo StringEnd StringStartSuppressTokenTokenConverterWhiteWordWordEnd WordStart ZeroOrMore alphanumsalphas alphas8bit anyCloseTag anyOpenTag cStyleCommentcolcommaSeparatedListcommonHTMLEntity countedArraycppStyleCommentdblQuotedStringdblSlashComment delimitedListdictOfdowncaseTokensemptyhexnums htmlCommentjavaStyleCommentlinelineEnd lineStartlineno makeHTMLTags makeXMLTagsmatchOnlyAtColmatchPreviousExprmatchPreviousLiteral nestedExprnullDebugActionnumsoneOfopAssocoperatorPrecedence printablespunc8bitpythonStyleComment quotedString removeQuotesreplaceHTMLEntity replaceWith restOfLinesglQuotedStringsrange stringEnd stringStarttraceParseAction unicodeString upcaseTokens withAttribute indentedBlockoriginalTextForungroup infixNotation locatedExpr withClass CloseMatchtokenMappyparsing_commonc Cs`t|tr|Syt|Stk rZt|jtjd}td}|jdd|j |SXdS)aDrop-in replacement for str(obj) that tries to be Unicode friendly. It first tries str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It then < returns the unicode object | encodes it with the default encoding | ... >. xmlcharrefreplacez&#\d+;cSs$dtt|dddddS)Nz\ur)hexint)trw/usr/lib/python3.6/pyparsing.pysz_ustr..N) isinstanceZunicodestrUnicodeEncodeErrorencodesysgetdefaultencodingr'setParseActiontransformString)objretZ xmlcharrefrwrwrx_ustrs rz6sum len sorted reversed list tuple set any all min maxccs|] }|VqdS)Nrw).0yrwrwrx srrrcCs>d}dddjD}x"t||D]\}}|j||}q"W|S)z/Escape &, <, >, ", ', etc. in a string of data.z&><"'css|]}d|dVqdS)&;Nrw)rsrwrwrxrsz_xml_escape..zamp gt lt quot apos)splitzipreplace)dataZ from_symbolsZ to_symbolsZfrom_Zto_rwrwrx _xml_escapes rc@s eZdZdS) _ConstantsN)__name__ __module__ __qualname__rwrwrwrxrsr 0123456789Z ABCDEFabcdef\ccs|]}|tjkr|VqdS)N)stringZ whitespace)rcrwrwrxrsc@sPeZdZdZdddZeddZdd Zd d Zd d Z dddZ ddZ dS)rz7base exception class for all parsing runtime exceptionsrNcCs>||_|dkr||_d|_n ||_||_||_|||f|_dS)Nr)locmsgpstr parserElementargs)selfrrrelemrwrwrx__init__szParseBaseException.__init__cCs||j|j|j|jS)z internal factory method to simplify creating one type of ParseException from another - avoids having __init__ signature conflicts among subclasses )rrrr)clsperwrwrx_from_exceptionsz"ParseBaseException._from_exceptioncCsN|dkrt|j|jS|dkr,t|j|jS|dkrBt|j|jSt|dS)zsupported attributes by name are: - lineno - returns the line number of the exception text - col - returns the column number of the exception text - line - returns the line containing the exception text rJr9columnrGN)r9r)rJrrr9rGAttributeError)rZanamerwrwrx __getattr__szParseBaseException.__getattr__cCsd|j|j|j|jfS)Nz"%s (at char %d), (line:%d, col:%d))rrrJr)rrwrwrx__str__szParseBaseException.__str__cCst|S)N)r)rrwrwrx__repr__szParseBaseException.__repr__>!} ('-' operator) indicates that parsing is to stop immediately because an unbacktrackable syntax error has been foundN)rrrrrwrwrwrxr#sc@s eZdZdZddZddZdS)r&zZexception thrown by L{ParserElement.validate} if the grammar could be improperly recursivecCs ||_dS)N)parseElementTrace)rparseElementListrwrwrxrsz"RecursiveGrammarException.__init__cCs d|jS)NzRecursiveGrammarException: %s)r)rrwrwrxr sz!RecursiveGrammarException.__str__N)rrrrrrrwrwrwrxr&sc@s,eZdZddZddZddZddZd S) _ParseResultsWithOffsetcCs||f|_dS)N)tup)rZp1Zp2rwrwrxr$sz _ParseResultsWithOffset.__init__cCs |j|S)N)r)rirwrwrx __getitem__&sz#_ParseResultsWithOffset.__getitem__cCst|jdS)Nr)reprr)rrwrwrxr(sz _ParseResultsWithOffset.__repr__cCs|jd|f|_dS)Nr)r)rrrwrwrx setOffset*sz!_ParseResultsWithOffset.setOffsetN)rrrrrrrrwrwrwrxr#src@seZdZdZd[ddZddddefddZdd Zefd d Zd d Z ddZ ddZ ddZ e Z ddZddZddZddZddZereZeZeZn$eZeZeZddZd d!Zd"d#Zd$d%Zd&d'Zd\d(d)Zd*d+Zd,d-Zd.d/Zd0d1Z d2d3Z!d4d5Z"d6d7Z#d8d9Z$d:d;Z%d} - see L{ParserElement.setResultsName}) Example:: integer = Word(nums) date_str = (integer.setResultsName("year") + '/' + integer.setResultsName("month") + '/' + integer.setResultsName("day")) # equivalent form: # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") # parseString returns a ParseResults object result = date_str.parseString("1999/12/31") def test(s, fn=repr): print("%s -> %s" % (s, fn(eval(s)))) test("list(result)") test("result[0]") test("result['month']") test("result.day") test("'month' in result") test("'minutes' in result") test("result.dump()", str) prints:: list(result) -> ['1999', '/', '12', '/', '31'] result[0] -> '1999' result['month'] -> '12' result.day -> '31' 'month' in result -> True 'minutes' in result -> False result.dump() -> ['1999', '/', '12', '/', '31'] - day: 31 - month: 12 - year: 1999 NTcCs"t||r|Stj|}d|_|S)NT)rzobject__new___ParseResults__doinit)rtoklistnameasListmodalZretobjrwrwrxrTs   zParseResults.__new__c Cs`|jrvd|_d|_d|_i|_||_||_|dkr6g}||trP|dd|_n||trft||_n|g|_t |_ |dk o|r\|sd|j|<||t rt |}||_||t dttfo|ddgfks\||tr|g}|r&||trt|jd||<ntt|dd||<|||_n6y|d||<Wn$tttfk rZ|||<YnXdS)NFrr)r_ParseResults__name_ParseResults__parent_ParseResults__accumNames_ParseResults__asList_ParseResults__modallist_ParseResults__toklist_generatorTypedict_ParseResults__tokdictrurr basestringr"rcopyKeyError TypeError IndexError)rrrrrrzrwrwrxr]sB     $   zParseResults.__init__cCsPt|ttfr|j|S||jkr4|j|ddStdd|j|DSdS)NrrrcSsg|] }|dqS)rrw)rvrwrwrx sz,ParseResults.__getitem__..rs)rzruslicerrrr")rrrwrwrxrs   zParseResults.__getitem__cCs||tr0|jj|t|g|j|<|d}nD||ttfrN||j|<|}n&|jj|tt|dg|j|<|}||trt||_ dS)Nr) rrgetrrurrr"wkrefr)rkrrzsubrwrwrx __setitem__s   " zParseResults.__setitem__c Cst|ttfrt|j}|j|=t|trH|dkr:||7}t||d}tt|j|}|jx^|j j D]F\}}x<|D]4}x.t |D]"\}\}} t || | |k||<qWq|WqnWn|j |=dS)Nrrr) rzrurlenrrrangeindicesreverseritems enumerater) rrZmylenZremovedr occurrencesjrvaluepositionrwrwrx __delitem__s   $zParseResults.__delitem__cCs ||jkS)N)r)rrrwrwrx __contains__szParseResults.__contains__cCs t|jS)N)rr)rrwrwrx__len__szParseResults.__len__cCs |j S)N)r)rrwrwrx__bool__szParseResults.__bool__cCs t|jS)N)iterr)rrwrwrx__iter__szParseResults.__iter__cCst|jdddS)Nrrrs)rr)rrwrwrx __reversed__szParseResults.__reversed__cCs$t|jdr|jjSt|jSdS)Niterkeys)hasattrrrr)rrwrwrx _iterkeyss  zParseResults._iterkeyscsfddjDS)Nc3s|]}|VqdS)Nrw)rr)rrwrxrsz+ParseResults._itervalues..)r)rrw)rrx _itervaluesszParseResults._itervaluescsfddjDS)Nc3s|]}||fVqdS)Nrw)rr)rrwrxrsz*ParseResults._iteritems..)r)rrw)rrx _iteritemsszParseResults._iteritemscCs t|jS)zVReturns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).)rr)rrwrwrxkeysszParseResults.keyscCs t|jS)zXReturns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).)r itervalues)rrwrwrxvaluesszParseResults.valuescCs t|jS)zfReturns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).)r iteritems)rrwrwrxrszParseResults.itemscCs t|jS)zSince keys() returns an iterator, this method is helpful in bypassing code that looks for the existence of any defined results names.)boolr)rrwrwrxhaskeysszParseResults.haskeyscOs|s dg}x6|jD]*\}}|dkr2|d|f}qtd|qWt|dtsht|dksh|d|kr|d}||}||=|S|d}|SdS)a Removes and returns item at specified index (default=C{last}). Supports both C{list} and C{dict} semantics for C{pop()}. If passed no argument or an integer argument, it will use C{list} semantics and pop tokens from the list of parsed tokens. If passed a non-integer argument (most likely a string), it will use C{dict} semantics and pop the corresponding value from any defined results names. A second default return value argument is supported, just as in C{dict.pop()}. Example:: def remove_first(tokens): tokens.pop(0) print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] label = Word(alphas) patt = label("LABEL") + OneOrMore(Word(nums)) print(patt.parseString("AAB 123 321").dump()) # Use pop() in a parse action to remove named result (note that corresponding value is not # removed from list form of results) def remove_LABEL(tokens): tokens.pop("LABEL") return tokens patt.addParseAction(remove_LABEL) print(patt.parseString("AAB 123 321").dump()) prints:: ['AAB', '123', '321'] - LABEL: AAB ['AAB', '123', '321'] rrdefaultrz-pop() got an unexpected keyword argument '%s'Nrs)rrrzrur)rrkwargsrrindexrZ defaultvaluerwrwrxpops"  zParseResults.popcCs||kr||S|SdS)ai Returns named result matching the given key, or if there is no such name, then returns the given C{defaultValue} or C{None} if no C{defaultValue} is specified. Similar to C{dict.get()}. Example:: integer = Word(nums) date_str = integer("year") + '/' + integer("month") + '/' + integer("day") result = date_str.parseString("1999/12/31") print(result.get("year")) # -> '1999' print(result.get("hour", "not specified")) # -> 'not specified' print(result.get("hour")) # -> None Nrw)rkey defaultValuerwrwrxrszParseResults.getcCsZ|jj||xF|jjD]8\}}x.t|D]"\}\}}t||||k||<q,WqWdS)a Inserts new element at location index in the list of parsed tokens. Similar to C{list.insert()}. Example:: print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] # use a parse action to insert the parse location in the front of the parsed results def insert_locn(locn, tokens): tokens.insert(0, locn) print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] N)rinsertrrrr)rrZinsStrrrrrrrwrwrxr2szParseResults.insertcCs|jj|dS)a Add single element to end of ParseResults list of elements. Example:: print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] # use a parse action to compute the sum of the parsed integers, and add it to the end def append_sum(tokens): tokens.append(sum(map(int, tokens))) print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] N)rappend)ritemrwrwrxrFs zParseResults.appendcCs$t|tr||7}n |jj|dS)a Add sequence of elements to end of ParseResults list of elements. Example:: patt = OneOrMore(Word(alphas)) # use a parse action to append the reverse of the matched strings, to make a palindrome def make_palindrome(tokens): tokens.extend(reversed([t[::-1] for t in tokens])) return ''.join(tokens) print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' N)rzr"rextend)rZitemseqrwrwrxrTs  zParseResults.extendcCs|jdd=|jjdS)z7 Clear all elements and results names. N)rrclear)rrwrwrxrfs zParseResults.clearc Csfy||Stk rdSX||jkr^||jkrD|j|ddStdd|j|DSndSdS)NrrrrcSsg|] }|dqS)rrw)rrrwrwrxrwsz,ParseResults.__getattr__..rs)rrrr")rrrwrwrxrms  zParseResults.__getattr__cCs|j}||7}|S)N)r)rotherrrwrwrx__add__{szParseResults.__add__cs|jrnt|jfdd|jj}fdd|D}x4|D],\}}|||<t|dtr>t||d_q>W|j|j7_|jj |j|S)Ncs|dkr S|S)Nrrw)a)offsetrwrxrysz'ParseResults.__iadd__..c s4g|],\}}|D]}|t|d|dfqqS)rrr)r)rrvlistr) addoffsetrwrxrsz)ParseResults.__iadd__..r) rrrrrzr"rrrupdate)rrZ otheritemsZotherdictitemsrrrw)rrrx__iadd__s    zParseResults.__iadd__cCs&t|tr|dkr|jS||SdS)Nr)rzrur)rrrwrwrx__radd__szParseResults.__radd__cCsdt|jt|jfS)Nz(%s, %s))rrr)rrwrwrxrszParseResults.__repr__cCsddjdd|jDdS)N[z, css(|] }t|trt|nt|VqdS)N)rzr"rr)rrrwrwrxrsz'ParseResults.__str__..])rr)rrwrwrxrszParseResults.__str__rcCsPg}xF|jD]<}|r"|r"|j|t|tr:||j7}q |jt|q W|S)N)rrrzr" _asStringListr)rsepoutrrwrwrxr s   zParseResults._asStringListcCsdd|jDS)a Returns the parse results as a nested list of matching tokens, all converted to strings. Example:: patt = OneOrMore(Word(alphas)) result = patt.parseString("sldkj lsdkj sldkj") # even though the result prints in string-like form, it is actually a pyparsing ParseResults print(type(result), result) # -> ['sldkj', 'lsdkj', 'sldkj'] # Use asList() to create an actual list result_list = result.asList() print(type(result_list), result_list) # -> ['sldkj', 'lsdkj', 'sldkj'] cSs"g|]}t|tr|jn|qSrw)rzr"r)rresrwrwrxrsz'ParseResults.asList..)r)rrwrwrxrszParseResults.asListcs6tr |j}n|j}fddtfdd|DS)a Returns the named parse results as a nested dictionary. Example:: integer = Word(nums) date_str = integer("year") + '/' + integer("month") + '/' + integer("day") result = date_str.parseString('12/31/1999') print(type(result), repr(result)) # -> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) result_dict = result.asDict() print(type(result_dict), repr(result_dict)) # -> {'day': '1999', 'year': '12', 'month': '31'} # even though a ParseResults supports dict-like access, sometime you just need to have a dict import json print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} cs6t|tr.|jr|jSfdd|DSn|SdS)Ncsg|] }|qSrwrw)rr)toItemrwrxrsz7ParseResults.asDict..toItem..)rzr"rasDict)r)rrwrxrs  z#ParseResults.asDict..toItemc3s|]\}}||fVqdS)Nrw)rrr)rrwrxrsz&ParseResults.asDict..)PY_3rrr)rZitem_fnrw)rrxrs  zParseResults.asDictcCs8t|j}|jj|_|j|_|jj|j|j|_|S)zA Returns a new copy of a C{ParseResults} object. )r"rrrrrrr)rrrwrwrxrs   zParseResults.copyFc CsPd}g}tdd|jjD}|d}|s8d}d}d}d} |dk rJ|} n |jrV|j} | sf|rbdSd} |||d| d g7}xt|jD]\} } t| tr| |kr|| j|| |o|dk||g7}n|| jd|o|dk||g7}qd} | |kr|| } | s |rqnd} t t | } |||d| d | d | d g 7}qW|||d | d g7}dj |S) z (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names.  css(|] \}}|D]}|d|fVqqdS)rrNrw)rrrrrwrwrxrsz%ParseResults.asXML..z rNZITEM<>z.z %s%s- %s: z rrcss|]}t|tVqdS)N)rzr")rvvrwrwrxrssz %s%s[%d]: %s%s%sr) rrrrsortedrrzr"dumpranyrr) rrdepthfullr NLrrrrrrwrwrxrPs,   4.zParseResults.dumpcOstj|jf||dS)a Pretty-printer for parsed results as a list, using the C{pprint} module. Accepts additional positional or keyword args as defined for the C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint}) Example:: ident = Word(alphas, alphanums) num = Word(nums) func = Forward() term = ident | num | Group('(' + func + ')') func <<= ident + Group(Optional(delimitedList(term))) result = func.parseString("fna a,b,(fnb c,d,200),100") result.pprint(width=40) prints:: ['fna', ['a', 'b', ['(', 'fnb', ['c', 'd', '200'], ')'], '100']] N)pprintr)rrrrwrwrxr"}szParseResults.pprintcCs.|j|jj|jdk r|jp d|j|jffS)N)rrrrrr)rrwrwrx __getstate__s zParseResults.__getstate__cCsN|d|_|d\|_}}|_i|_|jj||dk rDt||_nd|_dS)Nrrr)rrrrrrr)rstaterZ inAccumNamesrwrwrx __setstate__s   zParseResults.__setstate__cCs|j|j|j|jfS)N)rrrr)rrwrwrx__getnewargs__szParseResults.__getnewargs__cCstt|t|jS)N)rrrr)rrwrwrxrszParseResults.__dir__)NNTT)N)r)NFrT)rrT)4rrrrrrzrrrrrrr __nonzero__rrrrrrrrrrrrrrrrrrrrrrrrrr rrrrrrrr"r#r%r&rrwrwrwrxr"-sh& ' 4  # =% - cCsF|}d|kot|knr4||ddkr4dS||jdd|S)aReturns current column within a string, counting newlines as line separators. The first column is number 1. Note: the default parsing behavior is to expand tabs in the input string before starting the parsing process. See L{I{ParserElement.parseString}} for more information on parsing strings containing C{}s, and suggested methods to maintain a consistent view of the parsed string, the parse location, and line and column positions within the parsed string. rrrr)rrfind)rstrgrrwrwrxr9s cCs|jdd|dS)aReturns current line number within a string, counting newlines as line separators. The first line is number 1. Note: the default parsing behavior is to expand tabs in the input string before starting the parsing process. See L{I{ParserElement.parseString}} for more information on parsing strings containing C{}s, and suggested methods to maintain a consistent view of the parsed string, the parse location, and line and column positions within the parsed string. rrrr)count)rr)rwrwrxrJs cCsF|jdd|}|jd|}|dkr2||d|S||ddSdS)zfReturns the line of text containing loc within a string, counting newlines as line separators. rrrrN)r(find)rr)ZlastCRZnextCRrwrwrxrGs  cCs8tdt|dt|dt||t||fdS)NzMatch z at loc z(%d,%d))printrrJr9)instringrexprrwrwrx_defaultStartDebugActionsr/cCs$tdt|dt|jdS)NzMatched z -> )r,rr{r)r-startlocZendlocr.toksrwrwrx_defaultSuccessDebugActionsr2cCstdt|dS)NzException raised:)r,r)r-rr.excrwrwrx_defaultExceptionDebugActionsr4cGsdS)zG'Do-nothing' debug action, to suppress debugging output during parsing.Nrw)rrwrwrxrQsrqc stkrfddSdgdgtdddkrFddd }dd d n tj}tjd }|dd d}|d|d|ffdd}d}ytdtdj}Wntk rt}YnX||_|S)Ncs|S)Nrw)rlrv)funcrwrxrysz_trim_arity..rFrqrocSs8tdkr dnd }tj| |dd|}|j|jfgS) Nror7rrqrr)limit)ror7r)system_version traceback extract_stackfilenamerJ)r8r frame_summaryrwrwrxr=sz"_trim_arity..extract_stackcSs$tj||d}|d}|j|jfgS)N)r8rrrs)r< extract_tbr>rJ)tbr8Zframesr?rwrwrxr@sz_trim_arity..extract_tb)r8rrcsxy |dd}dd<|Stk rdr>n4z.tjd}|dddddksjWd~Xdkrdd7<wYqXqWdS)NrTrrrq)r8rsrs)rr~exc_info)rrrA)r@ foundArityr6r8maxargspa_call_line_synthrwrxwrappers"  z_trim_arity..wrapperzr __class__)ror7)r)rrs) singleArgBuiltinsr;r<r=r@getattrr Exceptionr{)r6rEr=Z LINE_DIFFZ this_linerG func_namerw)r@rDr6r8rErFrx _trim_aritys*   rMcseZdZdZdZdZeddZeddZddd Z d d Z d d Z dddZ dddZ ddZddZddZddZddZddZddd Zd!d"Zdd#d$Zd%d&Zd'd(ZGd)d*d*eZed+k rGd,d-d-eZnGd.d-d-eZiZeZd/d/gZ dd0d1Z!eZ"ed2d3Z#dZ$edd5d6Z%dd7d8Z&e'dfd9d:Z(d;d<Z)e'fd=d>Z*e'dfd?d@Z+dAdBZ,dCdDZ-dEdFZ.dGdHZ/dIdJZ0dKdLZ1dMdNZ2dOdPZ3dQdRZ4dSdTZ5dUdVZ6dWdXZ7dYdZZ8dd[d\Z9d]d^Z:d_d`Z;dadbZdgdhZ?ddidjZ@dkdlZAdmdnZBdodpZCdqdrZDgfdsdtZEddudvZFfdwdxZGdydzZHd{d|ZId}d~ZJddZKdddZLdddZMZNS)r$z)Abstract base level parser element class.z FcCs |t_dS)a Overrides the default whitespace chars Example:: # default whitespace chars are space, and newline OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] # change to just treat newline as significant ParserElement.setDefaultWhitespaceChars(" \t") OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] N)r$DEFAULT_WHITE_CHARS)charsrwrwrxsetDefaultWhitespaceChars=s z'ParserElement.setDefaultWhitespaceCharscCs |t_dS)a Set class to be used for inclusion of string literals into a parser. Example:: # default literal class used is Literal integer = Word(nums) date_str = integer("year") + '/' + integer("month") + '/' + integer("day") date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] # change to Suppress ParserElement.inlineLiteralsUsing(Suppress) date_str = integer("year") + '/' + integer("month") + '/' + integer("day") date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] N)r$_literalStringClass)rrwrwrxinlineLiteralsUsingLsz!ParserElement.inlineLiteralsUsingcCst|_d|_d|_d|_||_d|_tj|_ d|_ d|_ d|_ t|_ d|_d|_d|_d|_d|_d|_d|_d|_d|_dS)NTFr)NNN)r parseAction failActionstrRepr resultsName saveAsListskipWhitespacer$rN whiteCharscopyDefaultWhiteCharsmayReturnEmptykeepTabs ignoreExprsdebug streamlined mayIndexErrorerrmsg modalResults debugActionsre callPreparse callDuringTry)rsavelistrwrwrxras(zParserElement.__init__cCs<tj|}|jdd|_|jdd|_|jr8tj|_|S)a$ Make a copy of this C{ParserElement}. Useful for defining different parse actions for the same parsing pattern, using copies of the original parse element. Example:: integer = Word(nums).setParseAction(lambda toks: int(toks[0])) integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) prints:: [5120, 100, 655360, 268435456] Equivalent form of C{expr.copy()} is just C{expr()}:: integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") N)rrSr]rZr$rNrY)rZcpyrwrwrxrxs  zParserElement.copycCs*||_d|j|_t|dr&|j|j_|S)af Define name for this expression, makes debugging and exception messages clearer. Example:: Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) z Expected exception)rrarrhr)rrrwrwrxsetNames    zParserElement.setNamecCs4|j}|jdr"|dd}d}||_| |_|S)aP Define name for referencing matching tokens as a nested attribute of the returned parse results. NOTE: this returns a *copy* of the original C{ParserElement} object; this is so that the client can define a basic element, such as an integer, and reference it in multiple places with different names. You can also set results names using the abbreviated syntax, C{expr("name")} in place of C{expr.setResultsName("name")} - see L{I{__call__}<__call__>}. Example:: date_str = (integer.setResultsName("year") + '/' + integer.setResultsName("month") + '/' + integer.setResultsName("day")) # equivalent form: date_str = integer("year") + '/' + integer("month") + '/' + integer("day") *NrrTrs)rendswithrVrb)rrlistAllMatchesZnewselfrwrwrxsetResultsNames  zParserElement.setResultsNameTcs@|r&|jdfdd }|_||_nt|jdr<|jj|_|S)zMethod to invoke the Python pdb debugger when this element is about to be parsed. Set C{breakFlag} to True to enable, False to disable. Tcsddl}|j||||S)Nr)pdbZ set_trace)r-r doActions callPreParsern) _parseMethodrwrxbreakersz'ParserElement.setBreak..breaker_originalParseMethod)TT)_parsersr)rZ breakFlagrrrw)rqrxsetBreaks  zParserElement.setBreakcOs&tttt||_|jdd|_|S)a  Define action to perform when successfully matching parse element definition. Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: - s = the original string being parsed (see note below) - loc = the location of the matching substring - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object If the functions in fns modify the tokens, they can return them as the return value from fn, and the modified list of tokens will replace the original. Otherwise, fn does not need to return any value. Optional keyword arguments: - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing Note: the default parsing behavior is to expand tabs in the input string before starting the parsing process. See L{I{parseString}} for more information on parsing strings containing C{}s, and suggested methods to maintain a consistent view of the parsed string, the parse location, and line and column positions within the parsed string. Example:: integer = Word(nums) date_str = integer + '/' + integer + '/' + integer date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] # use parse action to convert to ints at parse time integer = Word(nums).setParseAction(lambda toks: int(toks[0])) date_str = integer + '/' + integer + '/' + integer # note that integer fields are now ints, not strings date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] rfF)rmaprMrSrrf)rfnsrrwrwrxrs"zParserElement.setParseActioncOs4|jtttt|7_|jp,|jdd|_|S)z Add parse action to expression's list of parse actions. See L{I{setParseAction}}. See examples in L{I{copy}}. rfF)rSrrvrMrfr)rrwrrwrwrxaddParseActionszParserElement.addParseActioncsb|jdd|jddrtntx(|D] fdd}|jj|q&W|jpZ|jdd|_|S)aAdd a boolean predicate function to expression's list of parse actions. See L{I{setParseAction}} for function call signatures. Unlike C{setParseAction}, functions passed to C{addCondition} need to return boolean success/fail of the condition. Optional keyword arguments: - message = define a custom message to be used in the raised exception - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException Example:: integer = Word(nums).setParseAction(lambda toks: int(toks[0])) year_int = integer.copy() year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") date_str = year_int + '/' + integer + '/' + integer result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) messagezfailed user-defined conditionfatalFcs$tt|||s ||dS)N)rrM)rr5rv)exc_typefnrrwrxpasz&ParserElement.addCondition..parf)rr!rrSrrf)rrwrr}rw)r{r|rrx addConditions  zParserElement.addConditioncCs ||_|S)a Define action to perform if parsing fails at this expression. Fail acton fn is a callable function that takes the arguments C{fn(s,loc,expr,err)} where: - s = string being parsed - loc = location where expression match was attempted and failed - expr = the parse expression that failed - err = the exception thrown The function returns no value. It may throw C{L{ParseFatalException}} if it is desired to stop parsing immediately.)rT)rr|rwrwrx setFailActions zParserElement.setFailActionc CsZd}xP|rTd}xB|jD]8}yx|j||\}}d}qWWqtk rLYqXqWqW|S)NTF)r]rtr)rr-rZ exprsFoundeZdummyrwrwrx_skipIgnorables#s  zParserElement._skipIgnorablescCsL|jr|j||}|jrH|j}t|}x ||krF|||krF|d7}q(W|S)Nrr)r]rrXrYr)rr-rZwtinstrlenrwrwrxpreParse0s  zParserElement.preParsecCs|gfS)Nrw)rr-rrorwrwrx parseImpl<szParserElement.parseImplcCs|S)Nrw)rr-r tokenlistrwrwrx postParse?szParserElement.postParsec "Cs|j}|s|jr|jdr,|jd||||rD|jrD|j||}n|}|}yDy|j|||\}}Wn(tk rt|t||j |YnXWnXt k r} z<|jdr|jd|||| |jr|j|||| WYdd} ~ XnXn|o|jr|j||}n|}|}|j s$|t|krhy|j|||\}}Wn*tk rdt|t||j |YnXn|j|||\}}|j |||}t ||j|j|jd} |jr|s|jr|rVyRxL|jD]B} | ||| }|dk rt ||j|jot|t tf|jd} qWWnFt k rR} z(|jdr@|jd|||| WYdd} ~ XnXnNxL|jD]B} | ||| }|dk r^t ||j|jot|t tf|jd} q^W|r|jdr|jd||||| || fS)Nrrq)rrrr)r^rTrcrerrrrrrarr`rr"rVrWrbrSrfrzr) rr-rrorpZ debuggingprelocZ tokensStarttokenserrZ retTokensr|rwrwrx _parseNoCacheCsp             zParserElement._parseNoCachec Cs>y|j||dddStk r8t|||j|YnXdS)NF)ror)rtr!rra)rr-rrwrwrxtryParseszParserElement.tryParsec Cs2y|j||Wnttfk r(dSXdSdS)NFT)rrr)rr-rrwrwrx canParseNexts zParserElement.canParseNextc@seZdZddZdS)zParserElement._UnboundedCachecsdit|_fdd}fdd}fdd}tj|||_tj|||_tj|||_dS)Ncs j|S)N)r)rr)cache not_in_cacherwrxrsz3ParserElement._UnboundedCache.__init__..getcs ||<dS)Nrw)rrr)rrwrxsetsz3ParserElement._UnboundedCache.__init__..setcs jdS)N)r)r)rrwrxrsz5ParserElement._UnboundedCache.__init__..clear)rrtypes MethodTyperrr)rrrrrw)rrrxrs   z&ParserElement._UnboundedCache.__init__N)rrrrrwrwrwrx_UnboundedCachesrNc@seZdZddZdS)zParserElement._FifoCachecsht|_tfdd}fdd}fdd}tj|||_tj|||_tj|||_dS)Ncs j|S)N)r)rr)rrrwrxrsz.ParserElement._FifoCache.__init__..getcs"||<tkrjddS)NF)rpopitem)rrr)rsizerwrxrs z.ParserElement._FifoCache.__init__..setcs jdS)N)r)r)rrwrxrsz0ParserElement._FifoCache.__init__..clear)rr _OrderedDictrrrrr)rrrrrrw)rrrrxrs  z!ParserElement._FifoCache.__init__N)rrrrrwrwrwrx _FifoCachesrc@seZdZddZdS)zParserElement._FifoCachecsvt|_itjgfdd}fdd}fdd}tj|||_tj|||_tj|||_dS)Ncs j|S)N)r)rr)rrrwrxrsz.ParserElement._FifoCache.__init__..getcs2||<tkr$jjdj|dS)N)rrpopleftr)rrr)rkey_fiforrwrxrs z.ParserElement._FifoCache.__init__..setcsjjdS)N)r)r)rrrwrxrsz0ParserElement._FifoCache.__init__..clear) rr collectionsdequerrrrr)rrrrrrw)rrrrrxrs  z!ParserElement._FifoCache.__init__N)rrrrrwrwrwrxrsrc Csd\}}|||||f}tjtj}|j|} | |jkrtj|d7<y|j||||} Wn8tk r} z|j|| j | j WYdd} ~ XqX|j|| d| dj f| Sn4tj|d7<t | t r| | d| dj fSWdQRXdS)Nrrr)rrr)r$packrat_cache_lock packrat_cacherrpackrat_cache_statsrrrrHrrrzrK) rr-rrorpZHITZMISSlookuprrrrwrwrx _parseCaches$   zParserElement._parseCachecCs(tjjdgttjtjdd<dS)Nr)r$rrrrrwrwrwrx resetCaches zParserElement.resetCachecCs8tjs4dt_|dkr tjt_n tj|t_tjt_dS)aEnables "packrat" parsing, which adds memoizing to the parsing logic. Repeated parse attempts at the same string location (which happens often in many complex grammars) can immediately return a cached value, instead of re-executing parsing/validating code. Memoizing is done of both valid results and parsing exceptions. Parameters: - cache_size_limit - (default=C{128}) - if an integer value is provided will limit the size of the packrat cache; if None is passed, then the cache size will be unbounded; if 0 is passed, the cache will be effectively disabled. This speedup may break existing programs that use parse actions that have side-effects. For this reason, packrat parsing is disabled when you first import pyparsing. To activate the packrat feature, your program must call the class method C{ParserElement.enablePackrat()}. If your program uses C{psyco} to "compile as you go", you must call C{enablePackrat} before calling C{psyco.full()}. If you do not do this, Python will crash. For best results, call C{enablePackrat()} immediately after importing pyparsing. Example:: import pyparsing pyparsing.ParserElement.enablePackrat() TN)r$_packratEnabledrrrrrt)Zcache_size_limitrwrwrx enablePackrats   zParserElement.enablePackratcCstj|js|jx|jD] }|jqW|js<|j}y<|j|d\}}|rv|j||}t t }|j||Wn0t k r}ztj rn|WYdd}~XnX|SdS)aB Execute the parse expression with the given string. This is the main interface to the client code, once the complete expression has been built. If you want the grammar to require that the entire input string be successfully parsed, then set C{parseAll} to True (equivalent to ending the grammar with C{L{StringEnd()}}). Note: C{parseString} implicitly calls C{expandtabs()} on the input string, in order to report proper column numbers in parse actions. If the input string contains tabs and the grammar uses parse actions that use the C{loc} argument to index into the string being parsed, you can ensure you have a consistent view of the input string by: - calling C{parseWithTabs} on your grammar before calling C{parseString} (see L{I{parseWithTabs}}) - define your parse action using the full C{(s,loc,toks)} signature, and reference the input string using the parse action's C{s} argument - explictly expand the tabs in your input string before calling C{parseString} Example:: Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text rN) r$rr_ streamliner]r\ expandtabsrtrr r)rverbose_stacktrace)rr-parseAllrrrZser3rwrwrx parseString#s$    zParserElement.parseStringccs@|js|jx|jD] }|jqW|js8t|j}t|}d}|j}|j}t j d} yx||kon| |kry |||} ||| dd\} } Wnt k r| d}Yq`X| |kr| d7} | | | fV|r|||} | |kr| }q|d7}n| }q`| d}q`WWn4t k r:}zt j r&n|WYdd}~XnXdS)a Scan the input string for expression matches. Each match will return the matching tokens, start location, and end location. May be called with optional C{maxMatches} argument, to clip scanning after 'n' matches are found. If C{overlap} is specified, then overlapping matches will be reported. Note that the start and end locations are reported relative to the string being parsed. See L{I{parseString}} for more information on parsing strings with embedded tabs. Example:: source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" print(source) for tokens,start,end in Word(alphas).scanString(source): print(' '*start + '^'*(end-start)) print(' '*start + tokens[0]) prints:: sldjf123lsdjjkf345sldkjf879lkjsfd987 ^^^^^ sldjf ^^^^^^^ lsdjjkf ^^^^^^ sldkjf ^^^^^^ lkjsfd rF)rprrN)r_rr]r\rrrrrtr$rrrr)rr- maxMatchesZoverlaprrrZ preparseFnZparseFnmatchesrZnextLocrZnextlocr3rwrwrx scanStringUsB       zParserElement.scanStringcCsg}d}d|_yxh|j|D]Z\}}}|j||||rrt|trT||j7}nt|trh||7}n |j||}qW|j||ddd|D}djtt t |St k r}zt j rȂn|WYdd}~XnXdS)af Extension to C{L{scanString}}, to modify matching text with modified tokens that may be returned from a parse action. To use C{transformString}, define a grammar and attach a parse action to it that modifies the returned token list. Invoking C{transformString()} on a target string will then scan for matches, and replace the matched text patterns according to the logic in the parse action. C{transformString()} returns the resulting transformed string. Example:: wd = Word(alphas) wd.setParseAction(lambda toks: toks[0].title()) print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) Prints:: Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. rTNcSsg|] }|r|qSrwrw)rorwrwrxrsz1ParserElement.transformString..r)r\rrrzr"rrrrvr_flattenrr$r)rr-r ZlastErvrrr3rwrwrxrs(    zParserElement.transformStringcCsPytdd|j||DStk rJ}ztjr6n|WYdd}~XnXdS)a~ Another extension to C{L{scanString}}, simplifying the access to the tokens found to match the given parse expression. May be called with optional C{maxMatches} argument, to clip searching after 'n' matches are found. Example:: # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters cap_word = Word(alphas.upper(), alphas.lower()) print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) prints:: ['More', 'Iron', 'Lead', 'Gold', 'I'] cSsg|]\}}}|qSrwrw)rrvrrrwrwrxrsz.ParserElement.searchString..N)r"rrr$r)rr-rr3rwrwrx searchStrings zParserElement.searchStringc csXd}d}x<|j||dD]*\}}}|||V|r>|dV|}qW||dVdS)a[ Generator method to split a string using the given expression as a separator. May be called with optional C{maxsplit} argument, to limit the number of splits; and the optional C{includeSeparators} argument (default=C{False}), if the separating matching text should be included in the split results. Example:: punc = oneOf(list(".,;:/-!?")) print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) prints:: ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] r)rN)r) rr-maxsplitZincludeSeparatorsZsplitsZlastrvrrrwrwrxrs  zParserElement.splitcCsFt|trtj|}t|ts:tjdt|tdddSt||gS)a Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement converts them to L{Literal}s by default. Example:: greet = Word(alphas) + "," + Word(alphas) + "!" hello = "Hello, World!" print (hello, "->", greet.parseString(hello)) Prints:: Hello, World! -> ['Hello', ',', 'World', '!'] z4Cannot combine element of type %s with ParserElementrq) stacklevelN) rzrr$rQwarningswarnr SyntaxWarningr)rrrwrwrxrs    zParserElement.__add__cCsBt|trtj|}t|ts:tjdt|tdddS||S)z] Implementation of + operator when left operand is not a C{L{ParserElement}} z4Cannot combine element of type %s with ParserElementrq)rN)rzrr$rQrrrr)rrrwrwrxrs    zParserElement.__radd__cCsLt|trtj|}t|ts:tjdt|tdddSt|tj |gS)zQ Implementation of - operator, returns C{L{And}} with error stop z4Cannot combine element of type %s with ParserElementrq)rN) rzrr$rQrrrrr _ErrorStop)rrrwrwrx__sub__s    zParserElement.__sub__cCsBt|trtj|}t|ts:tjdt|tdddS||S)z] Implementation of - operator when left operand is not a C{L{ParserElement}} z4Cannot combine element of type %s with ParserElementrq)rN)rzrr$rQrrrr)rrrwrwrx__rsub__ s    zParserElement.__rsub__cst|tr|d}}nt|tr|d dd}|ddkrHd|df}t|dtr|ddkr|ddkrvtS|ddkrtS|dtSnJt|dtrt|dtr|\}}||8}ntdt|dt|dntdt||dkr td|dkrtd||ko2dknrBtd |rfd d |r|dkrt|}ntg||}n|}n|dkr}ntg|}|S) a Implementation of * operator, allows use of C{expr * 3} in place of C{expr + expr + expr}. Expressions may also me multiplied by a 2-integer tuple, similar to C{{min,max}} multipliers in regular expressions. Tuples may also include C{None} as in: - C{expr*(n,None)} or C{expr*(n,)} is equivalent to C{expr*n + L{ZeroOrMore}(expr)} (read as "at least n instances of C{expr}") - C{expr*(None,n)} is equivalent to C{expr*(0,n)} (read as "0 to n instances of C{expr}") - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)} - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)} Note that C{expr*(None,n)} does not raise an exception if more than n exprs exist in the input stream; that is, C{expr*(None,n)} does not enforce a maximum number of expr occurrences. If this behavior is desired, then write C{expr*(None,n) + ~expr} rNrqrrz7cannot multiply 'ParserElement' and ('%s','%s') objectsz0cannot multiply 'ParserElement' and '%s' objectsz/cannot multiply ParserElement by negative valuez@second tuple value must be greater or equal to first tuple valuez+cannot multiply ParserElement by 0 or (0,0)cs(|dkrt|dStSdS)Nrr)r)n)makeOptionalListrrwrxr]sz/ParserElement.__mul__..makeOptionalList)NN) rzrutupler2rrr ValueErrorr)rrZ minElementsZ optElementsrrw)rrrx__mul__,sD             zParserElement.__mul__cCs |j|S)N)r)rrrwrwrx__rmul__pszParserElement.__rmul__cCsFt|trtj|}t|ts:tjdt|tdddSt||gS)zI Implementation of | operator - returns C{L{MatchFirst}} z4Cannot combine element of type %s with ParserElementrq)rN) rzrr$rQrrrrr)rrrwrwrx__or__ss    zParserElement.__or__cCsBt|trtj|}t|ts:tjdt|tdddS||BS)z] Implementation of | operator when left operand is not a C{L{ParserElement}} z4Cannot combine element of type %s with ParserElementrq)rN)rzrr$rQrrrr)rrrwrwrx__ror__s    zParserElement.__ror__cCsFt|trtj|}t|ts:tjdt|tdddSt||gS)zA Implementation of ^ operator - returns C{L{Or}} z4Cannot combine element of type %s with ParserElementrq)rN) rzrr$rQrrrrr)rrrwrwrx__xor__s    zParserElement.__xor__cCsBt|trtj|}t|ts:tjdt|tdddS||AS)z] Implementation of ^ operator when left operand is not a C{L{ParserElement}} z4Cannot combine element of type %s with ParserElementrq)rN)rzrr$rQrrrr)rrrwrwrx__rxor__s    zParserElement.__rxor__cCsFt|trtj|}t|ts:tjdt|tdddSt||gS)zC Implementation of & operator - returns C{L{Each}} z4Cannot combine element of type %s with ParserElementrq)rN) rzrr$rQrrrrr )rrrwrwrx__and__s    zParserElement.__and__cCsBt|trtj|}t|ts:tjdt|tdddS||@S)z] Implementation of & operator when left operand is not a C{L{ParserElement}} z4Cannot combine element of type %s with ParserElementrq)rN)rzrr$rQrrrr)rrrwrwrx__rand__s    zParserElement.__rand__cCst|S)zE Implementation of ~ operator - returns C{L{NotAny}} )r)rrwrwrx __invert__szParserElement.__invert__cCs|dk r|j|S|jSdS)a  Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}. If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be passed as C{True}. If C{name} is omitted, same as calling C{L{copy}}. Example:: # these are equivalent userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") N)rmr)rrrwrwrx__call__s zParserElement.__call__cCst|S)z Suppresses the output of this C{ParserElement}; useful to keep punctuation from cluttering up returned output. )r+)rrwrwrxsuppressszParserElement.suppresscCs d|_|S)a Disables the skipping of whitespace before matching the characters in the C{ParserElement}'s defined pattern. This is normally only used internally by the pyparsing module, but may be needed in some whitespace-sensitive grammars. F)rX)rrwrwrxleaveWhitespaceszParserElement.leaveWhitespacecCsd|_||_d|_|S)z8 Overrides the default whitespace chars TF)rXrYrZ)rrOrwrwrxsetWhitespaceCharssz ParserElement.setWhitespaceCharscCs d|_|S)z Overrides default behavior to expand C{}s to spaces before parsing the input string. Must be called before C{parseString} when the input grammar contains elements that match C{} characters. T)r\)rrwrwrx parseWithTabsszParserElement.parseWithTabscCsLt|trt|}t|tr4||jkrH|jj|n|jjt|j|S)a Define expression to be ignored (e.g., comments) while doing pattern matching; may be called repeatedly, to define multiple comment or other ignorable patterns. Example:: patt = OneOrMore(Word(alphas)) patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] patt.ignore(cStyleComment) patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] )rzrr+r]rr)rrrwrwrxignores   zParserElement.ignorecCs"|pt|p t|ptf|_d|_|S)zT Enable display of debugging messages while doing pattern matching. T)r/r2r4rcr^)rZ startActionZ successActionZexceptionActionrwrwrxsetDebugActions s  zParserElement.setDebugActionscCs|r|jtttnd|_|S)a Enable display of debugging messages while doing pattern matching. Set C{flag} to True to enable, False to disable. Example:: wd = Word(alphas).setName("alphaword") integer = Word(nums).setName("numword") term = wd | integer # turn on debugging for wd wd.setDebug() OneOrMore(term).parseString("abc 123 xyz 890") prints:: Match alphaword at loc 0(1,1) Matched alphaword -> ['abc'] Match alphaword at loc 3(1,4) Exception raised:Expected alphaword (at char 4), (line:1, col:5) Match alphaword at loc 7(1,8) Matched alphaword -> ['xyz'] Match alphaword at loc 11(1,12) Exception raised:Expected alphaword (at char 12), (line:1, col:13) Match alphaword at loc 15(1,16) Exception raised:Expected alphaword (at char 15), (line:1, col:16) The output shown is that produced by the default debug actions - custom debug actions can be specified using L{setDebugActions}. Prior to attempting to match the C{wd} expression, the debugging message C{"Match at loc (,)"} is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"} message is shown. Also note the use of L{setName} to assign a human-readable name to the expression, which makes debugging and exception messages easier to understand - for instance, the default name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}. F)rr/r2r4r^)rflagrwrwrxsetDebugs#zParserElement.setDebugcCs|jS)N)r)rrwrwrxr@szParserElement.__str__cCst|S)N)r)rrwrwrxrCszParserElement.__repr__cCsd|_d|_|S)NT)r_rU)rrwrwrxrFszParserElement.streamlinecCsdS)Nrw)rrrwrwrxcheckRecursionKszParserElement.checkRecursioncCs|jgdS)zj Check defined expressions for valid structure, check for infinite recursive definitions. N)r)r validateTracerwrwrxvalidateNszParserElement.validatecCsy |j}Wn2tk r>t|d}|j}WdQRXYnXy |j||Stk r|}ztjrhn|WYdd}~XnXdS)z Execute the parse expression on the given file or filename. If a filename is specified (instead of a file object), the entire file is opened, read, and closed before parsing. rN)readropenrrr$r)rZfile_or_filenamerZ file_contentsfr3rwrwrx parseFileTs   zParserElement.parseFilecsHt|tr"||kp t|t|kSt|tr6|j|Stt||kSdS)N)rzr$varsrrsuper)rr)rHrwrx__eq__hs    zParserElement.__eq__cCs ||k S)Nrw)rrrwrwrx__ne__pszParserElement.__ne__cCs tt|S)N)hashid)rrwrwrx__hash__sszParserElement.__hash__cCs||kS)Nrw)rrrwrwrx__req__vszParserElement.__req__cCs ||k S)Nrw)rrrwrwrx__rne__yszParserElement.__rne__c Cs0y|jt||ddStk r*dSXdS)a Method for quick testing of a parser against a test string. Good for simple inline microtests of sub expressions while building up larger parser. Parameters: - testString - to test against this expression for a match - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests Example:: expr = Word(nums) assert expr.matches("100") )rTFN)rrr)rZ testStringrrwrwrxr|s zParserElement.matches#cCst|tr"tttj|jj}t|tr4t|}g}g}d} x|D]} |dk rb|j | dsl|rx| rx|j | qH| s~qHdj || g} g}y:| j dd} |j | |d} | j | j|d| o| } Wntk rx} zt| trdnd }d| kr0| j t| j| | j d t| j| d d |n| j d | jd || j d t| | ob|} | } WYdd} ~ XnDtk r}z&| j dt|| o|} |} WYdd}~XnX|r|r| j d tdj | |j | | fqHW| |fS)a3 Execute the parse expression on a series of test strings, showing each test, the parsed results or where the parse failed. Quick and easy way to run a parse expression against a list of sample strings. Parameters: - tests - a list of separate test strings, or a multiline string of test strings - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests - comment - (default=C{'#'}) - expression for indicating embedded comments in the test string; pass None to disable comment filtering - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline; if False, only dump nested list - printResults - (default=C{True}) prints test output to stdout - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing Returns: a (success, results) tuple, where success indicates that all tests succeeded (or failed if C{failureTests} is True), and the results contain a list of lines of each test's output Example:: number_expr = pyparsing_common.number.copy() result = number_expr.runTests(''' # unsigned integer 100 # negative integer -100 # float with scientific notation 6.02e23 # integer with scientific notation 1e-12 ''') print("Success" if result[0] else "Failed!") result = number_expr.runTests(''' # stray character 100Z # missing leading digit before '.' -.100 # too many '.' 3.14.159 ''', failureTests=True) print("Success" if result[0] else "Failed!") prints:: # unsigned integer 100 [100] # negative integer -100 [-100] # float with scientific notation 6.02e23 [6.02e+23] # integer with scientific notation 1e-12 [1e-12] Success # stray character 100Z ^ FAIL: Expected end of text (at char 3), (line:1, col:4) # missing leading digit before '.' -.100 ^ FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) # too many '.' 3.14.159 ^ FAIL: Expected end of text (at char 4), (line:1, col:5) Success Each test string must be on a single line. If you want to test a string that spans multiple lines, create a test like this:: expr.runTest(r"this is a test\n of strings that spans \n 3 lines") (Note that this is a raw string literal, you must include the leading 'r'.) TNFrz\n)r)r z(FATAL)r rr^zFAIL: zFAIL-EXCEPTION: )rzrrrvr{rrstrip splitlinesrrrrrrrrr!rGrr9rKr,)rZtestsrZcommentZfullDumpZ printResultsZ failureTestsZ allResultsZcommentssuccessrvr resultrrzr3rwrwrxrunTestssNW     $   zParserElement.runTests)F)F)T)T)TT)TT)r)F)N)T)F)T)TrTTF)OrrrrrNr staticmethodrPrRrrrirmrurrxr~rrrrrrrrrrrrrrrrrrtrrrr_MAX_INTrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr __classcell__rwrw)rHrxr$8s     &     H   " 2G+    D           )    cs eZdZdZfddZZS)r,zT Abstract C{ParserElement} subclass, for defining atomic matching patterns. cstt|jdddS)NF)rg)rr,r)r)rHrwrxr szToken.__init__)rrrrrrrwrw)rHrxr, scs eZdZdZfddZZS)r z, An empty token, will always match. cs$tt|jd|_d|_d|_dS)Nr TF)rr rrr[r`)r)rHrwrxr szEmpty.__init__)rrrrrrrwrw)rHrxr  scs*eZdZdZfddZdddZZS)rz( A token that will never match. cs*tt|jd|_d|_d|_d|_dS)NrTFzUnmatchable token)rrrrr[r`ra)r)rHrwrxr* s zNoMatch.__init__TcCst|||j|dS)N)rra)rr-rrorwrwrxr1 szNoMatch.parseImpl)T)rrrrrrrrwrw)rHrxr& s cs*eZdZdZfddZdddZZS)ra Token to exactly match a specified string. Example:: Literal('blah').parseString('blah') # -> ['blah'] Literal('blah').parseString('blahfooblah') # -> ['blah'] Literal('blah').parseString('bla') # -> Exception: Expected "blah" For case-insensitive matching, use L{CaselessLiteral}. For keyword matching (force word break before and after the matched string), use L{Keyword} or L{CaselessKeyword}. c stt|j||_t||_y|d|_Wn*tk rVtj dt ddt |_ YnXdt |j|_d|j|_d|_d|_dS)Nrz2null string passed to Literal; use Empty() insteadrq)rz"%s"z Expected F)rrrmatchrmatchLenfirstMatchCharrrrrr rHrrrar[r`)r matchString)rHrwrxrC s    zLiteral.__init__TcCsJ|||jkr6|jdks&|j|j|r6||j|jfSt|||j|dS)Nrr)rr startswithrrra)rr-rrorwrwrxrV szLiteral.parseImpl)T)rrrrrrrrwrw)rHrxr5 s  csLeZdZdZedZdfdd Zddd Zfd d Ze d d Z Z S)ra\ Token to exactly match a specified string as a keyword, that is, it must be immediately followed by a non-keyword character. Compare with C{L{Literal}}: - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}. - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'} Accepts two optional constructor arguments in addition to the keyword string: - C{identChars} is a string of characters that would be valid identifier characters, defaulting to all alphanumerics + "_" and "$" - C{caseless} allows case-insensitive matching, default is C{False}. Example:: Keyword("start").parseString("start") # -> ['start'] Keyword("start").parseString("starting") # -> Exception For case-insensitive matching, use L{CaselessKeyword}. z_$NFc stt|j|dkrtj}||_t||_y|d|_Wn$tk r^t j dt ddYnXd|j|_ d|j |_ d|_d|_||_|r|j|_|j}t||_dS)Nrz2null string passed to Keyword; use Empty() insteadrq)rz"%s"z Expected F)rrrDEFAULT_KEYWORD_CHARSrrrrrrrrrrar[r`caselessupper caselessmatchr identChars)rrrr)rHrwrxrq s&    zKeyword.__init__TcCs|jr|||||jj|jkr|t||jksL|||jj|jkr|dksj||dj|jkr||j|jfSnv|||jkr|jdks|j|j|r|t||jks|||j|jkr|dks||d|jkr||j|jfSt |||j |dS)Nrrr) rrrrrrrrrrra)rr-rrorwrwrxr s*&zKeyword.parseImplcstt|j}tj|_|S)N)rrrrr)rr)rHrwrxr sz Keyword.copycCs |t_dS)z,Overrides the default Keyword chars N)rr)rOrwrwrxsetDefaultKeywordChars szKeyword.setDefaultKeywordChars)NF)T) rrrrr3rrrrrrrrwrw)rHrxr^ s   cs*eZdZdZfddZdddZZS)ral Token to match a specified string, ignoring case of letters. Note: the matched results will always be in the case of the given match string, NOT the case of the input text. Example:: OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] (Contrast with example for L{CaselessKeyword}.) cs6tt|j|j||_d|j|_d|j|_dS)Nz'%s'z Expected )rrrr returnStringrra)rr)rHrwrxr s zCaselessLiteral.__init__TcCs@||||jj|jkr,||j|jfSt|||j|dS)N)rrrrrra)rr-rrorwrwrxr szCaselessLiteral.parseImpl)T)rrrrrrrrwrw)rHrxr s  cs,eZdZdZdfdd Zd ddZZS) rz Caseless version of L{Keyword}. Example:: OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] (Contrast with example for L{CaselessLiteral}.) Ncstt|j||dddS)NT)r)rrr)rrr)rHrwrxr szCaselessKeyword.__init__TcCsj||||jj|jkrV|t||jksF|||jj|jkrV||j|jfSt|||j|dS)N)rrrrrrrra)rr-rrorwrwrxr s*zCaselessKeyword.parseImpl)N)T)rrrrrrrrwrw)rHrxr scs,eZdZdZdfdd Zd ddZZS) rlax A variation on L{Literal} which matches "close" matches, that is, strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters: - C{match_string} - string to be matched - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match The results from a successful parse will contain the matched text from the input string and the following named results: - C{mismatches} - a list of the positions within the match_string where mismatches were found - C{original} - the original match_string used to compare against the input string If C{mismatches} is an empty list, then the match was an exact match. Example:: patt = CloseMatch("ATCATCGAATGGA") patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) # exact match patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) # close match allowing up to 2 mismatches patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) rrcsBtt|j||_||_||_d|j|jf|_d|_d|_dS)Nz&Expected %r (with up to %d mismatches)F) rrlrr match_string maxMismatchesrar`r[)rrr)rHrwrxr szCloseMatch.__init__TcCs|}t|}|t|j}||kr|j}d}g} |j} xtt||||jD]0\}} | \} } | | krP| j|t| | krPPqPW|d}t|||g}|j|d<| |d<||fSt|||j|dS)Nrrroriginal mismatches) rrrrrrr"rra)rr-rrostartrmaxlocrZmatch_stringlocrrZs_msrcmatresultsrwrwrxr s("   zCloseMatch.parseImpl)rr)T)rrrrrrrrwrw)rHrxrl s cs8eZdZdZd fdd Zdd d Zfd d ZZS)r/a Token for matching words composed of allowed character sets. Defined with string containing all allowed initial characters, an optional string containing allowed body characters (if omitted, defaults to the initial character set), and an optional minimum, maximum, and/or exact length. The default value for C{min} is 1 (a minimum value < 1 is not valid); the default values for C{max} and C{exact} are 0, meaning no maximum or exact length restriction. An optional C{excludeChars} parameter can list characters that might be found in the input C{bodyChars} string; useful to define a word of all printables except for one or two characters, for instance. L{srange} is useful for defining custom character set strings for defining C{Word} expressions, using range notation from regular expression character sets. A common mistake is to use C{Word} to match a specific literal string, as in C{Word("Address")}. Remember that C{Word} uses the string argument to define I{sets} of matchable characters. This expression would match "Add", "AAA", "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'. To match an exact literal string, use L{Literal} or L{Keyword}. pyparsing includes helper strings for building Words: - L{alphas} - L{nums} - L{alphanums} - L{hexnums} - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.) - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.) - L{printables} (any non-whitespace character) Example:: # a word composed of digits integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) # a word with a leading capital, and zero or more lowercase capital_word = Word(alphas.upper(), alphas.lower()) # hostnames are alphanumeric, with leading alpha, and '-' hostname = Word(alphas, alphanums+'-') # roman numeral (not a strict parser, accepts invalid mix of characters) roman = Word("IVXLCDM") # any string of non-whitespace characters, except for ',' csv_value = Word(printables, excludeChars=",") NrrrFc stt|jrFdjfdd|D}|rFdjfdd|D}||_t||_|rl||_t||_n||_t||_|dk|_ |dkrt d||_ |dkr||_ nt |_ |dkr||_ ||_ t||_d|j|_d |_||_d |j|jkr|dkr|dkr|dkr|j|jkr8d t|j|_nHt|jdkrfd tj|jt|jf|_nd t|jt|jf|_|jrd|jd|_ytj|j|_Wntk rd|_YnXdS)Nrc3s|]}|kr|VqdS)Nrw)rr) excludeCharsrwrxr7 sz Word.__init__..c3s|]}|kr|VqdS)Nrw)rr)rrwrxr9 srrrzZcannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permittedz Expected Frz[%s]+z%s[%s]*z [%s][%s]*z\b)rr/rr initCharsOrigr initChars bodyCharsOrig bodyChars maxSpecifiedrminLenmaxLenrrrrar` asKeyword_escapeRegexRangeCharsreStringrrdescapecompilerK)rrrminmaxexactrr)rH)rrxr4 sT      0 z Word.__init__Tc CsD|jr<|jj||}|s(t|||j||j}||jfS|||jkrZt|||j||}|d7}t|}|j}||j }t ||}x ||kr|||kr|d7}qWd} |||j krd} |j r||kr|||krd} |j r|dkr||d|ks||kr|||krd} | r4t|||j|||||fS)NrrFTr)rdrrraendgrouprrrrr rrr) rr-rrorrrZ bodycharsrZthrowExceptionrwrwrxrj s6    4zWord.parseImplc stytt|jStk r"YnX|jdkrndd}|j|jkr^d||j||jf|_nd||j|_|jS)NcSs$t|dkr|dddS|SdS)Nz...)r)rrwrwrx charsAsStr s z Word.__str__..charsAsStrz W:(%s,%s)zW:(%s))rr/rrKrUrr)rr)rHrwrxr s  z Word.__str__)NrrrrFN)T)rrrrrrrrrwrw)rHrxr/ s.6 #csFeZdZdZeejdZd fdd Zd ddZ fd d Z Z S) r'a Token for matching strings that match a given regular expression. Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. If the given regex contains named groups (defined using C{(?P...)}), these will be preserved as named parse results. Example:: realnum = Regex(r"[+-]?\d+\.\d*") date = Regex(r'(?P\d{4})-(?P\d\d?)-(?P\d\d?)') # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") z[A-Z]rc stt|jt|tr|s,tjdtdd||_||_ yt j |j|j |_ |j|_ Wqt jk rtjd|tddYqXn2t|tjr||_ t||_|_ ||_ ntdt||_d|j|_d|_d|_d S) zThe parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags.z0null string passed to Regex; use Empty() insteadrq)rz$invalid pattern (%s) passed to RegexzCRegex may only be constructed with a string or a compiled RE objectz Expected FTN)rr'rrzrrrrpatternflagsrdr r sre_constantserrorcompiledREtyper{rrrrar`r[)rrr)rHrwrxr s.         zRegex.__init__TcCsd|jj||}|s"t|||j||j}|j}t|j}|r\x|D]}||||<qHW||fS)N)rdrrrar groupdictr"r)rr-rrordrrrwrwrxr s  zRegex.parseImplc sDytt|jStk r"YnX|jdkr>dt|j|_|jS)NzRe:(%s))rr'rrKrUrr)r)rHrwrxr s z Regex.__str__)r)T) rrrrrrdr rrrrrrwrw)rHrxr' s  " cs8eZdZdZd fdd Zd ddZfd d ZZS) r%a Token for matching strings that are delimited by quoting characters. Defined with the following parameters: - quoteChar - string of one or more characters defining the quote delimiting string - escChar - character to escape quotes, typically backslash (default=C{None}) - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None}) - multiline - boolean indicating whether quotes can span multiple lines (default=C{False}) - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True}) - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar) - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True}) Example:: qs = QuotedString('"') print(qs.searchString('lsjdf "This is the quote" sldjf')) complex_qs = QuotedString('{{', endQuoteChar='}}') print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) sql_qs = QuotedString('"', escQuote='""') print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) prints:: [['This is the quote']] [['This is the "quote"']] [['This is the quote with "embedded" quotes']] NFTc sNttj|j}|s0tjdtddt|dkr>|}n"|j}|s`tjdtddt|_t |_ |d_ |_ t |_ |_|_|_|_|rtjtjB_dtjjtj d|dk rt|pdf_n.)z|(?:%s)z|(?:%s.)z(.)z)*%sz$invalid pattern (%s) passed to Regexz Expected FTrs)%rr%rrrrr SyntaxError quoteCharr quoteCharLenfirstQuoteCharrendQuoteCharLenescCharescQuoteunquoteResultsconvertWhitespaceEscapesrd MULTILINEDOTALLrr rrrrescCharReplacePatternr rrrrrrar`r[)rrr r!Z multiliner"rr#)rH)rrxr sf       6     zQuotedString.__init__c Cs|||jkr|jj||pd}|s4t|||j||j}|j}|jr||j|j }t |t rd|kr|j rddddd}x |j D]\}}|j||}qW|jrtj|jd|}|jr|j|j|j}||fS)N\ r  )z\tz\nz\fz\rz\g<1>)rrdrrrarrr"rrrzrr#rrr rr&r!r) rr-rrorrZws_mapZwslitZwscharrwrwrxrG s(  zQuotedString.parseImplc sFytt|jStk r"YnX|jdkr@d|j|jf|_|jS)Nz.quoted string, starting with %s ending with %s)rr%rrKrUrr)r)rHrwrxrj s zQuotedString.__str__)NNFTNT)T)rrrrrrrrrwrw)rHrxr% sA #cs8eZdZdZd fdd Zd ddZfd d ZZS) r a Token for matching words composed of characters I{not} in a given set (will include whitespace in matched characters if not listed in the provided exclusion set - see example). Defined with string containing all disallowed characters, and an optional minimum, maximum, and/or exact length. The default value for C{min} is 1 (a minimum value < 1 is not valid); the default values for C{max} and C{exact} are 0, meaning no maximum or exact length restriction. Example:: # define a comma-separated-value as anything that is not a ',' csv_value = CharsNotIn(',') print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) prints:: ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] rrrcstt|jd|_||_|dkr*td||_|dkr@||_nt|_|dkrZ||_||_t ||_ d|j |_ |jdk|_ d|_ dS)NFrrzfcannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permittedrz Expected )rr rrXnotCharsrrrrrrrar[r`)rr+r r r )rHrwrxr s    zCharsNotIn.__init__TcCs|||jkrt|||j||}|d7}|j}t||jt|}x ||krd|||krd|d7}qFW|||jkrt|||j|||||fS)Nrr)r+rrar rrr)rr-rrorZnotcharsmaxlenrwrwrxr s   zCharsNotIn.parseImplc sdytt|jStk r"YnX|jdkr^t|jdkrRd|jdd|_n d|j|_|jS)Nrz !W:(%s...)z!W:(%s))rr rrKrUrr+)r)rHrwrxr s  zCharsNotIn.__str__)rrrr)T)rrrrrrrrrwrw)rHrxr v s cs<eZdZdZddddddZdfd d ZdddZZS)r.a Special matching class for matching whitespace. Normally, whitespace is ignored by pyparsing grammars. This class is included when some whitespace structures are significant. Define with a string containing the whitespace characters to be matched; default is C{" \t\r\n"}. Also takes optional C{min}, C{max}, and C{exact} arguments, as defined for the C{L{Word}} class. zzzzz)rr(rr*r) rrrcsttj|_jdjfddjDdjddjD_d_dj_ |_ |dkrt|_ nt _ |dkr|_ |_ dS)Nrc3s|]}|jkr|VqdS)N) matchWhite)rr)rrwrxr sz!White.__init__..css|]}tj|VqdS)N)r. whiteStrs)rrrwrwrxr sTz Expected r) rr.rr.rrrYrr[rarrr)rZwsr r r )rH)rrxr s  zWhite.__init__TcCs|||jkrt|||j||}|d7}||j}t|t|}x"||krd|||jkrd|d7}qDW|||jkrt|||j|||||fS)Nrr)r.rrarr rr)rr-rrorrrwrwrxr s  zWhite.parseImpl)r-rrrr)T)rrrrr/rrrrwrw)rHrxr. scseZdZfddZZS)_PositionTokencs(tt|j|jj|_d|_d|_dS)NTF)rr0rrHrrr[r`)r)rHrwrxr s z_PositionToken.__init__)rrrrrrwrw)rHrxr0 sr0cs2eZdZdZfddZddZd ddZZS) rzb Token to advance to a specific column of input text; useful for tabular report scraping. cstt|j||_dS)N)rrrr9)rcolno)rHrwrxr szGoToColumn.__init__cCs`t|||jkr\t|}|jr*|j||}x0||krZ||jrZt|||jkrZ|d7}q,W|S)Nrr)r9rr]risspace)rr-rrrwrwrxr s & zGoToColumn.preParseTcCsDt||}||jkr"t||d|||j|}|||}||fS)NzText not in expected column)r9r)rr-rroZthiscolZnewlocrrwrwrxr s    zGoToColumn.parseImpl)T)rrrrrrrrrwrw)rHrxr s  cs*eZdZdZfddZdddZZS)ra Matches if current position is at the beginning of a line within the parse string Example:: test = ''' AAA this line AAA and this line AAA but not this one B AAA and definitely not this one ''' for t in (LineStart() + 'AAA' + restOfLine).searchString(test): print(t) Prints:: ['AAA', ' this line'] ['AAA', ' and this line'] cstt|jd|_dS)NzExpected start of line)rrrra)r)rHrwrxr& szLineStart.__init__TcCs*t||dkr|gfSt|||j|dS)Nrr)r9rra)rr-rrorwrwrxr* szLineStart.parseImpl)T)rrrrrrrrwrw)rHrxr s cs*eZdZdZfddZdddZZS)rzU Matches if current position is at the end of a line within the parse string cs,tt|j|jtjjddd|_dS)NrrzExpected end of line)rrrrr$rNrra)r)rHrwrxr3 szLineEnd.__init__TcCsb|t|kr6||dkr$|ddfSt|||j|n(|t|krN|dgfSt|||j|dS)Nrrr)rrra)rr-rrorwrwrxr8 s     zLineEnd.parseImpl)T)rrrrrrrrwrw)rHrxr/ s cs*eZdZdZfddZdddZZS)r*zM Matches if current position is at the beginning of the parse string cstt|jd|_dS)NzExpected start of text)rr*rra)r)rHrwrxrG szStringStart.__init__TcCs0|dkr(||j|dkr(t|||j||gfS)Nr)rrra)rr-rrorwrwrxrK szStringStart.parseImpl)T)rrrrrrrrwrw)rHrxr*C s cs*eZdZdZfddZdddZZS)r)zG Matches if current position is at the end of the parse string cstt|jd|_dS)NzExpected end of text)rr)rra)r)rHrwrxrV szStringEnd.__init__TcCs^|t|krt|||j|n<|t|kr6|dgfS|t|krJ|gfSt|||j|dS)Nrr)rrra)rr-rrorwrwrxrZ s    zStringEnd.parseImpl)T)rrrrrrrrwrw)rHrxr)R s cs.eZdZdZeffdd ZdddZZS)r1ap Matches if the current position is at the beginning of a Word, and is not preceded by any character in a given set of C{wordChars} (default=C{printables}). To emulate the C{} behavior of regular expressions, use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of the string being parsed, or at the beginning of a line. cs"tt|jt||_d|_dS)NzNot at the start of a word)rr1rr wordCharsra)rr3)rHrwrxrl s zWordStart.__init__TcCs@|dkr8||d|jks(|||jkr8t|||j||gfS)Nrrr)r3rra)rr-rrorwrwrxrq s zWordStart.parseImpl)T)rrrrrVrrrrwrw)rHrxr1d scs.eZdZdZeffdd ZdddZZS)r0aZ Matches if the current position is at the end of a Word, and is not followed by any character in a given set of C{wordChars} (default=C{printables}). To emulate the C{} behavior of regular expressions, use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of the string being parsed, or at the end of a line. cs(tt|jt||_d|_d|_dS)NFzNot at the end of a word)rr0rrr3rXra)rr3)rHrwrxr s zWordEnd.__init__TcCsPt|}|dkrH||krH|||jks8||d|jkrHt|||j||gfS)Nrrr)rr3rra)rr-rrorrwrwrxr s zWordEnd.parseImpl)T)rrrrrVrrrrwrw)rHrxr0x scseZdZdZdfdd ZddZddZd d Zfd d Zfd dZ fddZ dfdd Z gfddZ fddZ ZS)r z^ Abstract subclass of ParserElement, for combining and post-processing parsed tokens. Fc stt|j|t|tr"t|}t|tr.F)rr rrzrrrr$rQexprsrIterableallrvrre)rr4rg)rHrwrxr s     zParseExpression.__init__cCs |j|S)N)r4)rrrwrwrxr szParseExpression.__getitem__cCs|jj|d|_|S)N)r4rrU)rrrwrwrxr s zParseExpression.appendcCs4d|_dd|jD|_x|jD] }|jq W|S)z~Extends C{leaveWhitespace} defined in base class, and also invokes C{leaveWhitespace} on all contained expressions.FcSsg|] }|jqSrw)r)rrrwrwrxr sz3ParseExpression.leaveWhitespace..)rXr4r)rrrwrwrxr s   zParseExpression.leaveWhitespacecszt|trF||jkrvtt|j|xP|jD]}|j|jdq,Wn0tt|j|x|jD]}|j|jdq^W|S)Nrrrsrs)rzr+r]rr rr4)rrr)rHrwrxr s    zParseExpression.ignorec sLytt|jStk r"YnX|jdkrFd|jjt|jf|_|jS)Nz%s:(%s)) rr rrKrUrHrrr4)r)rHrwrxr s zParseExpression.__str__cs0tt|jx|jD] }|jqWt|jdkr|jd}t||jr|j r|jdkr|j r|jdd|jdg|_d|_ |j |j O_ |j |j O_ |jd}t||jo|j o|jdko|j r|jdd|jdd|_d|_ |j |j O_ |j |j O_ dt ||_|S)Nrqrrrz Expected rsrs)rr rr4rrzrHrSrVr^rUr[r`rra)rrr)rHrwrxr s0         zParseExpression.streamlinecstt|j||}|S)N)rr rm)rrrlr)rHrwrxrm szParseExpression.setResultsNamecCs:|dd|g}x|jD]}|j|qW|jgdS)N)r4rr)rrtmprrwrwrxr s zParseExpression.validatecs$tt|j}dd|jD|_|S)NcSsg|] }|jqSrw)r)rrrwrwrxr sz(ParseExpression.copy..)rr rr4)rr)rHrwrxr szParseExpression.copy)F)F)rrrrrrrrrrrrmrrrrwrw)rHrxr s " csTeZdZdZGdddeZdfdd ZdddZd d Zd d Z d dZ Z S)ra  Requires all given C{ParseExpression}s to be found in the given order. Expressions may be separated by whitespace. May be constructed using the C{'+'} operator. May also be constructed using the C{'-'} operator, which will suppress backtracking. Example:: integer = Word(nums) name_expr = OneOrMore(Word(alphas)) expr = And([integer("id"),name_expr("name"),integer("age")]) # more easily written as: expr = integer("id") + name_expr("name") + integer("age") cseZdZfddZZS)zAnd._ErrorStopcs&ttj|j||d|_|jdS)N-)rrrrrr)rrr)rHrwrxr szAnd._ErrorStop.__init__)rrrrrrwrw)rHrxr srTcsRtt|j||tdd|jD|_|j|jdj|jdj|_d|_ dS)Ncss|] }|jVqdS)N)r[)rrrwrwrxr szAnd.__init__..rT) rrrr6r4r[rrYrXre)rr4rg)rHrwrxr s z And.__init__c Cs|jdj|||dd\}}d}x|jddD]}t|tjrFd}q0|ry|j|||\}}Wqtk rvYqtk r}zd|_tj|WYdd}~Xqt k rt|t ||j |YqXn|j|||\}}|s|j r0||7}q0W||fS)NrF)rprrT) r4rtrzrrr#r __traceback__rrrrar) rr-rro resultlistZ errorStoprZ exprtokensrrwrwrxr s(   z And.parseImplcCst|trtj|}|j|S)N)rzrr$rQr)rrrwrwrxr5 s  z And.__iadd__cCs8|dd|g}x |jD]}|j||jsPqWdS)N)r4rr[)rrsubRecCheckListrrwrwrxr: s   zAnd.checkRecursioncCs@t|dr|jS|jdkr:ddjdd|jDd|_|jS)Nr{rcss|]}t|VqdS)N)r)rrrwrwrxrF szAnd.__str__..})rrrUrr4)rrwrwrxrA s    z And.__str__)T)T) rrrrr rrrrrrrrwrw)rHrxr s csDeZdZdZdfdd ZdddZdd Zd d Zd d ZZ S)ra Requires that at least one C{ParseExpression} is found. If two expressions match, the expression that matches the longest string will be used. May be constructed using the C{'^'} operator. Example:: # construct Or using '^' operator number = Word(nums) ^ Combine(Word(nums) + '.' + Word(nums)) print(number.searchString("123 3.1416 789")) prints:: [['123'], ['3.1416'], ['789']] Fcs:tt|j|||jr0tdd|jD|_nd|_dS)Ncss|] }|jVqdS)N)r[)rrrwrwrxr\ szOr.__init__..T)rrrr4rr[)rr4rg)rHrwrxrY sz Or.__init__Tc CsTd}d}g}x|jD]}y|j||}Wnvtk rd} z d| _| j|krT| }| j}WYdd} ~ Xqtk rt||krt|t||j|}t|}YqX|j||fqW|r*|j dddx`|D]X\} }y|j |||Stk r$} z"d| _| j|kr| }| j}WYdd} ~ XqXqW|dk rB|j|_ |nt||d|dS)NrrcSs |d S)Nrrw)xrwrwrxryu szOr.parseImpl..)rz no defined alternatives to matchrs) r4rrr9rrrrarsortrtr) rr-rro maxExcLoc maxExceptionrrZloc2r_rwrwrxr` s<     z Or.parseImplcCst|trtj|}|j|S)N)rzrr$rQr)rrrwrwrx__ixor__ s  z Or.__ixor__cCs@t|dr|jS|jdkr:ddjdd|jDd|_|jS)Nrr<z ^ css|]}t|VqdS)N)r)rrrwrwrxr szOr.__str__..r=)rrrUrr4)rrwrwrxr s    z Or.__str__cCs0|dd|g}x|jD]}|j|qWdS)N)r4r)rrr;rrwrwrxr s zOr.checkRecursion)F)T) rrrrrrrCrrrrwrw)rHrxrK s   & csDeZdZdZdfdd ZdddZdd Zd d Zd d ZZ S)ra Requires that at least one C{ParseExpression} is found. If two expressions match, the first one listed is the one that will match. May be constructed using the C{'|'} operator. Example:: # construct MatchFirst using '|' operator # watch the order of expressions to match number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] # put more selective expression first number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] Fcs:tt|j|||jr0tdd|jD|_nd|_dS)Ncss|] }|jVqdS)N)r[)rrrwrwrxr sz&MatchFirst.__init__..T)rrrr4rr[)rr4rg)rHrwrxr szMatchFirst.__init__Tc Csd}d}x|jD]}y|j|||}|Stk r\}z|j|krL|}|j}WYdd}~Xqtk rt||krt|t||j|}t|}YqXqW|dk r|j|_|nt||d|dS)Nrrz no defined alternatives to matchrs)r4rtrrrrrar) rr-rror@rArrrrwrwrxr s$   zMatchFirst.parseImplcCst|trtj|}|j|S)N)rzrr$rQr)rrrwrwrx__ior__ s  zMatchFirst.__ior__cCs@t|dr|jS|jdkr:ddjdd|jDd|_|jS)Nrr<z | css|]}t|VqdS)N)r)rrrwrwrxr sz%MatchFirst.__str__..r=)rrrUrr4)rrwrwrxr s    zMatchFirst.__str__cCs0|dd|g}x|jD]}|j|qWdS)N)r4r)rrr;rrwrwrxr s zMatchFirst.checkRecursion)F)T) rrrrrrrDrrrrwrw)rHrxr s   cs<eZdZdZd fdd Zd ddZddZd d ZZS) r am Requires all given C{ParseExpression}s to be found, but in any order. Expressions may be separated by whitespace. May be constructed using the C{'&'} operator. Example:: color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") integer = Word(nums) shape_attr = "shape:" + shape_type("shape") posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") color_attr = "color:" + color("color") size_attr = "size:" + integer("size") # use Each (using operator '&') to accept attributes in any order # (shape and posn are required, color and size are optional) shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) shape_spec.runTests(''' shape: SQUARE color: BLACK posn: 100, 120 shape: CIRCLE size: 50 color: BLUE posn: 50,80 color:GREEN size:20 shape:TRIANGLE posn:20,40 ''' ) prints:: shape: SQUARE color: BLACK posn: 100, 120 ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] - color: BLACK - posn: ['100', ',', '120'] - x: 100 - y: 120 - shape: SQUARE shape: CIRCLE size: 50 color: BLUE posn: 50,80 ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] - color: BLUE - posn: ['50', ',', '80'] - x: 50 - y: 80 - shape: CIRCLE - size: 50 color: GREEN size: 20 shape: TRIANGLE posn: 20,40 ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] - color: GREEN - posn: ['20', ',', '40'] - x: 20 - y: 40 - shape: TRIANGLE - size: 20 Tcs8tt|j||tdd|jD|_d|_d|_dS)Ncss|] }|jVqdS)N)r[)rrrwrwrxrsz Each.__init__..T)rr rr6r4r[rXinitExprGroups)rr4rg)rHrwrxrsz Each.__init__c s|jrtdd|jD|_dd|jD}dd|jD}|||_dd|jD|_dd|jD|_dd|jD|_|j|j7_d |_|}|jdd}|jddg}d } x| rp||j|j} g} x~| D]v} y| j||}Wn t k r| j | YqX|j |jj t | | | |krD|j | q| krj | qWt| t| krd } qW|rd jd d|D} t ||d | |fdd|jD7}g}x*|D]"} | j|||\}}|j |qWt|tg}||fS)Ncss&|]}t|trt|j|fVqdS)N)rzrrr.)rrrwrwrxrsz!Each.parseImpl..cSsg|]}t|tr|jqSrw)rzrr.)rrrwrwrxrsz"Each.parseImpl..cSs"g|]}|jrt|t r|qSrw)r[rzr)rrrwrwrxrscSsg|]}t|tr|jqSrw)rzr2r.)rrrwrwrxr scSsg|]}t|tr|jqSrw)rzrr.)rrrwrwrxr!scSs g|]}t|tttfs|qSrw)rzrr2r)rrrwrwrxr"sFTz, css|]}t|VqdS)N)r)rrrwrwrxr=sz*Missing one or more required elements (%s)cs$g|]}t|tr|jkr|qSrw)rzrr.)rr)tmpOptrwrxrAs)rErr4Zopt1mapZ optionalsZmultioptionalsZ multirequiredZrequiredrrrrrremoverrrtsumr")rr-rroZopt1Zopt2ZtmpLocZtmpReqdZ matchOrderZ keepMatchingZtmpExprsZfailedrZmissingr:rZ finalResultsrw)rFrxrsP     zEach.parseImplcCs@t|dr|jS|jdkr:ddjdd|jDd|_|jS)Nrr<z & css|]}t|VqdS)N)r)rrrwrwrxrPszEach.__str__..r=)rrrUrr4)rrwrwrxrKs    z Each.__str__cCs0|dd|g}x|jD]}|j|qWdS)N)r4r)rrr;rrwrwrxrTs zEach.checkRecursion)T)T) rrrrrrrrrrwrw)rHrxr s 5 1 csleZdZdZdfdd ZdddZdd Zfd d Zfd d ZddZ gfddZ fddZ Z S)rza Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. Fcstt|j|t|tr@ttjtr2tj|}ntjt |}||_ d|_ |dk r|j |_ |j |_ |j|j|j|_|j|_|j|_|jj|jdS)N)rrrrzr issubclassr$rQr,rr.rUr`r[rrYrXrWrer]r)rr.rg)rHrwrxr^s    zParseElementEnhance.__init__TcCs2|jdk r|jj|||ddStd||j|dS)NF)rpr)r.rtrra)rr-rrorwrwrxrps zParseElementEnhance.parseImplcCs*d|_|jj|_|jdk r&|jj|S)NF)rXr.rr)rrwrwrxrvs    z#ParseElementEnhance.leaveWhitespacecsrt|trB||jkrntt|j||jdk rn|jj|jdn,tt|j||jdk rn|jj|jd|S)Nrrrsrs)rzr+r]rrrr.)rr)rHrwrxr}s    zParseElementEnhance.ignorecs&tt|j|jdk r"|jj|S)N)rrrr.)r)rHrwrxrs  zParseElementEnhance.streamlinecCsB||krt||g|dd|g}|jdk r>|jj|dS)N)r&r.r)rrr;rwrwrxrs  z"ParseElementEnhance.checkRecursioncCs6|dd|g}|jdk r(|jj||jgdS)N)r.rr)rrr7rwrwrxrs  zParseElementEnhance.validatec sVytt|jStk r"YnX|jdkrP|jdk rPd|jjt|jf|_|jS)Nz%s:(%s)) rrrrKrUr.rHrr)r)rHrwrxrszParseElementEnhance.__str__)F)T) rrrrrrrrrrrrrrwrw)rHrxrZs   cs*eZdZdZfddZdddZZS)ra Lookahead matching of the given parse expression. C{FollowedBy} does I{not} advance the parsing position within the input string, it only verifies that the specified parse expression matches at the current position. C{FollowedBy} always returns a null token list. Example:: # use FollowedBy to match a label only if it is followed by a ':' data_word = Word(alphas) label = data_word + FollowedBy(':') attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() prints:: [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] cstt|j|d|_dS)NT)rrrr[)rr.)rHrwrxrszFollowedBy.__init__TcCs|jj|||gfS)N)r.r)rr-rrorwrwrxrszFollowedBy.parseImpl)T)rrrrrrrrwrw)rHrxrs cs2eZdZdZfddZd ddZddZZS) ra Lookahead to disallow matching with the given parse expression. C{NotAny} does I{not} advance the parsing position within the input string, it only verifies that the specified parse expression does I{not} match at the current position. Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny} always returns a null token list. May be constructed using the '~' operator. Example:: cs0tt|j|d|_d|_dt|j|_dS)NFTzFound unwanted token, )rrrrXr[rr.ra)rr.)rHrwrxrszNotAny.__init__TcCs&|jj||rt|||j||gfS)N)r.rrra)rr-rrorwrwrxrszNotAny.parseImplcCs4t|dr|jS|jdkr.dt|jd|_|jS)Nrz~{r=)rrrUrr.)rrwrwrxrs   zNotAny.__str__)T)rrrrrrrrrwrw)rHrxrs   cs(eZdZdfdd ZdddZZS) _MultipleMatchNcsFtt|j|d|_|}t|tr.tj|}|dk r<|nd|_dS)NT) rrJrrWrzrr$rQ not_ender)rr.stopOnZender)rHrwrxrs   z_MultipleMatch.__init__Tc Cs|jj}|j}|jdk }|r$|jj}|r2|||||||dd\}}yZ|j } xJ|rb|||| rr|||} n|} ||| |\}} | s| jrT|| 7}qTWWnttfk rYnX||fS)NF)rp) r.rtrrKrr]rrr) rr-rroZself_expr_parseZself_skip_ignorablesZ check_enderZ try_not_enderrZhasIgnoreExprsrZ tmptokensrwrwrxrs,      z_MultipleMatch.parseImpl)N)T)rrrrrrrwrw)rHrxrJsrJc@seZdZdZddZdS)ra Repetition of one or more of the given expression. Parameters: - expr - expression that must match one or more times - stopOn - (default=C{None}) - expression for a terminating sentinel (only required if the sentinel would ordinarily match the repetition expression) Example:: data_word = Word(alphas) label = data_word + FollowedBy(':') attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) text = "shape: SQUARE posn: upper left color: BLACK" OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] # use stopOn attribute for OneOrMore to avoid reading label string as part of the data attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] # could also be written as (attr_expr * (1,)).parseString(text).pprint() cCs4t|dr|jS|jdkr.dt|jd|_|jS)Nrr<z}...)rrrUrr.)rrwrwrxr!s   zOneOrMore.__str__N)rrrrrrwrwrwrxrscs8eZdZdZd fdd Zd fdd Zdd ZZS) r2aw Optional repetition of zero or more of the given expression. Parameters: - expr - expression that must match zero or more times - stopOn - (default=C{None}) - expression for a terminating sentinel (only required if the sentinel would ordinarily match the repetition expression) Example: similar to L{OneOrMore} Ncstt|j||dd|_dS)N)rLT)rr2rr[)rr.rL)rHrwrxr6szZeroOrMore.__init__Tc s6ytt|j|||Sttfk r0|gfSXdS)N)rr2rrr)rr-rro)rHrwrxr:szZeroOrMore.parseImplcCs4t|dr|jS|jdkr.dt|jd|_|jS)Nrrz]...)rrrUrr.)rrwrwrxr@s   zZeroOrMore.__str__)N)T)rrrrrrrrrwrw)rHrxr2*s c@s eZdZddZeZddZdS) _NullTokencCsdS)NFrw)rrwrwrxrJsz_NullToken.__bool__cCsdS)Nrrw)rrwrwrxrMsz_NullToken.__str__N)rrrrr'rrwrwrwrxrMIsrMcs6eZdZdZeffdd Zd ddZddZZS) raa Optional matching of the given expression. Parameters: - expr - expression that must match zero or more times - default (optional) - value to be returned if the optional expression is not found. Example:: # US postal code can be a 5-digit zip, plus optional 4-digit qualifier zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) zip.runTests(''' # traditional ZIP code 12345 # ZIP+4 form 12101-0001 # invalid ZIP 98765- ''') prints:: # traditional ZIP code 12345 ['12345'] # ZIP+4 form 12101-0001 ['12101-0001'] # invalid ZIP 98765- ^ FAIL: Expected end of text (at char 5), (line:1, col:6) cs.tt|j|dd|jj|_||_d|_dS)NF)rgT)rrrr.rWrr[)rr.r)rHrwrxrts zOptional.__init__Tc Cszy|jj|||dd\}}WnTttfk rp|jtk rh|jjr^t|jg}|j||jj<ql|jg}ng}YnX||fS)NF)rp)r.rtrrr_optionalNotMatchedrVr")rr-rrorrwrwrxrzs    zOptional.parseImplcCs4t|dr|jS|jdkr.dt|jd|_|jS)Nrrr )rrrUrr.)rrwrwrxrs   zOptional.__str__)T) rrrrrNrrrrrwrw)rHrxrQs" cs,eZdZdZd fdd Zd ddZZS) r(a Token for skipping over all undefined text until the matched expression is found. Parameters: - expr - target expression marking the end of the data to be skipped - include - (default=C{False}) if True, the target expression is also parsed (the skipped text and target expression are returned as a 2-element list). - ignore - (default=C{None}) used to define grammars (typically quoted strings and comments) that might contain false matches to the target expression - failOn - (default=C{None}) define expressions that are not allowed to be included in the skipped test; if found before the target expression is found, the SkipTo is not a match Example:: report = ''' Outstanding Issues Report - 1 Jan 2000 # | Severity | Description | Days Open -----+----------+-------------------------------------------+----------- 101 | Critical | Intermittent system crash | 6 94 | Cosmetic | Spelling error on Login ('log|n') | 14 79 | Minor | System slow when running too many reports | 47 ''' integer = Word(nums) SEP = Suppress('|') # use SkipTo to simply match everything up until the next SEP # - ignore quoted strings, so that a '|' character inside a quoted string does not match # - parse action will call token.strip() for each matched token, i.e., the description body string_data = SkipTo(SEP, ignore=quotedString) string_data.setParseAction(tokenMap(str.strip)) ticket_expr = (integer("issue_num") + SEP + string_data("sev") + SEP + string_data("desc") + SEP + integer("days_open")) for tkt in ticket_expr.searchString(report): print tkt.dump() prints:: ['101', 'Critical', 'Intermittent system crash', '6'] - days_open: 6 - desc: Intermittent system crash - issue_num: 101 - sev: Critical ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] - days_open: 14 - desc: Spelling error on Login ('log|n') - issue_num: 94 - sev: Cosmetic ['79', 'Minor', 'System slow when running too many reports', '47'] - days_open: 47 - desc: System slow when running too many reports - issue_num: 79 - sev: Minor FNcs`tt|j|||_d|_d|_||_d|_t|t rFt j ||_ n||_ dt |j|_dS)NTFzNo match found for )rr(r ignoreExprr[r` includeMatchrrzrr$rQfailOnrr.ra)rrincluderrQ)rHrwrxrs zSkipTo.__init__Tc Cs,|}t|}|j}|jj}|jdk r,|jjnd}|jdk rB|jjnd} |} x| |kr|dk rh||| rhP| dk rx*y| || } Wqrtk rPYqrXqrWy||| dddWn tt fk r| d7} YqLXPqLWt|||j || }|||} t | } |j r$||||dd\}} | | 7} || fS)NF)rorprr)rp) rr.rtrQrrOrrrrrar"rP)rr-rror0rr.Z expr_parseZself_failOn_canParseNextZself_ignoreExpr_tryParseZtmplocZskiptextZ skipresultrrwrwrxrs<    zSkipTo.parseImpl)FNN)T)rrrrrrrrwrw)rHrxr(s6 csbeZdZdZdfdd ZddZddZd d Zd d Zgfd dZ ddZ fddZ Z S)raK Forward declaration of an expression to be defined later - used for recursive grammars, such as algebraic infix notation. When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator. Note: take care when assigning to C{Forward} not to overlook precedence of operators. Specifically, '|' has a lower precedence than '<<', so that:: fwdExpr << a | b | c will actually be evaluated as:: (fwdExpr << a) | b | c thereby leaving b and c out as parseable alternatives. It is recommended that you explicitly group the values inserted into the C{Forward}:: fwdExpr << (a | b | c) Converting to use the '<<=' operator instead will avoid this problem. See L{ParseResults.pprint} for an example of a recursive parser created using C{Forward}. Ncstt|j|dddS)NF)rg)rrr)rr)rHrwrxrszForward.__init__cCsjt|trtj|}||_d|_|jj|_|jj|_|j|jj |jj |_ |jj |_ |j j |jj |S)N)rzrr$rQr.rUr`r[rrYrXrWr]r)rrrwrwrx __lshift__s      zForward.__lshift__cCs||>S)Nrw)rrrwrwrx __ilshift__'szForward.__ilshift__cCs d|_|S)NF)rX)rrwrwrxr*szForward.leaveWhitespacecCs$|js d|_|jdk r |jj|S)NT)r_r.r)rrwrwrxr.s   zForward.streamlinecCs>||kr0|dd|g}|jdk r0|jj||jgdS)N)r.rr)rrr7rwrwrxr5s   zForward.validatec Cs>t|dr|jS|jjdSd}Wd|j|_X|jjd|S)Nrz: ...Nonez: )rrrHrZ _revertClass_ForwardNoRecurser.r)rZ retStringrwrwrxr<s   zForward.__str__cs.|jdk rtt|jSt}||K}|SdS)N)r.rrr)rr)rHrwrxrMs  z Forward.copy)N) rrrrrrSrTrrrrrrrwrw)rHrxrs  c@seZdZddZdS)rVcCsdS)Nz...rw)rrwrwrxrVsz_ForwardNoRecurse.__str__N)rrrrrwrwrwrxrVUsrVcs"eZdZdZdfdd ZZS)r-zQ Abstract subclass of C{ParseExpression}, for converting parsed results. Fcstt|j|d|_dS)NF)rr-rrW)rr.rg)rHrwrxr]szTokenConverter.__init__)F)rrrrrrrwrw)rHrxr-Yscs6eZdZdZd fdd ZfddZdd ZZS) r a Converter to concatenate all matching tokens to a single string. By default, the matching patterns must also be contiguous in the input string; this can be disabled by specifying C{'adjacent=False'} in the constructor. Example:: real = Word(nums) + '.' + Word(nums) print(real.parseString('3.1416')) # -> ['3', '.', '1416'] # will also erroneously match the following print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] real = Combine(Word(nums) + '.' + Word(nums)) print(real.parseString('3.1416')) # -> ['3.1416'] # no match when there are internal spaces print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) rTcs8tt|j||r|j||_d|_||_d|_dS)NT)rr rradjacentrX joinStringre)rr.rXrW)rHrwrxrrszCombine.__init__cs(|jrtj||ntt|j||S)N)rWr$rrr )rr)rHrwrxr|szCombine.ignorecCsP|j}|dd=|tdj|j|jg|jd7}|jrH|jrH|gS|SdS)Nr)r)rr"rr rXrbrVr)rr-rrZretToksrwrwrxrs  "zCombine.postParse)rT)rrrrrrrrrwrw)rHrxr as cs(eZdZdZfddZddZZS)ra Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions. Example:: ident = Word(alphas) num = Word(nums) term = ident | num func = ident + Optional(delimitedList(term)) print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] func = ident + Group(Optional(delimitedList(term))) print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] cstt|j|d|_dS)NT)rrrrW)rr.)rHrwrxrszGroup.__init__cCs|gS)Nrw)rr-rrrwrwrxrszGroup.postParse)rrrrrrrrwrw)rHrxrs  cs(eZdZdZfddZddZZS)r aW Converter to return a repetitive expression as a list, but also as a dictionary. Each element can also be referenced using the first token in the expression as its key. Useful for tabular report scraping when the first column can be used as a item key. Example:: data_word = Word(alphas) label = data_word + FollowedBy(':') attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) text = "shape: SQUARE posn: upper left color: light blue texture: burlap" attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) # print attributes as plain groups print(OneOrMore(attr_expr).parseString(text).dump()) # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names result = Dict(OneOrMore(Group(attr_expr))).parseString(text) print(result.dump()) # access named fields as dict entries, or output as dict print(result['shape']) print(result.asDict()) prints:: ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - color: light blue - posn: upper left - shape: SQUARE - texture: burlap SQUARE {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} See more examples at L{ParseResults} of accessing fields by results name. cstt|j|d|_dS)NT)rr rrW)rr.)rHrwrxrsz Dict.__init__cCsxt|D]\}}t|dkr q |d}t|trBt|dj}t|dkr^td|||<q t|dkrt|dt rt|d|||<q |j}|d=t|dkst|tr|j rt||||<q t|d|||<q W|j r|gS|SdS)Nrrrrrq) rrrzrurrrr"rrrV)rr-rrrtokZikeyZ dictvaluerwrwrxrs$   zDict.postParse)rrrrrrrrwrw)rHrxr s# c@s eZdZdZddZddZdS)r+aV Converter for ignoring the results of a parsed expression. Example:: source = "a, b, c,d" wd = Word(alphas) wd_list1 = wd + ZeroOrMore(',' + wd) print(wd_list1.parseString(source)) # often, delimiters that are useful during parsing are just in the # way afterward - use Suppress to keep them out of the parsed output wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) print(wd_list2.parseString(source)) prints:: ['a', ',', 'b', ',', 'c', ',', 'd'] ['a', 'b', 'c', 'd'] (See also L{delimitedList}.) cCsgS)Nrw)rr-rrrwrwrxrszSuppress.postParsecCs|S)Nrw)rrwrwrxrszSuppress.suppressN)rrrrrrrwrwrwrxr+sc@s(eZdZdZddZddZddZdS) rzI Wrapper for parse actions, to ensure they are only called once. cCst||_d|_dS)NF)rMcallablecalled)rZ methodCallrwrwrxrs zOnlyOnce.__init__cCs.|js|j|||}d|_|St||ddS)NTr)r[rZr)rrr5rvrrwrwrxrs zOnlyOnce.__call__cCs d|_dS)NF)r[)rrwrwrxreset szOnlyOnce.resetN)rrrrrrr\rwrwrwrxrsc s:tfdd}y j|_Wntk r4YnX|S)as Decorator for debugging parse actions. When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".} When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised. Example:: wd = Word(alphas) @traceParseAction def remove_duplicate_chars(tokens): return ''.join(sorted(set(''.join(tokens))) wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) print(wds.parseString("slkdjs sld sldd sdlf sdljf")) prints:: >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) <>entering %s(line: '%s', %d, %r) z<.z)rMrr)rr`rw)rrxrb s  ,FcCs`t|dt|dt|d}|rBt|t||j|S|tt||j|SdS)a Helper to define a delimited list of expressions - the delimiter defaults to ','. By default, the list elements and delimiters can have intervening whitespace, and comments, but this can be overridden by passing C{combine=True} in the constructor. If C{combine} is set to C{True}, the matching tokens are returned as a single token string, with the delimiters included; otherwise, the matching tokens are returned as a list of tokens, with the delimiters suppressed. Example:: delimitedList(Word(alphas)).parseString("aa,bb,cc") # -> ['aa', 'bb', 'cc'] delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] z [rz]...N)rr r2rir+)r.ZdelimcombineZdlNamerwrwrxr@9s $csjtfdd}|dkr0ttjdd}n|j}|jd|j|dd|jd td S) a: Helper to define a counted list of expressions. This helper defines a pattern of the form:: integer expr expr expr... where the leading integer tells how many expr expressions follow. The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed. If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value. Example:: countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] # in this parser, the leading integer value is given in binary, # '10' indicating that 2 values are in the array binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] cs.|d}|r ttg|p&tt>gS)Nr)rrrC)rr5rvr) arrayExprr.rwrxcountFieldParseAction_s"z+countedArray..countFieldParseActionNcSs t|dS)Nr)ru)rvrwrwrxrydszcountedArray..ZarrayLenT)rfz(len) z...)rr/rRrrrirxr)r.ZintExprrdrw)rcr.rxr<Ls cCs:g}x0|D](}t|tr(|jt|q |j|q W|S)N)rzrrrr)Lrrrwrwrxrks   rcs6tfdd}|j|ddjdt|S)a* Helper to define an expression that is indirectly defined from the tokens matched in a previous expression, that is, it looks for a 'repeat' of a previous expression. For example:: first = Word(nums) second = matchPreviousLiteral(first) matchExpr = first + ":" + second will match C{"1:1"}, but not C{"1:2"}. Because this matches a previous literal, will also match the leading C{"1:1"} in C{"1:10"}. If this is not desired, use C{matchPreviousExpr}. Do I{not} use with packrat parsing enabled. csP|rBt|dkr|d>qLt|j}tdd|D>n t>dS)Nrrrcss|]}t|VqdS)N)r)rttrwrwrxrszDmatchPreviousLiteral..copyTokenToRepeater..)rrrrr )rr5rvZtflat)reprwrxcopyTokenToRepeaters   z1matchPreviousLiteral..copyTokenToRepeaterT)rfz(prev) )rrxrir)r.rhrw)rgrxrOts  csFt|j}|Kfdd}|j|ddjdt|S)aS Helper to define an expression that is indirectly defined from the tokens matched in a previous expression, that is, it looks for a 'repeat' of a previous expression. For example:: first = Word(nums) second = matchPreviousExpr(first) matchExpr = first + ":" + second will match C{"1:1"}, but not C{"1:2"}. Because this matches by expressions, will I{not} match the leading C{"1:1"} in C{"1:10"}; the expressions are evaluated first, and then compared, so C{"1"} is compared with C{"10"}. Do I{not} use with packrat parsing enabled. cs*t|jfdd}j|dddS)Ncs$t|j}|kr tddddS)Nrr)rrr)rr5rvZ theseTokens) matchTokensrwrxmustMatchTheseTokenss zLmatchPreviousExpr..copyTokenToRepeater..mustMatchTheseTokensT)rf)rrr)rr5rvrj)rg)rirxrhs  z.matchPreviousExpr..copyTokenToRepeaterT)rfz(prev) )rrrxrir)r.Ze2rhrw)rgrxrNs cCs>xdD]}|j|t|}qW|jdd}|jdd}t|S)Nz\^-]rz\nr(z\t)r_bslashr)rrrwrwrxrs    rTc s|rdd}dd}tndd}dd}tg}t|trF|j}n&t|tjr\t|}ntj dt dd|svt Sd }x|t |d kr||}xnt ||d d D]N\}} || |r|||d =Pq||| r|||d =|j|| | }PqW|d 7}q|W| r|ryht |t d j|krZtd d jdd|Djdj|Stdjdd|Djdj|SWn&tk rtj dt ddYnXtfdd|Djdj|S)a Helper to quickly define a set of alternative Literals, and makes sure to do longest-first testing when there is a conflict, regardless of the input order, but returns a C{L{MatchFirst}} for best performance. Parameters: - strs - a string of space-delimited literals, or a collection of string literals - caseless - (default=C{False}) - treat all literals as caseless - useRegex - (default=C{True}) - as an optimization, will generate a Regex object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or if creating a C{Regex} raises an exception) Example:: comp_oper = oneOf("< = > <= >= !=") var = Word(alphas) number = Word(nums) term = var | number comparison_expr = term + comp_oper + term print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) prints:: [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] cSs|j|jkS)N)r)rbrwrwrxryszoneOf..cSs|jj|jS)N)rr)rrlrwrwrxryscSs||kS)Nrw)rrlrwrwrxryscSs |j|S)N)r)rrlrwrwrxrysz6Invalid argument to oneOf, expected string or iterablerq)rrrrNrz[%s]css|]}t|VqdS)N)r)rsymrwrwrxrszoneOf..z | |css|]}tj|VqdS)N)rdr )rrmrwrwrxrsz7Exception creating Regex for oneOf, building MatchFirstc3s|]}|VqdS)Nrw)rrm)parseElementClassrwrxrs)rrrzrrrr5rrrrrrrrrr'rirKr) ZstrsrZuseRegexZisequalZmasksZsymbolsrZcurrrrw)rorxrSsL         ((cCsttt||S)a Helper to easily and clearly define a dictionary by specifying the respective patterns for the key and value. Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens in the proper order. The key pattern can include delimiting markers or punctuation, as long as they are suppressed, thereby leaving the significant key text. The value pattern can include named results, so that the C{Dict} results can include named token fields. Example:: text = "shape: SQUARE posn: upper left color: light blue texture: burlap" attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) print(OneOrMore(attr_expr).parseString(text).dump()) attr_label = label attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) # similar to Dict, but simpler call format result = dictOf(attr_label, attr_value).parseString(text) print(result.dump()) print(result['shape']) print(result.shape) # object attribute access works too print(result.asDict()) prints:: [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - color: light blue - posn: upper left - shape: SQUARE - texture: burlap SQUARE SQUARE {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} )r r2r)rrrwrwrxrAs!cCs^tjdd}|j}d|_|d||d}|r@dd}ndd}|j||j|_|S) a Helper to return the original, untokenized text for a given expression. Useful to restore the parsed fields of an HTML start tag into the raw tag text itself, or to revert separate tokens with intervening whitespace back to the original matching input text. By default, returns astring containing the original parsed text. If the optional C{asString} argument is passed as C{False}, then the return value is a C{L{ParseResults}} containing any results names that were originally matched, and a single token containing the original matched text from the input string. So if the expression passed to C{L{originalTextFor}} contains expressions with defined results names, you must set C{asString} to C{False} if you want to preserve those results name values. Example:: src = "this is test bold text normal text " for tag in ("b","i"): opener,closer = makeHTMLTags(tag) patt = originalTextFor(opener + SkipTo(closer) + closer) print(patt.searchString(src)[0]) prints:: [' bold text '] ['text'] cSs|S)Nrw)rrrvrwrwrxry8sz!originalTextFor..F_original_start _original_endcSs||j|jS)N)rprq)rr5rvrwrwrxry=scSs&||jd|jdg|dd<dS)Nrprq)r)rr5rvrwrwrx extractText?sz$originalTextFor..extractText)r rrrer])r.ZasStringZ locMarkerZ endlocMarker matchExprrrrwrwrxrg s  cCst|jddS)zp Helper to undo pyparsing's default grouping of And expressions, even if all but one are non-empty. cSs|dS)Nrrw)rvrwrwrxryJszungroup..)r-r)r.rwrwrxrhEscCs4tjdd}t|d|d|jjdS)a Helper to decorate a returned token with its starting and ending locations in the input string. This helper adds the following results names: - locn_start = location where matched expression begins - locn_end = location where matched expression ends - value = the actual parsed results Be careful if the input text contains C{} characters, you may want to call C{L{ParserElement.parseWithTabs}} Example:: wd = Word(alphas) for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): print(match) prints:: [[0, 'ljsdf', 5]] [[8, 'lksdjjf', 15]] [[18, 'lkkjj', 23]] cSs|S)Nrw)rr5rvrwrwrxry`szlocatedExpr..Z locn_startrZlocn_end)r rrrr)r.ZlocatorrwrwrxrjLsz\[]-*.$+^?()~ )r cCs |ddS)Nrrrrw)rr5rvrwrwrxryksryz\\0?[xX][0-9a-fA-F]+cCstt|djddS)Nrz\0x)unichrrulstrip)rr5rvrwrwrxrylsz \\0[0-7]+cCstt|ddddS)Nrrr)ruru)rr5rvrwrwrxrymsz\])rr z\wr8rrZnegatebodyr c sBddy djfddtj|jDStk r<dSXdS)a Helper to easily define string ranges for use in Word construction. Borrows syntax from regexp '[]' string range definitions:: srange("[0-9]") -> "0123456789" srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" The input string must be enclosed in []'s, and the returned string is the expanded character set joined into a single string. The values enclosed in the []'s may be: - a single character - an escaped character with a leading backslash (such as C{\-} or C{\]}) - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) (C{\0x##} is also supported for backwards compatibility) - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character) - a range of any of the above, separated by a dash (C{'a-z'}, etc.) - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.) cSs<t|ts|Sdjddtt|dt|ddDS)Nrcss|]}t|VqdS)N)ru)rrrwrwrxrsz+srange....rrr)rzr"rrord)prwrwrxryszsrange..rc3s|]}|VqdS)Nrw)rpart) _expandedrwrxrszsrange..N)r_reBracketExprrrxrK)rrw)r|rxr_rs  csfdd}|S)zt Helper method for defining parse actions that require matching at a specific column in the input text. cs"t||krt||ddS)Nzmatched token not at column %d)r9r)r)Zlocnr1)rrwrx verifyColsz!matchOnlyAtCol..verifyColrw)rr~rw)rrxrMs cs fddS)a Helper method for common parse actions that simply return a literal value. Especially useful when used with C{L{transformString}()}. Example:: num = Word(nums).setParseAction(lambda toks: int(toks[0])) na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) term = na | num OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] csgS)Nrw)rr5rv)replStrrwrxryszreplaceWith..rw)rrw)rrxr\s cCs|dddS)a Helper parse action for removing quotation marks from parsed quoted strings. Example:: # by default, quotation marks are included in parsed results quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] # use removeQuotes to strip quotation marks from parsed results quotedString.setParseAction(removeQuotes) quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] rrrrsrw)rr5rvrwrwrxrZs c sNfdd}ytdtdj}Wntk rBt}YnX||_|S)aG Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional args are passed, they are forwarded to the given function as additional arguments after the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the parsed data to an integer using base 16. Example (compare the last to example in L{ParserElement.transformString}:: hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) hex_ints.runTests(''' 00 11 22 aa FF 0a 0d 1a ''') upperword = Word(alphas).setParseAction(tokenMap(str.upper)) OneOrMore(upperword).runTests(''' my kingdom for a horse ''') wd = Word(alphas).setParseAction(tokenMap(str.title)) OneOrMore(wd).setParseAction(' '.join).runTests(''' now is the winter of our discontent made glorious summer by this sun of york ''') prints:: 00 11 22 aa FF 0a 0d 1a [0, 17, 34, 170, 255, 10, 13, 26] my kingdom for a horse ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] now is the winter of our discontent made glorious summer by this sun of york ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] csfdd|DS)Ncsg|]}|fqSrwrw)rZtokn)rr6rwrxrsz(tokenMap..pa..rw)rr5rv)rr6rwrxr}sztokenMap..parrH)rJrrKr{)r6rr}rLrw)rr6rxrms cCs t|jS)N)rr)rvrwrwrxryscCs t|jS)N)rlower)rvrwrwrxryscCst|tr|}t|| d}n|j}tttd}|rtjj t }t d|dt t t|t d|tddgdjd j d d t d }nd jddtD}tjj t t|B}t d|dt t t|j ttt d|tddgdjd j dd t d }ttd|d }|jdd j|jddjjjd|}|jdd j|jddjjjd|}||_||_||fS)zRInternal helper to construct opening and closing tag expressions, given a tag name)rz_-:rtag=/F)rrCcSs |ddkS)Nrrrw)rr5rvrwrwrxrysz_makeTags..rrcss|]}|dkr|VqdS)rNrw)rrrwrwrxrsz_makeTags..cSs |ddkS)Nrrrw)rr5rvrwrwrxryszrz)rzrrrr/r4r3r>rrrZr+r r2rrrmrrVrYrBr _Lrtitlerrir)tagStrZxmlZresnameZ tagAttrNameZ tagAttrValueZopenTagZprintablesLessRAbrackZcloseTagrwrwrx _makeTagss" T\..rcCs t|dS)a  Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values. Example:: text = 'More info at the pyparsing wiki page' # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple a,a_end = makeHTMLTags("A") link_expr = a + SkipTo(a_end)("link_text") + a_end for link in link_expr.searchString(text): # attributes in the tag (like "href" shown here) are also accessible as named results print(link.link_text, '->', link.href) prints:: pyparsing -> http://pyparsing.wikispaces.com F)r)rrwrwrxrKscCs t|dS)z Helper to construct opening and closing tag expressions for XML, given a tag name. Matches tags only in the given upper/lower case. Example: similar to L{makeHTMLTags} T)r)rrwrwrxrLscs8|r|ddn|jddDfdd}|S)a< Helper to create a validating parse action to be used with start tags created with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag with a required attribute value, to avoid false matches on common tags such as C{} or C{
}. Call C{withAttribute} with a series of attribute names and values. Specify the list of filter attributes names and values as: - keyword arguments, as in C{(align="right")}, or - as an explicit dict with C{**} operator, when an attribute name is also a Python reserved word, as in C{**{"class":"Customer", "align":"right"}} - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) For attribute names with a namespace prefix, you must use the second form. Attribute names are matched insensitive to upper/lower case. If just testing for C{class} (with or without a namespace), use C{L{withClass}}. To verify that the attribute exists, but without specifying a value, pass C{withAttribute.ANY_VALUE} as the value. Example:: html = '''
Some text
1 4 0 1 0
1,3 2,3 1,1
this has no type
''' div,div_end = makeHTMLTags("div") # only match div tag having a type attribute with value "grid" div_grid = div().setParseAction(withAttribute(type="grid")) grid_expr = div_grid + SkipTo(div | div_end)("body") for grid_header in grid_expr.searchString(html): print(grid_header.body) # construct a match with any div tag having a type attribute, regardless of the value div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) div_expr = div_any_type + SkipTo(div | div_end)("body") for div_header in div_expr.searchString(html): print(div_header.body) prints:: 1 4 0 1 0 1 4 0 1 0 1,3 2,3 1,1 NcSsg|]\}}||fqSrwrw)rrrrwrwrxrQsz!withAttribute..cs^xXD]P\}}||kr&t||d||tjkr|||krt||d||||fqWdS)Nzno matching attribute z+attribute '%s' has value '%s', must be '%s')rre ANY_VALUE)rr5rZattrNameZ attrValue)attrsrwrxr}Rs zwithAttribute..pa)r)rZattrDictr}rw)rrxres 2 cCs|r d|nd}tf||iS)a Simplified version of C{L{withAttribute}} when matching on a div class - made difficult because C{class} is a reserved word in Python. Example:: html = '''
Some text
1 4 0 1 0
1,3 2,3 1,1
this <div> has no class
''' div,div_end = makeHTMLTags("div") div_grid = div().setParseAction(withClass("grid")) grid_expr = div_grid + SkipTo(div | div_end)("body") for grid_header in grid_expr.searchString(html): print(grid_header.body) div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) div_expr = div_any_type + SkipTo(div | div_end)("body") for div_header in div_expr.searchString(html): print(div_header.body) prints:: 1 4 0 1 0 1 4 0 1 0 1,3 2,3 1,1 z%s:classclass)re)Z classname namespaceZ classattrrwrwrxrk\s (rcCst}||||B}x`t|D]R\}}|d dd\}} } } | dkrTd|nd|} | dkr|dksxt|dkrtd|\} }tj| }| tjkrd| dkrt||t|t |}n| dkr|dk rt|||t|t ||}nt||t|t |}nD| dkrZt|| |||t|| |||}ntd n| tj krH| dkrt |t st |}t|j |t||}n| dkr|dk rt|||t|t ||}nt||t|t |}nD| dkr>t|| |||t|| |||}ntd ntd | r`|j| ||j| |BK}|}q"W||K}|S) a Helper method for constructing grammars of expressions made up of operators working in a precedence hierarchy. Operators may be unary or binary, left- or right-associative. Parse actions can also be attached to operator expressions. The generated parser will also recognize the use of parentheses to override operator precedences (see example below). Note: if you define a deep operator list, you may see performance issues when using infixNotation. See L{ParserElement.enablePackrat} for a mechanism to potentially improve your parser performance. Parameters: - baseExpr - expression representing the most basic element for the nested - opList - list of tuples, one for each operator precedence level in the expression grammar; each tuple is of the form (opExpr, numTerms, rightLeftAssoc, parseAction), where: - opExpr is the pyparsing expression for the operator; may also be a string, which will be converted to a Literal; if numTerms is 3, opExpr is a tuple of two expressions, for the two operators separating the 3 terms - numTerms is the number of terms for this operator (must be 1, 2, or 3) - rightLeftAssoc is the indicator whether the operator is right or left associative, using the pyparsing-defined constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. - parseAction is the parse action to be associated with expressions matching this operator expression (the parse action tuple member may be omitted) - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) Example:: # simple example of four-function arithmetic with ints and variable names integer = pyparsing_common.signed_integer varname = pyparsing_common.identifier arith_expr = infixNotation(integer | varname, [ ('-', 1, opAssoc.RIGHT), (oneOf('* /'), 2, opAssoc.LEFT), (oneOf('+ -'), 2, opAssoc.LEFT), ]) arith_expr.runTests(''' 5+3*6 (5+3)*6 -2--11 ''', fullDump=False) prints:: 5+3*6 [[5, '+', [3, '*', 6]]] (5+3)*6 [[[5, '+', 3], '*', 6]] -2--11 [[['-', 2], '-', ['-', 11]]] Nrroz%s termz %s%s termrqz@if numterms=3, opExpr must be a tuple or list of two expressionsrrz6operator must be unary (1), binary (2), or ternary (3)z2operator must indicate right or left associativity)N)rrrrrirTLEFTrrrRIGHTrzrr.r)ZbaseExprZopListZlparZrparrZlastExprrZoperDefZopExprZarityZrightLeftAssocr}ZtermNameZopExpr1ZopExpr2ZthisExprrsrwrwrxrisR;    &       &   z4"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*"z string enclosed in double quotesz4'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*'z string enclosed in single quotesz*quotedString using single or double quotesuzunicode string literalcCs||krtd|dkr(t|to,t|tr t|dkrt|dkr|dk rtt|t||tjddj dd}n$t j t||tjj dd}nx|dk rtt|t |t |ttjddj dd}n4ttt |t |ttjddj d d}ntd t }|dk rb|tt|t||B|Bt|K}n$|tt|t||Bt|K}|jd ||f|S) a~ Helper method for defining nested lists enclosed in opening and closing delimiters ("(" and ")" are the default). Parameters: - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression - content - expression for items within the nested lists (default=C{None}) - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) If an expression is not provided for the content argument, the nested expression will capture all whitespace-delimited content between delimiters as a list of separate values. Use the C{ignoreExpr} argument to define expressions that may contain opening or closing characters that should not be treated as opening or closing characters for nesting, such as quotedString or a comment expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. The default is L{quotedString}, but if no expressions are to be ignored, then pass C{None} for this argument. Example:: data_type = oneOf("void int short long char float double") decl_data_type = Combine(data_type + Optional(Word('*'))) ident = Word(alphas+'_', alphanums+'_') number = pyparsing_common.number arg = Group(decl_data_type + ident) LPAR,RPAR = map(Suppress, "()") code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) c_function = (decl_data_type("type") + ident("name") + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + code_body("body")) c_function.ignore(cStyleComment) source_code = ''' int is_odd(int x) { return (x%2); } int dec_to_hex(char hchar) { if (hchar >= '0' && hchar <= '9') { return (ord(hchar)-ord('0')); } else { return (10+ord(hchar)-ord('A')); } } ''' for func in c_function.searchString(source_code): print("%(name)s (%(type)s) args: %(args)s" % func) prints:: is_odd (int) args: [['int', 'x']] dec_to_hex (int) args: [['char', 'hchar']] z.opening and closing strings cannot be the sameNrr)r cSs |djS)Nr)r)rvrwrwrxry9sznestedExpr..cSs |djS)Nr)r)rvrwrwrxry<scSs |djS)Nr)r)rvrwrwrxryBscSs |djS)Nr)r)rvrwrwrxryFszOopening and closing arguments must be strings if no content expression is givenznested %s%s expression)rrzrrr rr r$rNrrCrrrrr+r2ri)openerZcloserZcontentrOrrwrwrxrPs4:     *$c sfdd}fdd}fdd}ttjdj}ttj|jd}tj|jd }tj|jd } |rtt||t|t|t|| } n$tt|t|t|t|} |j t t| jd S) a Helper method for defining space-delimited indentation blocks, such as those used to define block statements in Python source code. Parameters: - blockStatementExpr - expression defining syntax of statement that is repeated within the indented block - indentStack - list created by caller to manage indentation stack (multiple statementWithIndentedBlock expressions within a single grammar should share a common indentStack) - indent - boolean indicating whether block must be indented beyond the the current level; set to False for block of left-most statements (default=C{True}) A valid block must contain at least one C{blockStatement}. Example:: data = ''' def A(z): A1 B = 100 G = A2 A2 A3 B def BB(a,b,c): BB1 def BBA(): bba1 bba2 bba3 C D def spam(x,y): def eggs(z): pass ''' indentStack = [1] stmt = Forward() identifier = Word(alphas, alphanums) funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") func_body = indentedBlock(stmt, indentStack) funcDef = Group( funcDecl + func_body ) rvalue = Forward() funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") rvalue << (funcCall | identifier | Word(nums)) assignment = Group(identifier + "=" + rvalue) stmt << ( funcDef | assignment | identifier ) module_body = OneOrMore(stmt) parseTree = module_body.parseString(data) parseTree.pprint() prints:: [['def', 'A', ['(', 'z', ')'], ':', [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], 'B', ['def', 'BB', ['(', 'a', 'b', 'c', ')'], ':', [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], 'C', 'D', ['def', 'spam', ['(', 'x', 'y', ')'], ':', [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] csN|t|krdSt||}|dkrJ|dkr>t||dt||ddS)Nrrzillegal nestingznot a peer entryrsrs)rr9r!r)rr5rvcurCol) indentStackrwrxcheckPeerIndents     z&indentedBlock..checkPeerIndentcs2t||}|dkr"j|n t||ddS)Nrrznot a subentryrs)r9rr)rr5rvr)rrwrxcheckSubIndents   z%indentedBlock..checkSubIndentcsN|t|krdSt||}o4|dko4|dksBt||djdS)Nrrrqznot an unindentrsr:)rr9rr)rr5rvr)rrwrx checkUnindents    z$indentedBlock..checkUnindentz INDENTrZUNINDENTzindented block) rrrrr rrirrrrk) ZblockStatementExprrrrrrr!rZPEERZUNDENTZsmExprrw)rrxrfQsN   ,z#[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]z[\0xa1-\0xbf\0xd7\0xf7]z_:zany tagzgt lt amp nbsp quot aposz><& "'z &(?Prnz);zcommon HTML entitycCs tj|jS)zRHelper parser action to replace common HTML entities with their special characters)_htmlEntityMaprZentity)rvrwrwrxr[sz/\*(?:[^*]|\*(?!/))*z*/zC style commentzz HTML commentz.*z rest of linez//(?:\\\n|[^\n])*z // commentzC++ style commentz#.*zPython style comment)rz commaItem)rc@seZdZdZeeZeeZe e j dj eZ e ej dj eedZedj dj eZej edej ej dZejd d eeeed jeBj d Zejeed j dj eZedj dj eZeeBeBjZedj dj eZe ededj dZedj dZ edj dZ!e!de!dj dZ"ee!de!d>dee!de!d?j dZ#e#j$d d d!e j d"Z%e&e"e%Be#Bj d#j d#Z'ed$j d%Z(e)d@d'd(Z*e)dAd*d+Z+ed,j d-Z,ed.j d/Z-ed0j d1Z.e/je0jBZ1e)d2d3Z2e&e3e4d4e5e e6d4d5ee7d6jj d7Z8e9ee:j;e8Bd8d9j d:Zd=S)Brna Here are some common low-level expressions that may be useful in jump-starting parser development: - numeric forms (L{integers}, L{reals}, L{scientific notation}) - common L{programming identifiers} - network addresses (L{MAC}, L{IPv4}, L{IPv6}) - ISO8601 L{dates} and L{datetime} - L{UUID} - L{comma-separated list} Parse actions: - C{L{convertToInteger}} - C{L{convertToFloat}} - C{L{convertToDate}} - C{L{convertToDatetime}} - C{L{stripHTMLTags}} - C{L{upcaseTokens}} - C{L{downcaseTokens}} Example:: pyparsing_common.number.runTests(''' # any int or real number, returned as the appropriate type 100 -100 +100 3.14159 6.02e23 1e-12 ''') pyparsing_common.fnumber.runTests(''' # any int or real number, returned as float 100 -100 +100 3.14159 6.02e23 1e-12 ''') pyparsing_common.hex_integer.runTests(''' # hex numbers 100 FF ''') pyparsing_common.fraction.runTests(''' # fractions 1/2 -3/4 ''') pyparsing_common.mixed_integer.runTests(''' # mixed fractions 1 1/2 -3/4 1-3/4 ''') import uuid pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) pyparsing_common.uuid.runTests(''' # uuid 12345678-1234-5678-1234-567812345678 ''') prints:: # any int or real number, returned as the appropriate type 100 [100] -100 [-100] +100 [100] 3.14159 [3.14159] 6.02e23 [6.02e+23] 1e-12 [1e-12] # any int or real number, returned as float 100 [100.0] -100 [-100.0] +100 [100.0] 3.14159 [3.14159] 6.02e23 [6.02e+23] 1e-12 [1e-12] # hex numbers 100 [256] FF [255] # fractions 1/2 [0.5] -3/4 [-0.75] # mixed fractions 1 [1] 1/2 [0.5] -3/4 [-0.75] 1-3/4 [1.75] # uuid 12345678-1234-5678-1234-567812345678 [UUID('12345678-1234-5678-1234-567812345678')] integerz hex integerrtz[+-]?\d+zsigned integerrfractioncCs|d|dS)Nrrrrsrw)rvrwrwrxryszpyparsing_common.r8z"fraction or mixed integer-fractionz [+-]?\d+\.\d*z real numberz+[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)z$real number with scientific notationz[+-]?\d+\.?\d*([eE][+-]?\d+)?fnumberrB identifierzK(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}z IPv4 addressz[0-9a-fA-F]{1,4} hex_integerrzfull IPv6 addressrrBz::zshort IPv6 addresscCstdd|DdkS)Ncss|]}tjj|rdVqdS)rrN)rn _ipv6_partr)rrfrwrwrxrsz,pyparsing_common...rw)rH)rvrwrwrxrysz::ffff:zmixed IPv6 addressz IPv6 addressz:[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}z MAC address%Y-%m-%dcsfdd}|S)a Helper to create a parse action for converting parsed date string to Python datetime.date Params - - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) Example:: date_expr = pyparsing_common.iso8601_date.copy() date_expr.setParseAction(pyparsing_common.convertToDate()) print(date_expr.parseString("1999-12-31")) prints:: [datetime.date(1999, 12, 31)] csLytj|djStk rF}zt||t|WYdd}~XnXdS)Nr)rstrptimeZdaterrr{)rr5rvve)fmtrwrxcvt_fnsz.pyparsing_common.convertToDate..cvt_fnrw)rrrw)rrx convertToDates zpyparsing_common.convertToDate%Y-%m-%dT%H:%M:%S.%fcsfdd}|S)a Helper to create a parse action for converting parsed datetime string to Python datetime.datetime Params - - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) Example:: dt_expr = pyparsing_common.iso8601_datetime.copy() dt_expr.setParseAction(pyparsing_common.convertToDatetime()) print(dt_expr.parseString("1999-12-31T23:59:59.999")) prints:: [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] csHytj|dStk rB}zt||t|WYdd}~XnXdS)Nr)rrrrr{)rr5rvr)rrwrxrsz2pyparsing_common.convertToDatetime..cvt_fnrw)rrrw)rrxconvertToDatetimes z"pyparsing_common.convertToDatetimez7(?P\d{4})(?:-(?P\d\d)(?:-(?P\d\d))?)?z ISO8601 datez(?P\d{4})-(?P\d\d)-(?P\d\d)[T ](?P\d\d):(?P\d\d)(:(?P\d\d(\.\d*)?)?)?(?PZ|[+-]\d\d:?\d\d)?zISO8601 datetimez2[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}UUIDcCstjj|dS)a Parse action to remove HTML tags from web page HTML source Example:: # strip HTML links from normal text text = 'More info at the
pyparsing wiki page' td,td_end = makeHTMLTags("TD") table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' r)rn_html_stripperr)rr5rrwrwrx stripHTMLTagss zpyparsing_common.stripHTMLTagsra)rz rr)rzcomma separated listcCs t|jS)N)rr)rvrwrwrxryscCs t|jS)N)rr)rvrwrwrxrysN)rrB)rrB)r)r)?rrrrrmruZconvertToIntegerfloatZconvertToFloatr/rRrirrrDrr'Zsigned_integerrrxrrZ mixed_integerrHrealZsci_realrnumberrr4r3rZ ipv4_addressrZ_full_ipv6_addressZ_short_ipv6_addressr~Z_mixed_ipv6_addressr Z ipv6_addressZ mac_addressrrrZ iso8601_dateZiso8601_datetimeuuidr7r6rrrrrrVr. _commasepitemr@rYrZcomma_separated_listrdrBrwrwrwrxrnsN"" 2   8__main__Zselectfromz_$r])rbcolumnsrjZtablesZcommandaK # '*' as column list and dotted table name select * from SYS.XYZZY # caseless match on "SELECT", and casts back to "select" SELECT * from XYZZY, ABC # list of column names, and mixed case SELECT keyword Select AA,BB,CC from Sys.dual # multiple tables Select A, B, C from Sys.dual, Table2 # invalid SELECT keyword - should fail Xelect A, B, C from Sys.dual # incomplete command - should fail Select # invalid column name - should fail Select ^^^ frox Sys.dual z] 100 -100 +100 3.14159 6.02e23 1e-12 z 100 FF z6 12345678-1234-5678-1234-567812345678 )rq)raF)N)FT)T)r)T)r __version__Z__versionTime__ __author__rweakrefrrrr~rrdrrr"r<rr_threadr ImportErrorZ threadingrrZ ordereddict__all__r version_infor;rmaxsizerr{rchrrurrHrrreversedrrrr6r r rIZmaxintZxrangerZ __builtin__rZfnamerrJrrrrrrZascii_uppercaseZascii_lowercaser4rRrDr3rkrZ printablerVrKrrr!r#r&rr"MutableMappingregisterr9rJrGr/r2r4rQrMr$r,r rrrrQrrrrlr/r'r%r r.r0rrrr*r)r1r0r rrrr rrrrJrr2rMrNrr(rrVr-r rr r+rrbr@r<rrOrNrrSrArgrhrjrirCrIrHrar`rZ _escapedPuncZ_escapedHexCharZ_escapedOctCharUNICODEZ _singleCharZ _charRangermr}r_rMr\rZrmrdrBrrKrLrerrkrTrrrirUr>r^rYrcrPrfr5rWr7r6rrrrr;r[r8rErr]r?r=rFrXrrr:rnrZ selectTokenZ fromTokenZidentZ columnNameZcolumnNameListZ columnSpecZ tableNameZ tableNameListZ simpleSQLrrrrrrrwrwrwrx=s                 8      @d &A= I G3pLOD|M &#@sQ,A,    I# %     &0 ,   ? #k Zr   (  0     "__pycache__/pyparsing.cpython-36.pyc000064400000610513147205126200013423 0ustar003 9f@s dZdZdZdZddlZddlmZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlmZyddlmZWn ek rddlmZYnXydd l mZWn>ek rydd lmZWnek rdZYnXYnXd d d d ddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;dd?d@dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdgdhdidjdkdldmdndodpdqdrgiZee jddsZeddskZer"e jZe Z!e"Z#e Z$e%e&e'e(e)ee*e+e,e-e.g Z/nbe j0Ze1Z2dtduZ$gZ/ddl3Z3xBdvj4D]6Z5ye/j6e7e3e5Wne8k r|wJYnXqJWe9dwdxe2dyDZ:dzd{Z;Gd|d}d}e<Z=ej>ej?Z@d~ZAeAdZBe@eAZCe"dZDdjEddxejFDZGGdd!d!eHZIGdd#d#eIZJGdd%d%eIZKGdd'd'eKZLGdd*d*eHZMGddde<ZNGdd&d&e<ZOe jPjQeOdd=ZRddNZSddKZTddZUddZVddZWddUZXd/ddZYGdd(d(e<ZZGdd0d0eZZ[Gddde[Z\Gddde[Z]Gddde[Z^e^Z_e^eZ_`Gddde[ZaGdd d e^ZbGdd d eaZcGddpdpe[ZdGdd3d3e[ZeGdd+d+e[ZfGdd)d)e[ZgGdd d e[ZhGdd2d2e[ZiGddde[ZjGdddejZkGdddejZlGdddejZmGdd.d.ejZnGdd-d-ejZoGdd5d5ejZpGdd4d4ejZqGdd$d$eZZrGdd d erZsGdd d erZtGddderZuGddderZvGdd"d"eZZwGdddewZxGdddewZyGdddewZzGdddezZ{Gdd6d6ezZ|Gddde<Z}e}Z~GdddewZGdd,d,ewZGdddewZGdddeZGdd1d1ewZGdddeZGdddeZGdddeZGdd/d/eZGddde<ZddfZd0ddDZd1dd@Zdd΄ZddSZddRZdd҄Zd2ddWZddEZd3ddkZddlZddnZe\jdGZeljdMZemjdLZenjdeZeojddZeeeDdddڍjdd܄Zefd݃jdd܄Zefd߃jdd܄ZeeBeBeeeGddydBefde jBZeeedeZe^dedjdee{eeBjddZddcZddQZdd`Zdd^ZddqZedd܄Zedd܄ZddZddOZddPZddiZe<e_d4ddoZe=Ze<e_e<e_ededfddmZeZeefddjdZeefddjdZeefddefddBjdZee_dejjdZdddejfddTZd5ddjZedZedZeeee@eCdjd\ZZeed j4d Zefd d jEejÃd jdZĐdd_ZeefddjdZefdjdZefdjȃjdZefdjdZeefddeBjdZeZefdjdZee{eeeGdɐdeeede^dɃemj΃jdZeeejeBddjd>ZGd drdrZeҐd!k rebd"Zebd#Zeee@eCd$ZeeՐd%dӐd&jeZeeeփjd'Zאd(eBZeeՐd%dӐd&jeZeeeكjd)ZeӐd*eؐd'eeڐd)Zejܐd+ejjܐd,ejjܐd,ejjܐd-ddlZejjeejejjܐd.dS(6aS pyparsing module - Classes and methods to define and execute parsing grammars The pyparsing module is an alternative approach to creating and executing simple grammars, vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you don't need to learn a new syntax for defining grammars or matching expressions - the parsing module provides a library of classes that you use to construct the grammar directly in Python. Here is a program to parse "Hello, World!" (or any greeting of the form C{", !"}), built up using L{Word}, L{Literal}, and L{And} elements (L{'+'} operator gives L{And} expressions, strings are auto-converted to L{Literal} expressions):: from pyparsing import Word, alphas # define grammar of a greeting greet = Word(alphas) + "," + Word(alphas) + "!" hello = "Hello, World!" print (hello, "->", greet.parseString(hello)) The program outputs the following:: Hello, World! -> ['Hello', ',', 'World', '!'] The Python representation of the grammar is quite readable, owing to the self-explanatory class names, and the use of '+', '|' and '^' operators. The L{ParseResults} object returned from L{ParserElement.parseString} can be accessed as a nested list, a dictionary, or an object with named attributes. The pyparsing module handles some of the problems that are typically vexing when writing text parsers: - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) - quoted strings - embedded comments z2.1.10z07 Oct 2016 01:31 UTCz*Paul McGuire N)ref)datetime)RLock) OrderedDictAndCaselessKeywordCaselessLiteral CharsNotInCombineDictEachEmpty FollowedByForward GoToColumnGroupKeywordLineEnd LineStartLiteral MatchFirstNoMatchNotAny OneOrMoreOnlyOnceOptionalOrParseBaseExceptionParseElementEnhanceParseExceptionParseExpressionParseFatalException ParseResultsParseSyntaxException ParserElement QuotedStringRecursiveGrammarExceptionRegexSkipTo StringEnd StringStartSuppressTokenTokenConverterWhiteWordWordEnd WordStart ZeroOrMore alphanumsalphas alphas8bit anyCloseTag anyOpenTag cStyleCommentcolcommaSeparatedListcommonHTMLEntity countedArraycppStyleCommentdblQuotedStringdblSlashComment delimitedListdictOfdowncaseTokensemptyhexnums htmlCommentjavaStyleCommentlinelineEnd lineStartlineno makeHTMLTags makeXMLTagsmatchOnlyAtColmatchPreviousExprmatchPreviousLiteral nestedExprnullDebugActionnumsoneOfopAssocoperatorPrecedence printablespunc8bitpythonStyleComment quotedString removeQuotesreplaceHTMLEntity replaceWith restOfLinesglQuotedStringsrange stringEnd stringStarttraceParseAction unicodeString upcaseTokens withAttribute indentedBlockoriginalTextForungroup infixNotation locatedExpr withClass CloseMatchtokenMappyparsing_commonc Cs`t|tr|Syt|Stk rZt|jtjd}td}|jdd|j |SXdS)aDrop-in replacement for str(obj) that tries to be Unicode friendly. It first tries str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It then < returns the unicode object | encodes it with the default encoding | ... >. xmlcharrefreplacez&#\d+;cSs$dtt|dddddS)Nz\ur)hexint)trw/usr/lib/python3.6/pyparsing.pysz_ustr..N) isinstanceZunicodestrUnicodeEncodeErrorencodesysgetdefaultencodingr'setParseActiontransformString)objretZ xmlcharrefrwrwrx_ustrs rz6sum len sorted reversed list tuple set any all min maxccs|] }|VqdS)Nrw).0yrwrwrx srrrcCs>d}dddjD}x"t||D]\}}|j||}q"W|S)z/Escape &, <, >, ", ', etc. in a string of data.z&><"'css|]}d|dVqdS)&;Nrw)rsrwrwrxrsz_xml_escape..zamp gt lt quot apos)splitzipreplace)dataZ from_symbolsZ to_symbolsZfrom_Zto_rwrwrx _xml_escapes rc@s eZdZdS) _ConstantsN)__name__ __module__ __qualname__rwrwrwrxrsr 0123456789Z ABCDEFabcdef\ccs|]}|tjkr|VqdS)N)stringZ whitespace)rcrwrwrxrsc@sPeZdZdZdddZeddZdd Zd d Zd d Z dddZ ddZ dS)rz7base exception class for all parsing runtime exceptionsrNcCs>||_|dkr||_d|_n ||_||_||_|||f|_dS)Nr)locmsgpstr parserElementargs)selfrrrelemrwrwrx__init__szParseBaseException.__init__cCs||j|j|j|jS)z internal factory method to simplify creating one type of ParseException from another - avoids having __init__ signature conflicts among subclasses )rrrr)clsperwrwrx_from_exceptionsz"ParseBaseException._from_exceptioncCsN|dkrt|j|jS|dkr,t|j|jS|dkrBt|j|jSt|dS)zsupported attributes by name are: - lineno - returns the line number of the exception text - col - returns the column number of the exception text - line - returns the line containing the exception text rJr9columnrGN)r9r)rJrrr9rGAttributeError)rZanamerwrwrx __getattr__szParseBaseException.__getattr__cCsd|j|j|j|jfS)Nz"%s (at char %d), (line:%d, col:%d))rrrJr)rrwrwrx__str__szParseBaseException.__str__cCst|S)N)r)rrwrwrx__repr__szParseBaseException.__repr__>!} ('-' operator) indicates that parsing is to stop immediately because an unbacktrackable syntax error has been foundN)rrrrrwrwrwrxr#sc@s eZdZdZddZddZdS)r&zZexception thrown by L{ParserElement.validate} if the grammar could be improperly recursivecCs ||_dS)N)parseElementTrace)rparseElementListrwrwrxrsz"RecursiveGrammarException.__init__cCs d|jS)NzRecursiveGrammarException: %s)r)rrwrwrxr sz!RecursiveGrammarException.__str__N)rrrrrrrwrwrwrxr&sc@s,eZdZddZddZddZddZd S) _ParseResultsWithOffsetcCs||f|_dS)N)tup)rZp1Zp2rwrwrxr$sz _ParseResultsWithOffset.__init__cCs |j|S)N)r)rirwrwrx __getitem__&sz#_ParseResultsWithOffset.__getitem__cCst|jdS)Nr)reprr)rrwrwrxr(sz _ParseResultsWithOffset.__repr__cCs|jd|f|_dS)Nr)r)rrrwrwrx setOffset*sz!_ParseResultsWithOffset.setOffsetN)rrrrrrrrwrwrwrxr#src@seZdZdZd[ddZddddefddZdd Zefd d Zd d Z ddZ ddZ ddZ e Z ddZddZddZddZddZereZeZeZn$eZeZeZddZd d!Zd"d#Zd$d%Zd&d'Zd\d(d)Zd*d+Zd,d-Zd.d/Zd0d1Z d2d3Z!d4d5Z"d6d7Z#d8d9Z$d:d;Z%d} - see L{ParserElement.setResultsName}) Example:: integer = Word(nums) date_str = (integer.setResultsName("year") + '/' + integer.setResultsName("month") + '/' + integer.setResultsName("day")) # equivalent form: # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") # parseString returns a ParseResults object result = date_str.parseString("1999/12/31") def test(s, fn=repr): print("%s -> %s" % (s, fn(eval(s)))) test("list(result)") test("result[0]") test("result['month']") test("result.day") test("'month' in result") test("'minutes' in result") test("result.dump()", str) prints:: list(result) -> ['1999', '/', '12', '/', '31'] result[0] -> '1999' result['month'] -> '12' result.day -> '31' 'month' in result -> True 'minutes' in result -> False result.dump() -> ['1999', '/', '12', '/', '31'] - day: 31 - month: 12 - year: 1999 NTcCs"t||r|Stj|}d|_|S)NT)rzobject__new___ParseResults__doinit)rtoklistnameasListmodalZretobjrwrwrxrTs   zParseResults.__new__c Cs`|jrvd|_d|_d|_i|_||_||_|dkr6g}||trP|dd|_n||trft||_n|g|_t |_ |dk o|r\|sd|j|<||t rt |}||_||t dttfo|ddgfks\||tr|g}|r&||trt|jd||<ntt|dd||<|||_n6y|d||<Wn$tttfk rZ|||<YnXdS)NFrr)r_ParseResults__name_ParseResults__parent_ParseResults__accumNames_ParseResults__asList_ParseResults__modallist_ParseResults__toklist_generatorTypedict_ParseResults__tokdictrurr basestringr"rcopyKeyError TypeError IndexError)rrrrrrzrwrwrxr]sB     $   zParseResults.__init__cCsPt|ttfr|j|S||jkr4|j|ddStdd|j|DSdS)NrrrcSsg|] }|dqS)rrw)rvrwrwrx sz,ParseResults.__getitem__..rs)rzruslicerrrr")rrrwrwrxrs   zParseResults.__getitem__cCs||tr0|jj|t|g|j|<|d}nD||ttfrN||j|<|}n&|jj|tt|dg|j|<|}||trt||_ dS)Nr) rrgetrrurrr"wkrefr)rkrrzsubrwrwrx __setitem__s   " zParseResults.__setitem__c Cst|ttfrt|j}|j|=t|trH|dkr:||7}t||d}tt|j|}|jx^|j j D]F\}}x<|D]4}x.t |D]"\}\}} t || | |k||<qWq|WqnWn|j |=dS)Nrrr) rzrurlenrrrangeindicesreverseritems enumerater) rrZmylenZremovedr occurrencesjrvaluepositionrwrwrx __delitem__s   $zParseResults.__delitem__cCs ||jkS)N)r)rrrwrwrx __contains__szParseResults.__contains__cCs t|jS)N)rr)rrwrwrx__len__szParseResults.__len__cCs |j S)N)r)rrwrwrx__bool__szParseResults.__bool__cCs t|jS)N)iterr)rrwrwrx__iter__szParseResults.__iter__cCst|jdddS)Nrrrs)rr)rrwrwrx __reversed__szParseResults.__reversed__cCs$t|jdr|jjSt|jSdS)Niterkeys)hasattrrrr)rrwrwrx _iterkeyss  zParseResults._iterkeyscsfddjDS)Nc3s|]}|VqdS)Nrw)rr)rrwrxrsz+ParseResults._itervalues..)r)rrw)rrx _itervaluesszParseResults._itervaluescsfddjDS)Nc3s|]}||fVqdS)Nrw)rr)rrwrxrsz*ParseResults._iteritems..)r)rrw)rrx _iteritemsszParseResults._iteritemscCs t|jS)zVReturns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).)rr)rrwrwrxkeysszParseResults.keyscCs t|jS)zXReturns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).)r itervalues)rrwrwrxvaluesszParseResults.valuescCs t|jS)zfReturns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).)r iteritems)rrwrwrxrszParseResults.itemscCs t|jS)zSince keys() returns an iterator, this method is helpful in bypassing code that looks for the existence of any defined results names.)boolr)rrwrwrxhaskeysszParseResults.haskeyscOs|s dg}x6|jD]*\}}|dkr2|d|f}qtd|qWt|dtsht|dksh|d|kr|d}||}||=|S|d}|SdS)a Removes and returns item at specified index (default=C{last}). Supports both C{list} and C{dict} semantics for C{pop()}. If passed no argument or an integer argument, it will use C{list} semantics and pop tokens from the list of parsed tokens. If passed a non-integer argument (most likely a string), it will use C{dict} semantics and pop the corresponding value from any defined results names. A second default return value argument is supported, just as in C{dict.pop()}. Example:: def remove_first(tokens): tokens.pop(0) print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] label = Word(alphas) patt = label("LABEL") + OneOrMore(Word(nums)) print(patt.parseString("AAB 123 321").dump()) # Use pop() in a parse action to remove named result (note that corresponding value is not # removed from list form of results) def remove_LABEL(tokens): tokens.pop("LABEL") return tokens patt.addParseAction(remove_LABEL) print(patt.parseString("AAB 123 321").dump()) prints:: ['AAB', '123', '321'] - LABEL: AAB ['AAB', '123', '321'] rrdefaultrz-pop() got an unexpected keyword argument '%s'Nrs)rrrzrur)rrkwargsrrindexrZ defaultvaluerwrwrxpops"  zParseResults.popcCs||kr||S|SdS)ai Returns named result matching the given key, or if there is no such name, then returns the given C{defaultValue} or C{None} if no C{defaultValue} is specified. Similar to C{dict.get()}. Example:: integer = Word(nums) date_str = integer("year") + '/' + integer("month") + '/' + integer("day") result = date_str.parseString("1999/12/31") print(result.get("year")) # -> '1999' print(result.get("hour", "not specified")) # -> 'not specified' print(result.get("hour")) # -> None Nrw)rkey defaultValuerwrwrxrszParseResults.getcCsZ|jj||xF|jjD]8\}}x.t|D]"\}\}}t||||k||<q,WqWdS)a Inserts new element at location index in the list of parsed tokens. Similar to C{list.insert()}. Example:: print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] # use a parse action to insert the parse location in the front of the parsed results def insert_locn(locn, tokens): tokens.insert(0, locn) print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] N)rinsertrrrr)rrZinsStrrrrrrrwrwrxr2szParseResults.insertcCs|jj|dS)a Add single element to end of ParseResults list of elements. Example:: print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] # use a parse action to compute the sum of the parsed integers, and add it to the end def append_sum(tokens): tokens.append(sum(map(int, tokens))) print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] N)rappend)ritemrwrwrxrFs zParseResults.appendcCs$t|tr||7}n |jj|dS)a Add sequence of elements to end of ParseResults list of elements. Example:: patt = OneOrMore(Word(alphas)) # use a parse action to append the reverse of the matched strings, to make a palindrome def make_palindrome(tokens): tokens.extend(reversed([t[::-1] for t in tokens])) return ''.join(tokens) print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' N)rzr"rextend)rZitemseqrwrwrxrTs  zParseResults.extendcCs|jdd=|jjdS)z7 Clear all elements and results names. N)rrclear)rrwrwrxrfs zParseResults.clearc Csfy||Stk rdSX||jkr^||jkrD|j|ddStdd|j|DSndSdS)NrrrrcSsg|] }|dqS)rrw)rrrwrwrxrwsz,ParseResults.__getattr__..rs)rrrr")rrrwrwrxrms  zParseResults.__getattr__cCs|j}||7}|S)N)r)rotherrrwrwrx__add__{szParseResults.__add__cs|jrnt|jfdd|jj}fdd|D}x4|D],\}}|||<t|dtr>t||d_q>W|j|j7_|jj |j|S)Ncs|dkr S|S)Nrrw)a)offsetrwrxrysz'ParseResults.__iadd__..c s4g|],\}}|D]}|t|d|dfqqS)rrr)r)rrvlistr) addoffsetrwrxrsz)ParseResults.__iadd__..r) rrrrrzr"rrrupdate)rrZ otheritemsZotherdictitemsrrrw)rrrx__iadd__s    zParseResults.__iadd__cCs&t|tr|dkr|jS||SdS)Nr)rzrur)rrrwrwrx__radd__szParseResults.__radd__cCsdt|jt|jfS)Nz(%s, %s))rrr)rrwrwrxrszParseResults.__repr__cCsddjdd|jDdS)N[z, css(|] }t|trt|nt|VqdS)N)rzr"rr)rrrwrwrxrsz'ParseResults.__str__..])rr)rrwrwrxrszParseResults.__str__rcCsPg}xF|jD]<}|r"|r"|j|t|tr:||j7}q |jt|q W|S)N)rrrzr" _asStringListr)rsepoutrrwrwrxr s   zParseResults._asStringListcCsdd|jDS)a Returns the parse results as a nested list of matching tokens, all converted to strings. Example:: patt = OneOrMore(Word(alphas)) result = patt.parseString("sldkj lsdkj sldkj") # even though the result prints in string-like form, it is actually a pyparsing ParseResults print(type(result), result) # -> ['sldkj', 'lsdkj', 'sldkj'] # Use asList() to create an actual list result_list = result.asList() print(type(result_list), result_list) # -> ['sldkj', 'lsdkj', 'sldkj'] cSs"g|]}t|tr|jn|qSrw)rzr"r)rresrwrwrxrsz'ParseResults.asList..)r)rrwrwrxrszParseResults.asListcs6tr |j}n|j}fddtfdd|DS)a Returns the named parse results as a nested dictionary. Example:: integer = Word(nums) date_str = integer("year") + '/' + integer("month") + '/' + integer("day") result = date_str.parseString('12/31/1999') print(type(result), repr(result)) # -> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) result_dict = result.asDict() print(type(result_dict), repr(result_dict)) # -> {'day': '1999', 'year': '12', 'month': '31'} # even though a ParseResults supports dict-like access, sometime you just need to have a dict import json print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} cs6t|tr.|jr|jSfdd|DSn|SdS)Ncsg|] }|qSrwrw)rr)toItemrwrxrsz7ParseResults.asDict..toItem..)rzr"rasDict)r)rrwrxrs  z#ParseResults.asDict..toItemc3s|]\}}||fVqdS)Nrw)rrr)rrwrxrsz&ParseResults.asDict..)PY_3rrr)rZitem_fnrw)rrxrs  zParseResults.asDictcCs8t|j}|jj|_|j|_|jj|j|j|_|S)zA Returns a new copy of a C{ParseResults} object. )r"rrrrrrr)rrrwrwrxrs   zParseResults.copyFc CsPd}g}tdd|jjD}|d}|s8d}d}d}d} |dk rJ|} n |jrV|j} | sf|rbdSd} |||d| d g7}xt|jD]\} } t| tr| |kr|| j|| |o|dk||g7}n|| jd|o|dk||g7}qd} | |kr|| } | s |rqnd} t t | } |||d| d | d | d g 7}qW|||d | d g7}dj |S) z (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names.  css(|] \}}|D]}|d|fVqqdS)rrNrw)rrrrrwrwrxrsz%ParseResults.asXML..z rNZITEM<>z.z %s%s- %s: z rrcss|]}t|tVqdS)N)rzr")rvvrwrwrxrssz %s%s[%d]: %s%s%sr) rrrrsortedrrzr"dumpranyrr) rrdepthfullr NLrrrrrrwrwrxrPs,   4.zParseResults.dumpcOstj|jf||dS)a Pretty-printer for parsed results as a list, using the C{pprint} module. Accepts additional positional or keyword args as defined for the C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint}) Example:: ident = Word(alphas, alphanums) num = Word(nums) func = Forward() term = ident | num | Group('(' + func + ')') func <<= ident + Group(Optional(delimitedList(term))) result = func.parseString("fna a,b,(fnb c,d,200),100") result.pprint(width=40) prints:: ['fna', ['a', 'b', ['(', 'fnb', ['c', 'd', '200'], ')'], '100']] N)pprintr)rrrrwrwrxr"}szParseResults.pprintcCs.|j|jj|jdk r|jp d|j|jffS)N)rrrrrr)rrwrwrx __getstate__s zParseResults.__getstate__cCsN|d|_|d\|_}}|_i|_|jj||dk rDt||_nd|_dS)Nrrr)rrrrrrr)rstaterZ inAccumNamesrwrwrx __setstate__s   zParseResults.__setstate__cCs|j|j|j|jfS)N)rrrr)rrwrwrx__getnewargs__szParseResults.__getnewargs__cCstt|t|jS)N)rrrr)rrwrwrxrszParseResults.__dir__)NNTT)N)r)NFrT)rrT)4rrrrrrzrrrrrrr __nonzero__rrrrrrrrrrrrrrrrrrrrrrrrrr rrrrrrrr"r#r%r&rrwrwrwrxr"-sh& ' 4  # =% - cCsF|}d|kot|knr4||ddkr4dS||jdd|S)aReturns current column within a string, counting newlines as line separators. The first column is number 1. Note: the default parsing behavior is to expand tabs in the input string before starting the parsing process. See L{I{ParserElement.parseString}} for more information on parsing strings containing C{}s, and suggested methods to maintain a consistent view of the parsed string, the parse location, and line and column positions within the parsed string. rrrr)rrfind)rstrgrrwrwrxr9s cCs|jdd|dS)aReturns current line number within a string, counting newlines as line separators. The first line is number 1. Note: the default parsing behavior is to expand tabs in the input string before starting the parsing process. See L{I{ParserElement.parseString}} for more information on parsing strings containing C{}s, and suggested methods to maintain a consistent view of the parsed string, the parse location, and line and column positions within the parsed string. rrrr)count)rr)rwrwrxrJs cCsF|jdd|}|jd|}|dkr2||d|S||ddSdS)zfReturns the line of text containing loc within a string, counting newlines as line separators. rrrrN)r(find)rr)ZlastCRZnextCRrwrwrxrGs  cCs8tdt|dt|dt||t||fdS)NzMatch z at loc z(%d,%d))printrrJr9)instringrexprrwrwrx_defaultStartDebugActionsr/cCs$tdt|dt|jdS)NzMatched z -> )r,rr{r)r-startlocZendlocr.toksrwrwrx_defaultSuccessDebugActionsr2cCstdt|dS)NzException raised:)r,r)r-rr.excrwrwrx_defaultExceptionDebugActionsr4cGsdS)zG'Do-nothing' debug action, to suppress debugging output during parsing.Nrw)rrwrwrxrQsrqc stkrfddSdgdgtdddkrFddd }dd d n tj}tjd }|dd d}|d|d|ffdd}d}ytdtdj}Wntk rt}YnX||_|S)Ncs|S)Nrw)rlrv)funcrwrxrysz_trim_arity..rFrqrocSs8tdkr dnd }tj| |dd|}|j|jfgS) Nror7rrqrr)limit)ror7r)system_version traceback extract_stackfilenamerJ)r8r frame_summaryrwrwrxr=sz"_trim_arity..extract_stackcSs$tj||d}|d}|j|jfgS)N)r8rrrs)r< extract_tbr>rJ)tbr8Zframesr?rwrwrxr@sz_trim_arity..extract_tb)r8rrcsxy |dd}dd<|Stk rdr>n4z.tjd}|dddddksjWd~Xdkrdd7<wYqXqWdS)NrTrrrq)r8rsrs)rr~exc_info)rrrA)r@ foundArityr6r8maxargspa_call_line_synthrwrxwrappers"  z_trim_arity..wrapperzr __class__)ror7)r)rrs) singleArgBuiltinsr;r<r=r@getattrr Exceptionr{)r6rEr=Z LINE_DIFFZ this_linerG func_namerw)r@rDr6r8rErFrx _trim_aritys*   rMcseZdZdZdZdZeddZeddZddd Z d d Z d d Z dddZ dddZ ddZddZddZddZddZddZddd Zd!d"Zdd#d$Zd%d&Zd'd(ZGd)d*d*eZed+k rGd,d-d-eZnGd.d-d-eZiZeZd/d/gZ dd0d1Z!eZ"ed2d3Z#dZ$edd5d6Z%dd7d8Z&e'dfd9d:Z(d;d<Z)e'fd=d>Z*e'dfd?d@Z+dAdBZ,dCdDZ-dEdFZ.dGdHZ/dIdJZ0dKdLZ1dMdNZ2dOdPZ3dQdRZ4dSdTZ5dUdVZ6dWdXZ7dYdZZ8dd[d\Z9d]d^Z:d_d`Z;dadbZdgdhZ?ddidjZ@dkdlZAdmdnZBdodpZCdqdrZDgfdsdtZEddudvZFfdwdxZGdydzZHd{d|ZId}d~ZJddZKdddZLdddZMZNS)r$z)Abstract base level parser element class.z FcCs |t_dS)a Overrides the default whitespace chars Example:: # default whitespace chars are space, and newline OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] # change to just treat newline as significant ParserElement.setDefaultWhitespaceChars(" \t") OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] N)r$DEFAULT_WHITE_CHARS)charsrwrwrxsetDefaultWhitespaceChars=s z'ParserElement.setDefaultWhitespaceCharscCs |t_dS)a Set class to be used for inclusion of string literals into a parser. Example:: # default literal class used is Literal integer = Word(nums) date_str = integer("year") + '/' + integer("month") + '/' + integer("day") date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] # change to Suppress ParserElement.inlineLiteralsUsing(Suppress) date_str = integer("year") + '/' + integer("month") + '/' + integer("day") date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] N)r$_literalStringClass)rrwrwrxinlineLiteralsUsingLsz!ParserElement.inlineLiteralsUsingcCst|_d|_d|_d|_||_d|_tj|_ d|_ d|_ d|_ t|_ d|_d|_d|_d|_d|_d|_d|_d|_d|_dS)NTFr)NNN)r parseAction failActionstrRepr resultsName saveAsListskipWhitespacer$rN whiteCharscopyDefaultWhiteCharsmayReturnEmptykeepTabs ignoreExprsdebug streamlined mayIndexErrorerrmsg modalResults debugActionsre callPreparse callDuringTry)rsavelistrwrwrxras(zParserElement.__init__cCs<tj|}|jdd|_|jdd|_|jr8tj|_|S)a$ Make a copy of this C{ParserElement}. Useful for defining different parse actions for the same parsing pattern, using copies of the original parse element. Example:: integer = Word(nums).setParseAction(lambda toks: int(toks[0])) integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) prints:: [5120, 100, 655360, 268435456] Equivalent form of C{expr.copy()} is just C{expr()}:: integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") N)rrSr]rZr$rNrY)rZcpyrwrwrxrxs  zParserElement.copycCs*||_d|j|_t|dr&|j|j_|S)af Define name for this expression, makes debugging and exception messages clearer. Example:: Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) z Expected exception)rrarrhr)rrrwrwrxsetNames    zParserElement.setNamecCs4|j}|jdr"|dd}d}||_| |_|S)aP Define name for referencing matching tokens as a nested attribute of the returned parse results. NOTE: this returns a *copy* of the original C{ParserElement} object; this is so that the client can define a basic element, such as an integer, and reference it in multiple places with different names. You can also set results names using the abbreviated syntax, C{expr("name")} in place of C{expr.setResultsName("name")} - see L{I{__call__}<__call__>}. Example:: date_str = (integer.setResultsName("year") + '/' + integer.setResultsName("month") + '/' + integer.setResultsName("day")) # equivalent form: date_str = integer("year") + '/' + integer("month") + '/' + integer("day") *NrrTrs)rendswithrVrb)rrlistAllMatchesZnewselfrwrwrxsetResultsNames  zParserElement.setResultsNameTcs@|r&|jdfdd }|_||_nt|jdr<|jj|_|S)zMethod to invoke the Python pdb debugger when this element is about to be parsed. Set C{breakFlag} to True to enable, False to disable. Tcsddl}|j||||S)Nr)pdbZ set_trace)r-r doActions callPreParsern) _parseMethodrwrxbreakersz'ParserElement.setBreak..breaker_originalParseMethod)TT)_parsersr)rZ breakFlagrrrw)rqrxsetBreaks  zParserElement.setBreakcOs&tttt||_|jdd|_|S)a  Define action to perform when successfully matching parse element definition. Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: - s = the original string being parsed (see note below) - loc = the location of the matching substring - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object If the functions in fns modify the tokens, they can return them as the return value from fn, and the modified list of tokens will replace the original. Otherwise, fn does not need to return any value. Optional keyword arguments: - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing Note: the default parsing behavior is to expand tabs in the input string before starting the parsing process. See L{I{parseString}} for more information on parsing strings containing C{}s, and suggested methods to maintain a consistent view of the parsed string, the parse location, and line and column positions within the parsed string. Example:: integer = Word(nums) date_str = integer + '/' + integer + '/' + integer date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] # use parse action to convert to ints at parse time integer = Word(nums).setParseAction(lambda toks: int(toks[0])) date_str = integer + '/' + integer + '/' + integer # note that integer fields are now ints, not strings date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] rfF)rmaprMrSrrf)rfnsrrwrwrxrs"zParserElement.setParseActioncOs4|jtttt|7_|jp,|jdd|_|S)z Add parse action to expression's list of parse actions. See L{I{setParseAction}}. See examples in L{I{copy}}. rfF)rSrrvrMrfr)rrwrrwrwrxaddParseActionszParserElement.addParseActioncsb|jdd|jddrtntx(|D] fdd}|jj|q&W|jpZ|jdd|_|S)aAdd a boolean predicate function to expression's list of parse actions. See L{I{setParseAction}} for function call signatures. Unlike C{setParseAction}, functions passed to C{addCondition} need to return boolean success/fail of the condition. Optional keyword arguments: - message = define a custom message to be used in the raised exception - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException Example:: integer = Word(nums).setParseAction(lambda toks: int(toks[0])) year_int = integer.copy() year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") date_str = year_int + '/' + integer + '/' + integer result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) messagezfailed user-defined conditionfatalFcs$tt|||s ||dS)N)rrM)rr5rv)exc_typefnrrwrxpasz&ParserElement.addCondition..parf)rr!rrSrrf)rrwrr}rw)r{r|rrx addConditions  zParserElement.addConditioncCs ||_|S)a Define action to perform if parsing fails at this expression. Fail acton fn is a callable function that takes the arguments C{fn(s,loc,expr,err)} where: - s = string being parsed - loc = location where expression match was attempted and failed - expr = the parse expression that failed - err = the exception thrown The function returns no value. It may throw C{L{ParseFatalException}} if it is desired to stop parsing immediately.)rT)rr|rwrwrx setFailActions zParserElement.setFailActionc CsZd}xP|rTd}xB|jD]8}yx|j||\}}d}qWWqtk rLYqXqWqW|S)NTF)r]rtr)rr-rZ exprsFoundeZdummyrwrwrx_skipIgnorables#s  zParserElement._skipIgnorablescCsL|jr|j||}|jrH|j}t|}x ||krF|||krF|d7}q(W|S)Nrr)r]rrXrYr)rr-rZwtinstrlenrwrwrxpreParse0s  zParserElement.preParsecCs|gfS)Nrw)rr-rrorwrwrx parseImpl<szParserElement.parseImplcCs|S)Nrw)rr-r tokenlistrwrwrx postParse?szParserElement.postParsec "Cs|j}|s|jr|jdr,|jd||||rD|jrD|j||}n|}|}yDy|j|||\}}Wn(tk rt|t||j |YnXWnXt k r} z<|jdr|jd|||| |jr|j|||| WYdd} ~ XnXn|o|jr|j||}n|}|}|j s$|t|krhy|j|||\}}Wn*tk rdt|t||j |YnXn|j|||\}}|j |||}t ||j|j|jd} |jr|s|jr|rVyRxL|jD]B} | ||| }|dk rt ||j|jot|t tf|jd} qWWnFt k rR} z(|jdr@|jd|||| WYdd} ~ XnXnNxL|jD]B} | ||| }|dk r^t ||j|jot|t tf|jd} q^W|r|jdr|jd||||| || fS)Nrrq)rrrr)r^rTrcrerrrrrrarr`rr"rVrWrbrSrfrzr) rr-rrorpZ debuggingprelocZ tokensStarttokenserrZ retTokensr|rwrwrx _parseNoCacheCsp             zParserElement._parseNoCachec Cs>y|j||dddStk r8t|||j|YnXdS)NF)ror)rtr!rra)rr-rrwrwrxtryParseszParserElement.tryParsec Cs2y|j||Wnttfk r(dSXdSdS)NFT)rrr)rr-rrwrwrx canParseNexts zParserElement.canParseNextc@seZdZddZdS)zParserElement._UnboundedCachecsdit|_fdd}fdd}fdd}tj|||_tj|||_tj|||_dS)Ncs j|S)N)r)rr)cache not_in_cacherwrxrsz3ParserElement._UnboundedCache.__init__..getcs ||<dS)Nrw)rrr)rrwrxsetsz3ParserElement._UnboundedCache.__init__..setcs jdS)N)r)r)rrwrxrsz5ParserElement._UnboundedCache.__init__..clear)rrtypes MethodTyperrr)rrrrrw)rrrxrs   z&ParserElement._UnboundedCache.__init__N)rrrrrwrwrwrx_UnboundedCachesrNc@seZdZddZdS)zParserElement._FifoCachecsht|_tfdd}fdd}fdd}tj|||_tj|||_tj|||_dS)Ncs j|S)N)r)rr)rrrwrxrsz.ParserElement._FifoCache.__init__..getcs"||<tkrjddS)NF)rpopitem)rrr)rsizerwrxrs z.ParserElement._FifoCache.__init__..setcs jdS)N)r)r)rrwrxrsz0ParserElement._FifoCache.__init__..clear)rr _OrderedDictrrrrr)rrrrrrw)rrrrxrs  z!ParserElement._FifoCache.__init__N)rrrrrwrwrwrx _FifoCachesrc@seZdZddZdS)zParserElement._FifoCachecsvt|_itjgfdd}fdd}fdd}tj|||_tj|||_tj|||_dS)Ncs j|S)N)r)rr)rrrwrxrsz.ParserElement._FifoCache.__init__..getcs2||<tkr$jjdj|dS)N)rrpopleftr)rrr)rkey_fiforrwrxrs z.ParserElement._FifoCache.__init__..setcsjjdS)N)r)r)rrrwrxrsz0ParserElement._FifoCache.__init__..clear) rr collectionsdequerrrrr)rrrrrrw)rrrrrxrs  z!ParserElement._FifoCache.__init__N)rrrrrwrwrwrxrsrc Csd\}}|||||f}tjtj}|j|} | |jkrtj|d7<y|j||||} Wn8tk r} z|j|| j | j WYdd} ~ XqX|j|| d| dj f| Sn4tj|d7<t | t r| | d| dj fSWdQRXdS)Nrrr)rrr)r$packrat_cache_lock packrat_cacherrpackrat_cache_statsrrrrHrrrzrK) rr-rrorpZHITZMISSlookuprrrrwrwrx _parseCaches$   zParserElement._parseCachecCs(tjjdgttjtjdd<dS)Nr)r$rrrrrwrwrwrx resetCaches zParserElement.resetCachecCs8tjs4dt_|dkr tjt_n tj|t_tjt_dS)aEnables "packrat" parsing, which adds memoizing to the parsing logic. Repeated parse attempts at the same string location (which happens often in many complex grammars) can immediately return a cached value, instead of re-executing parsing/validating code. Memoizing is done of both valid results and parsing exceptions. Parameters: - cache_size_limit - (default=C{128}) - if an integer value is provided will limit the size of the packrat cache; if None is passed, then the cache size will be unbounded; if 0 is passed, the cache will be effectively disabled. This speedup may break existing programs that use parse actions that have side-effects. For this reason, packrat parsing is disabled when you first import pyparsing. To activate the packrat feature, your program must call the class method C{ParserElement.enablePackrat()}. If your program uses C{psyco} to "compile as you go", you must call C{enablePackrat} before calling C{psyco.full()}. If you do not do this, Python will crash. For best results, call C{enablePackrat()} immediately after importing pyparsing. Example:: import pyparsing pyparsing.ParserElement.enablePackrat() TN)r$_packratEnabledrrrrrt)Zcache_size_limitrwrwrx enablePackrats   zParserElement.enablePackratcCstj|js|jx|jD] }|jqW|js<|j}y<|j|d\}}|rv|j||}t t }|j||Wn0t k r}ztj rn|WYdd}~XnX|SdS)aB Execute the parse expression with the given string. This is the main interface to the client code, once the complete expression has been built. If you want the grammar to require that the entire input string be successfully parsed, then set C{parseAll} to True (equivalent to ending the grammar with C{L{StringEnd()}}). Note: C{parseString} implicitly calls C{expandtabs()} on the input string, in order to report proper column numbers in parse actions. If the input string contains tabs and the grammar uses parse actions that use the C{loc} argument to index into the string being parsed, you can ensure you have a consistent view of the input string by: - calling C{parseWithTabs} on your grammar before calling C{parseString} (see L{I{parseWithTabs}}) - define your parse action using the full C{(s,loc,toks)} signature, and reference the input string using the parse action's C{s} argument - explictly expand the tabs in your input string before calling C{parseString} Example:: Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text rN) r$rr_ streamliner]r\ expandtabsrtrr r)rverbose_stacktrace)rr-parseAllrrrZser3rwrwrx parseString#s$    zParserElement.parseStringccs@|js|jx|jD] }|jqW|js8t|j}t|}d}|j}|j}t j d} yx||kon| |kry |||} ||| dd\} } Wnt k r| d}Yq`X| |kr| d7} | | | fV|r|||} | |kr| }q|d7}n| }q`| d}q`WWn4t k r:}zt j r&n|WYdd}~XnXdS)a Scan the input string for expression matches. Each match will return the matching tokens, start location, and end location. May be called with optional C{maxMatches} argument, to clip scanning after 'n' matches are found. If C{overlap} is specified, then overlapping matches will be reported. Note that the start and end locations are reported relative to the string being parsed. See L{I{parseString}} for more information on parsing strings with embedded tabs. Example:: source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" print(source) for tokens,start,end in Word(alphas).scanString(source): print(' '*start + '^'*(end-start)) print(' '*start + tokens[0]) prints:: sldjf123lsdjjkf345sldkjf879lkjsfd987 ^^^^^ sldjf ^^^^^^^ lsdjjkf ^^^^^^ sldkjf ^^^^^^ lkjsfd rF)rprrN)r_rr]r\rrrrrtr$rrrr)rr- maxMatchesZoverlaprrrZ preparseFnZparseFnmatchesrZnextLocrZnextlocr3rwrwrx scanStringUsB       zParserElement.scanStringcCsg}d}d|_yxh|j|D]Z\}}}|j||||rrt|trT||j7}nt|trh||7}n |j||}qW|j||ddd|D}djtt t |St k r}zt j rȂn|WYdd}~XnXdS)af Extension to C{L{scanString}}, to modify matching text with modified tokens that may be returned from a parse action. To use C{transformString}, define a grammar and attach a parse action to it that modifies the returned token list. Invoking C{transformString()} on a target string will then scan for matches, and replace the matched text patterns according to the logic in the parse action. C{transformString()} returns the resulting transformed string. Example:: wd = Word(alphas) wd.setParseAction(lambda toks: toks[0].title()) print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) Prints:: Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. rTNcSsg|] }|r|qSrwrw)rorwrwrxrsz1ParserElement.transformString..r)r\rrrzr"rrrrvr_flattenrr$r)rr-r ZlastErvrrr3rwrwrxrs(    zParserElement.transformStringcCsPytdd|j||DStk rJ}ztjr6n|WYdd}~XnXdS)a~ Another extension to C{L{scanString}}, simplifying the access to the tokens found to match the given parse expression. May be called with optional C{maxMatches} argument, to clip searching after 'n' matches are found. Example:: # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters cap_word = Word(alphas.upper(), alphas.lower()) print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) prints:: ['More', 'Iron', 'Lead', 'Gold', 'I'] cSsg|]\}}}|qSrwrw)rrvrrrwrwrxrsz.ParserElement.searchString..N)r"rrr$r)rr-rr3rwrwrx searchStrings zParserElement.searchStringc csXd}d}x<|j||dD]*\}}}|||V|r>|dV|}qW||dVdS)a[ Generator method to split a string using the given expression as a separator. May be called with optional C{maxsplit} argument, to limit the number of splits; and the optional C{includeSeparators} argument (default=C{False}), if the separating matching text should be included in the split results. Example:: punc = oneOf(list(".,;:/-!?")) print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) prints:: ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] r)rN)r) rr-maxsplitZincludeSeparatorsZsplitsZlastrvrrrwrwrxrs  zParserElement.splitcCsFt|trtj|}t|ts:tjdt|tdddSt||gS)a Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement converts them to L{Literal}s by default. Example:: greet = Word(alphas) + "," + Word(alphas) + "!" hello = "Hello, World!" print (hello, "->", greet.parseString(hello)) Prints:: Hello, World! -> ['Hello', ',', 'World', '!'] z4Cannot combine element of type %s with ParserElementrq) stacklevelN) rzrr$rQwarningswarnr SyntaxWarningr)rrrwrwrxrs    zParserElement.__add__cCsBt|trtj|}t|ts:tjdt|tdddS||S)z] Implementation of + operator when left operand is not a C{L{ParserElement}} z4Cannot combine element of type %s with ParserElementrq)rN)rzrr$rQrrrr)rrrwrwrxrs    zParserElement.__radd__cCsLt|trtj|}t|ts:tjdt|tdddSt|tj |gS)zQ Implementation of - operator, returns C{L{And}} with error stop z4Cannot combine element of type %s with ParserElementrq)rN) rzrr$rQrrrrr _ErrorStop)rrrwrwrx__sub__s    zParserElement.__sub__cCsBt|trtj|}t|ts:tjdt|tdddS||S)z] Implementation of - operator when left operand is not a C{L{ParserElement}} z4Cannot combine element of type %s with ParserElementrq)rN)rzrr$rQrrrr)rrrwrwrx__rsub__ s    zParserElement.__rsub__cst|tr|d}}nt|tr|d dd}|ddkrHd|df}t|dtr|ddkr|ddkrvtS|ddkrtS|dtSnJt|dtrt|dtr|\}}||8}ntdt|dt|dntdt||dkr td|dkrtd||ko2dknrBtd |rfd d |r|dkrt|}ntg||}n|}n|dkr}ntg|}|S) a Implementation of * operator, allows use of C{expr * 3} in place of C{expr + expr + expr}. Expressions may also me multiplied by a 2-integer tuple, similar to C{{min,max}} multipliers in regular expressions. Tuples may also include C{None} as in: - C{expr*(n,None)} or C{expr*(n,)} is equivalent to C{expr*n + L{ZeroOrMore}(expr)} (read as "at least n instances of C{expr}") - C{expr*(None,n)} is equivalent to C{expr*(0,n)} (read as "0 to n instances of C{expr}") - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)} - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)} Note that C{expr*(None,n)} does not raise an exception if more than n exprs exist in the input stream; that is, C{expr*(None,n)} does not enforce a maximum number of expr occurrences. If this behavior is desired, then write C{expr*(None,n) + ~expr} rNrqrrz7cannot multiply 'ParserElement' and ('%s','%s') objectsz0cannot multiply 'ParserElement' and '%s' objectsz/cannot multiply ParserElement by negative valuez@second tuple value must be greater or equal to first tuple valuez+cannot multiply ParserElement by 0 or (0,0)cs(|dkrt|dStSdS)Nrr)r)n)makeOptionalListrrwrxr]sz/ParserElement.__mul__..makeOptionalList)NN) rzrutupler2rrr ValueErrorr)rrZ minElementsZ optElementsrrw)rrrx__mul__,sD             zParserElement.__mul__cCs |j|S)N)r)rrrwrwrx__rmul__pszParserElement.__rmul__cCsFt|trtj|}t|ts:tjdt|tdddSt||gS)zI Implementation of | operator - returns C{L{MatchFirst}} z4Cannot combine element of type %s with ParserElementrq)rN) rzrr$rQrrrrr)rrrwrwrx__or__ss    zParserElement.__or__cCsBt|trtj|}t|ts:tjdt|tdddS||BS)z] Implementation of | operator when left operand is not a C{L{ParserElement}} z4Cannot combine element of type %s with ParserElementrq)rN)rzrr$rQrrrr)rrrwrwrx__ror__s    zParserElement.__ror__cCsFt|trtj|}t|ts:tjdt|tdddSt||gS)zA Implementation of ^ operator - returns C{L{Or}} z4Cannot combine element of type %s with ParserElementrq)rN) rzrr$rQrrrrr)rrrwrwrx__xor__s    zParserElement.__xor__cCsBt|trtj|}t|ts:tjdt|tdddS||AS)z] Implementation of ^ operator when left operand is not a C{L{ParserElement}} z4Cannot combine element of type %s with ParserElementrq)rN)rzrr$rQrrrr)rrrwrwrx__rxor__s    zParserElement.__rxor__cCsFt|trtj|}t|ts:tjdt|tdddSt||gS)zC Implementation of & operator - returns C{L{Each}} z4Cannot combine element of type %s with ParserElementrq)rN) rzrr$rQrrrrr )rrrwrwrx__and__s    zParserElement.__and__cCsBt|trtj|}t|ts:tjdt|tdddS||@S)z] Implementation of & operator when left operand is not a C{L{ParserElement}} z4Cannot combine element of type %s with ParserElementrq)rN)rzrr$rQrrrr)rrrwrwrx__rand__s    zParserElement.__rand__cCst|S)zE Implementation of ~ operator - returns C{L{NotAny}} )r)rrwrwrx __invert__szParserElement.__invert__cCs|dk r|j|S|jSdS)a  Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}. If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be passed as C{True}. If C{name} is omitted, same as calling C{L{copy}}. Example:: # these are equivalent userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") N)rmr)rrrwrwrx__call__s zParserElement.__call__cCst|S)z Suppresses the output of this C{ParserElement}; useful to keep punctuation from cluttering up returned output. )r+)rrwrwrxsuppressszParserElement.suppresscCs d|_|S)a Disables the skipping of whitespace before matching the characters in the C{ParserElement}'s defined pattern. This is normally only used internally by the pyparsing module, but may be needed in some whitespace-sensitive grammars. F)rX)rrwrwrxleaveWhitespaceszParserElement.leaveWhitespacecCsd|_||_d|_|S)z8 Overrides the default whitespace chars TF)rXrYrZ)rrOrwrwrxsetWhitespaceCharssz ParserElement.setWhitespaceCharscCs d|_|S)z Overrides default behavior to expand C{}s to spaces before parsing the input string. Must be called before C{parseString} when the input grammar contains elements that match C{} characters. T)r\)rrwrwrx parseWithTabsszParserElement.parseWithTabscCsLt|trt|}t|tr4||jkrH|jj|n|jjt|j|S)a Define expression to be ignored (e.g., comments) while doing pattern matching; may be called repeatedly, to define multiple comment or other ignorable patterns. Example:: patt = OneOrMore(Word(alphas)) patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] patt.ignore(cStyleComment) patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] )rzrr+r]rr)rrrwrwrxignores   zParserElement.ignorecCs"|pt|p t|ptf|_d|_|S)zT Enable display of debugging messages while doing pattern matching. T)r/r2r4rcr^)rZ startActionZ successActionZexceptionActionrwrwrxsetDebugActions s  zParserElement.setDebugActionscCs|r|jtttnd|_|S)a Enable display of debugging messages while doing pattern matching. Set C{flag} to True to enable, False to disable. Example:: wd = Word(alphas).setName("alphaword") integer = Word(nums).setName("numword") term = wd | integer # turn on debugging for wd wd.setDebug() OneOrMore(term).parseString("abc 123 xyz 890") prints:: Match alphaword at loc 0(1,1) Matched alphaword -> ['abc'] Match alphaword at loc 3(1,4) Exception raised:Expected alphaword (at char 4), (line:1, col:5) Match alphaword at loc 7(1,8) Matched alphaword -> ['xyz'] Match alphaword at loc 11(1,12) Exception raised:Expected alphaword (at char 12), (line:1, col:13) Match alphaword at loc 15(1,16) Exception raised:Expected alphaword (at char 15), (line:1, col:16) The output shown is that produced by the default debug actions - custom debug actions can be specified using L{setDebugActions}. Prior to attempting to match the C{wd} expression, the debugging message C{"Match at loc (,)"} is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"} message is shown. Also note the use of L{setName} to assign a human-readable name to the expression, which makes debugging and exception messages easier to understand - for instance, the default name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}. F)rr/r2r4r^)rflagrwrwrxsetDebugs#zParserElement.setDebugcCs|jS)N)r)rrwrwrxr@szParserElement.__str__cCst|S)N)r)rrwrwrxrCszParserElement.__repr__cCsd|_d|_|S)NT)r_rU)rrwrwrxrFszParserElement.streamlinecCsdS)Nrw)rrrwrwrxcheckRecursionKszParserElement.checkRecursioncCs|jgdS)zj Check defined expressions for valid structure, check for infinite recursive definitions. N)r)r validateTracerwrwrxvalidateNszParserElement.validatecCsy |j}Wn2tk r>t|d}|j}WdQRXYnXy |j||Stk r|}ztjrhn|WYdd}~XnXdS)z Execute the parse expression on the given file or filename. If a filename is specified (instead of a file object), the entire file is opened, read, and closed before parsing. rN)readropenrrr$r)rZfile_or_filenamerZ file_contentsfr3rwrwrx parseFileTs   zParserElement.parseFilecsHt|tr"||kp t|t|kSt|tr6|j|Stt||kSdS)N)rzr$varsrrsuper)rr)rHrwrx__eq__hs    zParserElement.__eq__cCs ||k S)Nrw)rrrwrwrx__ne__pszParserElement.__ne__cCs tt|S)N)hashid)rrwrwrx__hash__sszParserElement.__hash__cCs||kS)Nrw)rrrwrwrx__req__vszParserElement.__req__cCs ||k S)Nrw)rrrwrwrx__rne__yszParserElement.__rne__c Cs0y|jt||ddStk r*dSXdS)a Method for quick testing of a parser against a test string. Good for simple inline microtests of sub expressions while building up larger parser. Parameters: - testString - to test against this expression for a match - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests Example:: expr = Word(nums) assert expr.matches("100") )rTFN)rrr)rZ testStringrrwrwrxr|s zParserElement.matches#cCst|tr"tttj|jj}t|tr4t|}g}g}d} x|D]} |dk rb|j | dsl|rx| rx|j | qH| s~qHdj || g} g}y:| j dd} |j | |d} | j | j|d| o| } Wntk rx} zt| trdnd }d| kr0| j t| j| | j d t| j| d d |n| j d | jd || j d t| | ob|} | } WYdd} ~ XnDtk r}z&| j dt|| o|} |} WYdd}~XnX|r|r| j d tdj | |j | | fqHW| |fS)a3 Execute the parse expression on a series of test strings, showing each test, the parsed results or where the parse failed. Quick and easy way to run a parse expression against a list of sample strings. Parameters: - tests - a list of separate test strings, or a multiline string of test strings - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests - comment - (default=C{'#'}) - expression for indicating embedded comments in the test string; pass None to disable comment filtering - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline; if False, only dump nested list - printResults - (default=C{True}) prints test output to stdout - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing Returns: a (success, results) tuple, where success indicates that all tests succeeded (or failed if C{failureTests} is True), and the results contain a list of lines of each test's output Example:: number_expr = pyparsing_common.number.copy() result = number_expr.runTests(''' # unsigned integer 100 # negative integer -100 # float with scientific notation 6.02e23 # integer with scientific notation 1e-12 ''') print("Success" if result[0] else "Failed!") result = number_expr.runTests(''' # stray character 100Z # missing leading digit before '.' -.100 # too many '.' 3.14.159 ''', failureTests=True) print("Success" if result[0] else "Failed!") prints:: # unsigned integer 100 [100] # negative integer -100 [-100] # float with scientific notation 6.02e23 [6.02e+23] # integer with scientific notation 1e-12 [1e-12] Success # stray character 100Z ^ FAIL: Expected end of text (at char 3), (line:1, col:4) # missing leading digit before '.' -.100 ^ FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) # too many '.' 3.14.159 ^ FAIL: Expected end of text (at char 4), (line:1, col:5) Success Each test string must be on a single line. If you want to test a string that spans multiple lines, create a test like this:: expr.runTest(r"this is a test\n of strings that spans \n 3 lines") (Note that this is a raw string literal, you must include the leading 'r'.) TNFrz\n)r)r z(FATAL)r rr^zFAIL: zFAIL-EXCEPTION: )rzrrrvr{rrstrip splitlinesrrrrrrrrr!rGrr9rKr,)rZtestsrZcommentZfullDumpZ printResultsZ failureTestsZ allResultsZcommentssuccessrvr resultrrzr3rwrwrxrunTestssNW     $   zParserElement.runTests)F)F)T)T)TT)TT)r)F)N)T)F)T)TrTTF)OrrrrrNr staticmethodrPrRrrrirmrurrxr~rrrrrrrrrrrrrrrrrrtrrrr_MAX_INTrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr __classcell__rwrw)rHrxr$8s     &     H   " 2G+    D           )    cs eZdZdZfddZZS)r,zT Abstract C{ParserElement} subclass, for defining atomic matching patterns. cstt|jdddS)NF)rg)rr,r)r)rHrwrxr szToken.__init__)rrrrrrrwrw)rHrxr, scs eZdZdZfddZZS)r z, An empty token, will always match. cs$tt|jd|_d|_d|_dS)Nr TF)rr rrr[r`)r)rHrwrxr szEmpty.__init__)rrrrrrrwrw)rHrxr  scs*eZdZdZfddZdddZZS)rz( A token that will never match. cs*tt|jd|_d|_d|_d|_dS)NrTFzUnmatchable token)rrrrr[r`ra)r)rHrwrxr* s zNoMatch.__init__TcCst|||j|dS)N)rra)rr-rrorwrwrxr1 szNoMatch.parseImpl)T)rrrrrrrrwrw)rHrxr& s cs*eZdZdZfddZdddZZS)ra Token to exactly match a specified string. Example:: Literal('blah').parseString('blah') # -> ['blah'] Literal('blah').parseString('blahfooblah') # -> ['blah'] Literal('blah').parseString('bla') # -> Exception: Expected "blah" For case-insensitive matching, use L{CaselessLiteral}. For keyword matching (force word break before and after the matched string), use L{Keyword} or L{CaselessKeyword}. c stt|j||_t||_y|d|_Wn*tk rVtj dt ddt |_ YnXdt |j|_d|j|_d|_d|_dS)Nrz2null string passed to Literal; use Empty() insteadrq)rz"%s"z Expected F)rrrmatchrmatchLenfirstMatchCharrrrrr rHrrrar[r`)r matchString)rHrwrxrC s    zLiteral.__init__TcCsJ|||jkr6|jdks&|j|j|r6||j|jfSt|||j|dS)Nrr)rr startswithrrra)rr-rrorwrwrxrV szLiteral.parseImpl)T)rrrrrrrrwrw)rHrxr5 s  csLeZdZdZedZdfdd Zddd Zfd d Ze d d Z Z S)ra\ Token to exactly match a specified string as a keyword, that is, it must be immediately followed by a non-keyword character. Compare with C{L{Literal}}: - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}. - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'} Accepts two optional constructor arguments in addition to the keyword string: - C{identChars} is a string of characters that would be valid identifier characters, defaulting to all alphanumerics + "_" and "$" - C{caseless} allows case-insensitive matching, default is C{False}. Example:: Keyword("start").parseString("start") # -> ['start'] Keyword("start").parseString("starting") # -> Exception For case-insensitive matching, use L{CaselessKeyword}. z_$NFc stt|j|dkrtj}||_t||_y|d|_Wn$tk r^t j dt ddYnXd|j|_ d|j |_ d|_d|_||_|r|j|_|j}t||_dS)Nrz2null string passed to Keyword; use Empty() insteadrq)rz"%s"z Expected F)rrrDEFAULT_KEYWORD_CHARSrrrrrrrrrrar[r`caselessupper caselessmatchr identChars)rrrr)rHrwrxrq s&    zKeyword.__init__TcCs|jr|||||jj|jkr|t||jksL|||jj|jkr|dksj||dj|jkr||j|jfSnv|||jkr|jdks|j|j|r|t||jks|||j|jkr|dks||d|jkr||j|jfSt |||j |dS)Nrrr) rrrrrrrrrrra)rr-rrorwrwrxr s*&zKeyword.parseImplcstt|j}tj|_|S)N)rrrrr)rr)rHrwrxr sz Keyword.copycCs |t_dS)z,Overrides the default Keyword chars N)rr)rOrwrwrxsetDefaultKeywordChars szKeyword.setDefaultKeywordChars)NF)T) rrrrr3rrrrrrrrwrw)rHrxr^ s   cs*eZdZdZfddZdddZZS)ral Token to match a specified string, ignoring case of letters. Note: the matched results will always be in the case of the given match string, NOT the case of the input text. Example:: OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] (Contrast with example for L{CaselessKeyword}.) cs6tt|j|j||_d|j|_d|j|_dS)Nz'%s'z Expected )rrrr returnStringrra)rr)rHrwrxr s zCaselessLiteral.__init__TcCs@||||jj|jkr,||j|jfSt|||j|dS)N)rrrrrra)rr-rrorwrwrxr szCaselessLiteral.parseImpl)T)rrrrrrrrwrw)rHrxr s  cs,eZdZdZdfdd Zd ddZZS) rz Caseless version of L{Keyword}. Example:: OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] (Contrast with example for L{CaselessLiteral}.) Ncstt|j||dddS)NT)r)rrr)rrr)rHrwrxr szCaselessKeyword.__init__TcCsj||||jj|jkrV|t||jksF|||jj|jkrV||j|jfSt|||j|dS)N)rrrrrrrra)rr-rrorwrwrxr s*zCaselessKeyword.parseImpl)N)T)rrrrrrrrwrw)rHrxr scs,eZdZdZdfdd Zd ddZZS) rlax A variation on L{Literal} which matches "close" matches, that is, strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters: - C{match_string} - string to be matched - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match The results from a successful parse will contain the matched text from the input string and the following named results: - C{mismatches} - a list of the positions within the match_string where mismatches were found - C{original} - the original match_string used to compare against the input string If C{mismatches} is an empty list, then the match was an exact match. Example:: patt = CloseMatch("ATCATCGAATGGA") patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) # exact match patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) # close match allowing up to 2 mismatches patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) rrcsBtt|j||_||_||_d|j|jf|_d|_d|_dS)Nz&Expected %r (with up to %d mismatches)F) rrlrr match_string maxMismatchesrar`r[)rrr)rHrwrxr szCloseMatch.__init__TcCs|}t|}|t|j}||kr|j}d}g} |j} xtt||||jD]0\}} | \} } | | krP| j|t| | krPPqPW|d}t|||g}|j|d<| |d<||fSt|||j|dS)Nrrroriginal mismatches) rrrrrrr"rra)rr-rrostartrmaxlocrZmatch_stringlocrrZs_msrcmatresultsrwrwrxr s("   zCloseMatch.parseImpl)rr)T)rrrrrrrrwrw)rHrxrl s cs8eZdZdZd fdd Zdd d Zfd d ZZS)r/a Token for matching words composed of allowed character sets. Defined with string containing all allowed initial characters, an optional string containing allowed body characters (if omitted, defaults to the initial character set), and an optional minimum, maximum, and/or exact length. The default value for C{min} is 1 (a minimum value < 1 is not valid); the default values for C{max} and C{exact} are 0, meaning no maximum or exact length restriction. An optional C{excludeChars} parameter can list characters that might be found in the input C{bodyChars} string; useful to define a word of all printables except for one or two characters, for instance. L{srange} is useful for defining custom character set strings for defining C{Word} expressions, using range notation from regular expression character sets. A common mistake is to use C{Word} to match a specific literal string, as in C{Word("Address")}. Remember that C{Word} uses the string argument to define I{sets} of matchable characters. This expression would match "Add", "AAA", "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'. To match an exact literal string, use L{Literal} or L{Keyword}. pyparsing includes helper strings for building Words: - L{alphas} - L{nums} - L{alphanums} - L{hexnums} - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.) - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.) - L{printables} (any non-whitespace character) Example:: # a word composed of digits integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) # a word with a leading capital, and zero or more lowercase capital_word = Word(alphas.upper(), alphas.lower()) # hostnames are alphanumeric, with leading alpha, and '-' hostname = Word(alphas, alphanums+'-') # roman numeral (not a strict parser, accepts invalid mix of characters) roman = Word("IVXLCDM") # any string of non-whitespace characters, except for ',' csv_value = Word(printables, excludeChars=",") NrrrFc stt|jrFdjfdd|D}|rFdjfdd|D}||_t||_|rl||_t||_n||_t||_|dk|_ |dkrt d||_ |dkr||_ nt |_ |dkr||_ ||_ t||_d|j|_d |_||_d |j|jkr|dkr|dkr|dkr|j|jkr8d t|j|_nHt|jdkrfd tj|jt|jf|_nd t|jt|jf|_|jrd|jd|_ytj|j|_Wntk rd|_YnXdS)Nrc3s|]}|kr|VqdS)Nrw)rr) excludeCharsrwrxr7 sz Word.__init__..c3s|]}|kr|VqdS)Nrw)rr)rrwrxr9 srrrzZcannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permittedz Expected Frz[%s]+z%s[%s]*z [%s][%s]*z\b)rr/rr initCharsOrigr initChars bodyCharsOrig bodyChars maxSpecifiedrminLenmaxLenrrrrar` asKeyword_escapeRegexRangeCharsreStringrrdescapecompilerK)rrrminmaxexactrr)rH)rrxr4 sT      0 z Word.__init__Tc CsD|jr<|jj||}|s(t|||j||j}||jfS|||jkrZt|||j||}|d7}t|}|j}||j }t ||}x ||kr|||kr|d7}qWd} |||j krd} |j r||kr|||krd} |j r|dkr||d|ks||kr|||krd} | r4t|||j|||||fS)NrrFTr)rdrrraendgrouprrrrr rrr) rr-rrorrrZ bodycharsrZthrowExceptionrwrwrxrj s6    4zWord.parseImplc stytt|jStk r"YnX|jdkrndd}|j|jkr^d||j||jf|_nd||j|_|jS)NcSs$t|dkr|dddS|SdS)Nz...)r)rrwrwrx charsAsStr s z Word.__str__..charsAsStrz W:(%s,%s)zW:(%s))rr/rrKrUrr)rr)rHrwrxr s  z Word.__str__)NrrrrFN)T)rrrrrrrrrwrw)rHrxr/ s.6 #csFeZdZdZeejdZd fdd Zd ddZ fd d Z Z S) r'a Token for matching strings that match a given regular expression. Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. If the given regex contains named groups (defined using C{(?P...)}), these will be preserved as named parse results. Example:: realnum = Regex(r"[+-]?\d+\.\d*") date = Regex(r'(?P\d{4})-(?P\d\d?)-(?P\d\d?)') # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") z[A-Z]rc stt|jt|tr|s,tjdtdd||_||_ yt j |j|j |_ |j|_ Wqt jk rtjd|tddYqXn2t|tjr||_ t||_|_ ||_ ntdt||_d|j|_d|_d|_d S) zThe parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags.z0null string passed to Regex; use Empty() insteadrq)rz$invalid pattern (%s) passed to RegexzCRegex may only be constructed with a string or a compiled RE objectz Expected FTN)rr'rrzrrrrpatternflagsrdr r sre_constantserrorcompiledREtyper{rrrrar`r[)rrr)rHrwrxr s.         zRegex.__init__TcCsd|jj||}|s"t|||j||j}|j}t|j}|r\x|D]}||||<qHW||fS)N)rdrrrar groupdictr"r)rr-rrordrrrwrwrxr s  zRegex.parseImplc sDytt|jStk r"YnX|jdkr>dt|j|_|jS)NzRe:(%s))rr'rrKrUrr)r)rHrwrxr s z Regex.__str__)r)T) rrrrrrdr rrrrrrwrw)rHrxr' s  " cs8eZdZdZd fdd Zd ddZfd d ZZS) r%a Token for matching strings that are delimited by quoting characters. Defined with the following parameters: - quoteChar - string of one or more characters defining the quote delimiting string - escChar - character to escape quotes, typically backslash (default=C{None}) - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None}) - multiline - boolean indicating whether quotes can span multiple lines (default=C{False}) - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True}) - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar) - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True}) Example:: qs = QuotedString('"') print(qs.searchString('lsjdf "This is the quote" sldjf')) complex_qs = QuotedString('{{', endQuoteChar='}}') print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) sql_qs = QuotedString('"', escQuote='""') print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) prints:: [['This is the quote']] [['This is the "quote"']] [['This is the quote with "embedded" quotes']] NFTc sNttj|j}|s0tjdtddt|dkr>|}n"|j}|s`tjdtddt|_t |_ |d_ |_ t |_ |_|_|_|_|rtjtjB_dtjjtj d|dk rt|pdf_n.)z|(?:%s)z|(?:%s.)z(.)z)*%sz$invalid pattern (%s) passed to Regexz Expected FTrs)%rr%rrrrr SyntaxError quoteCharr quoteCharLenfirstQuoteCharrendQuoteCharLenescCharescQuoteunquoteResultsconvertWhitespaceEscapesrd MULTILINEDOTALLrr rrrrescCharReplacePatternr rrrrrrar`r[)rrr r!Z multiliner"rr#)rH)rrxr sf       6     zQuotedString.__init__c Cs|||jkr|jj||pd}|s4t|||j||j}|j}|jr||j|j }t |t rd|kr|j rddddd}x |j D]\}}|j||}qW|jrtj|jd|}|jr|j|j|j}||fS)N\ r  )z\tz\nz\fz\rz\g<1>)rrdrrrarrr"rrrzrr#rrr rr&r!r) rr-rrorrZws_mapZwslitZwscharrwrwrxrG s(  zQuotedString.parseImplc sFytt|jStk r"YnX|jdkr@d|j|jf|_|jS)Nz.quoted string, starting with %s ending with %s)rr%rrKrUrr)r)rHrwrxrj s zQuotedString.__str__)NNFTNT)T)rrrrrrrrrwrw)rHrxr% sA #cs8eZdZdZd fdd Zd ddZfd d ZZS) r a Token for matching words composed of characters I{not} in a given set (will include whitespace in matched characters if not listed in the provided exclusion set - see example). Defined with string containing all disallowed characters, and an optional minimum, maximum, and/or exact length. The default value for C{min} is 1 (a minimum value < 1 is not valid); the default values for C{max} and C{exact} are 0, meaning no maximum or exact length restriction. Example:: # define a comma-separated-value as anything that is not a ',' csv_value = CharsNotIn(',') print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) prints:: ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] rrrcstt|jd|_||_|dkr*td||_|dkr@||_nt|_|dkrZ||_||_t ||_ d|j |_ |jdk|_ d|_ dS)NFrrzfcannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permittedrz Expected )rr rrXnotCharsrrrrrrrar[r`)rr+r r r )rHrwrxr s    zCharsNotIn.__init__TcCs|||jkrt|||j||}|d7}|j}t||jt|}x ||krd|||krd|d7}qFW|||jkrt|||j|||||fS)Nrr)r+rrar rrr)rr-rrorZnotcharsmaxlenrwrwrxr s   zCharsNotIn.parseImplc sdytt|jStk r"YnX|jdkr^t|jdkrRd|jdd|_n d|j|_|jS)Nrz !W:(%s...)z!W:(%s))rr rrKrUrr+)r)rHrwrxr s  zCharsNotIn.__str__)rrrr)T)rrrrrrrrrwrw)rHrxr v s cs<eZdZdZddddddZdfd d ZdddZZS)r.a Special matching class for matching whitespace. Normally, whitespace is ignored by pyparsing grammars. This class is included when some whitespace structures are significant. Define with a string containing the whitespace characters to be matched; default is C{" \t\r\n"}. Also takes optional C{min}, C{max}, and C{exact} arguments, as defined for the C{L{Word}} class. zzzzz)rr(rr*r) rrrcsttj|_jdjfddjDdjddjD_d_dj_ |_ |dkrt|_ nt _ |dkr|_ |_ dS)Nrc3s|]}|jkr|VqdS)N) matchWhite)rr)rrwrxr sz!White.__init__..css|]}tj|VqdS)N)r. whiteStrs)rrrwrwrxr sTz Expected r) rr.rr.rrrYrr[rarrr)rZwsr r r )rH)rrxr s  zWhite.__init__TcCs|||jkrt|||j||}|d7}||j}t|t|}x"||krd|||jkrd|d7}qDW|||jkrt|||j|||||fS)Nrr)r.rrarr rr)rr-rrorrrwrwrxr s  zWhite.parseImpl)r-rrrr)T)rrrrr/rrrrwrw)rHrxr. scseZdZfddZZS)_PositionTokencs(tt|j|jj|_d|_d|_dS)NTF)rr0rrHrrr[r`)r)rHrwrxr s z_PositionToken.__init__)rrrrrrwrw)rHrxr0 sr0cs2eZdZdZfddZddZd ddZZS) rzb Token to advance to a specific column of input text; useful for tabular report scraping. cstt|j||_dS)N)rrrr9)rcolno)rHrwrxr szGoToColumn.__init__cCs`t|||jkr\t|}|jr*|j||}x0||krZ||jrZt|||jkrZ|d7}q,W|S)Nrr)r9rr]risspace)rr-rrrwrwrxr s & zGoToColumn.preParseTcCsDt||}||jkr"t||d|||j|}|||}||fS)NzText not in expected column)r9r)rr-rroZthiscolZnewlocrrwrwrxr s    zGoToColumn.parseImpl)T)rrrrrrrrrwrw)rHrxr s  cs*eZdZdZfddZdddZZS)ra Matches if current position is at the beginning of a line within the parse string Example:: test = ''' AAA this line AAA and this line AAA but not this one B AAA and definitely not this one ''' for t in (LineStart() + 'AAA' + restOfLine).searchString(test): print(t) Prints:: ['AAA', ' this line'] ['AAA', ' and this line'] cstt|jd|_dS)NzExpected start of line)rrrra)r)rHrwrxr& szLineStart.__init__TcCs*t||dkr|gfSt|||j|dS)Nrr)r9rra)rr-rrorwrwrxr* szLineStart.parseImpl)T)rrrrrrrrwrw)rHrxr s cs*eZdZdZfddZdddZZS)rzU Matches if current position is at the end of a line within the parse string cs,tt|j|jtjjddd|_dS)NrrzExpected end of line)rrrrr$rNrra)r)rHrwrxr3 szLineEnd.__init__TcCsb|t|kr6||dkr$|ddfSt|||j|n(|t|krN|dgfSt|||j|dS)Nrrr)rrra)rr-rrorwrwrxr8 s     zLineEnd.parseImpl)T)rrrrrrrrwrw)rHrxr/ s cs*eZdZdZfddZdddZZS)r*zM Matches if current position is at the beginning of the parse string cstt|jd|_dS)NzExpected start of text)rr*rra)r)rHrwrxrG szStringStart.__init__TcCs0|dkr(||j|dkr(t|||j||gfS)Nr)rrra)rr-rrorwrwrxrK szStringStart.parseImpl)T)rrrrrrrrwrw)rHrxr*C s cs*eZdZdZfddZdddZZS)r)zG Matches if current position is at the end of the parse string cstt|jd|_dS)NzExpected end of text)rr)rra)r)rHrwrxrV szStringEnd.__init__TcCs^|t|krt|||j|n<|t|kr6|dgfS|t|krJ|gfSt|||j|dS)Nrr)rrra)rr-rrorwrwrxrZ s    zStringEnd.parseImpl)T)rrrrrrrrwrw)rHrxr)R s cs.eZdZdZeffdd ZdddZZS)r1ap Matches if the current position is at the beginning of a Word, and is not preceded by any character in a given set of C{wordChars} (default=C{printables}). To emulate the C{} behavior of regular expressions, use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of the string being parsed, or at the beginning of a line. cs"tt|jt||_d|_dS)NzNot at the start of a word)rr1rr wordCharsra)rr3)rHrwrxrl s zWordStart.__init__TcCs@|dkr8||d|jks(|||jkr8t|||j||gfS)Nrrr)r3rra)rr-rrorwrwrxrq s zWordStart.parseImpl)T)rrrrrVrrrrwrw)rHrxr1d scs.eZdZdZeffdd ZdddZZS)r0aZ Matches if the current position is at the end of a Word, and is not followed by any character in a given set of C{wordChars} (default=C{printables}). To emulate the C{} behavior of regular expressions, use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of the string being parsed, or at the end of a line. cs(tt|jt||_d|_d|_dS)NFzNot at the end of a word)rr0rrr3rXra)rr3)rHrwrxr s zWordEnd.__init__TcCsPt|}|dkrH||krH|||jks8||d|jkrHt|||j||gfS)Nrrr)rr3rra)rr-rrorrwrwrxr s zWordEnd.parseImpl)T)rrrrrVrrrrwrw)rHrxr0x scseZdZdZdfdd ZddZddZd d Zfd d Zfd dZ fddZ dfdd Z gfddZ fddZ ZS)r z^ Abstract subclass of ParserElement, for combining and post-processing parsed tokens. Fc stt|j|t|tr"t|}t|tr.F)rr rrzrrrr$rQexprsrIterableallrvrre)rr4rg)rHrwrxr s     zParseExpression.__init__cCs |j|S)N)r4)rrrwrwrxr szParseExpression.__getitem__cCs|jj|d|_|S)N)r4rrU)rrrwrwrxr s zParseExpression.appendcCs4d|_dd|jD|_x|jD] }|jq W|S)z~Extends C{leaveWhitespace} defined in base class, and also invokes C{leaveWhitespace} on all contained expressions.FcSsg|] }|jqSrw)r)rrrwrwrxr sz3ParseExpression.leaveWhitespace..)rXr4r)rrrwrwrxr s   zParseExpression.leaveWhitespacecszt|trF||jkrvtt|j|xP|jD]}|j|jdq,Wn0tt|j|x|jD]}|j|jdq^W|S)Nrrrsrs)rzr+r]rr rr4)rrr)rHrwrxr s    zParseExpression.ignorec sLytt|jStk r"YnX|jdkrFd|jjt|jf|_|jS)Nz%s:(%s)) rr rrKrUrHrrr4)r)rHrwrxr s zParseExpression.__str__cs0tt|jx|jD] }|jqWt|jdkr|jd}t||jr|j r|jdkr|j r|jdd|jdg|_d|_ |j |j O_ |j |j O_ |jd}t||jo|j o|jdko|j r|jdd|jdd|_d|_ |j |j O_ |j |j O_ dt ||_|S)Nrqrrrz Expected rsrs)rr rr4rrzrHrSrVr^rUr[r`rra)rrr)rHrwrxr s0         zParseExpression.streamlinecstt|j||}|S)N)rr rm)rrrlr)rHrwrxrm szParseExpression.setResultsNamecCs:|dd|g}x|jD]}|j|qW|jgdS)N)r4rr)rrtmprrwrwrxr s zParseExpression.validatecs$tt|j}dd|jD|_|S)NcSsg|] }|jqSrw)r)rrrwrwrxr sz(ParseExpression.copy..)rr rr4)rr)rHrwrxr szParseExpression.copy)F)F)rrrrrrrrrrrrmrrrrwrw)rHrxr s " csTeZdZdZGdddeZdfdd ZdddZd d Zd d Z d dZ Z S)ra  Requires all given C{ParseExpression}s to be found in the given order. Expressions may be separated by whitespace. May be constructed using the C{'+'} operator. May also be constructed using the C{'-'} operator, which will suppress backtracking. Example:: integer = Word(nums) name_expr = OneOrMore(Word(alphas)) expr = And([integer("id"),name_expr("name"),integer("age")]) # more easily written as: expr = integer("id") + name_expr("name") + integer("age") cseZdZfddZZS)zAnd._ErrorStopcs&ttj|j||d|_|jdS)N-)rrrrrr)rrr)rHrwrxr szAnd._ErrorStop.__init__)rrrrrrwrw)rHrxr srTcsRtt|j||tdd|jD|_|j|jdj|jdj|_d|_ dS)Ncss|] }|jVqdS)N)r[)rrrwrwrxr szAnd.__init__..rT) rrrr6r4r[rrYrXre)rr4rg)rHrwrxr s z And.__init__c Cs|jdj|||dd\}}d}x|jddD]}t|tjrFd}q0|ry|j|||\}}Wqtk rvYqtk r}zd|_tj|WYdd}~Xqt k rt|t ||j |YqXn|j|||\}}|s|j r0||7}q0W||fS)NrF)rprrT) r4rtrzrrr#r __traceback__rrrrar) rr-rro resultlistZ errorStoprZ exprtokensrrwrwrxr s(   z And.parseImplcCst|trtj|}|j|S)N)rzrr$rQr)rrrwrwrxr5 s  z And.__iadd__cCs8|dd|g}x |jD]}|j||jsPqWdS)N)r4rr[)rrsubRecCheckListrrwrwrxr: s   zAnd.checkRecursioncCs@t|dr|jS|jdkr:ddjdd|jDd|_|jS)Nr{rcss|]}t|VqdS)N)r)rrrwrwrxrF szAnd.__str__..})rrrUrr4)rrwrwrxrA s    z And.__str__)T)T) rrrrr rrrrrrrrwrw)rHrxr s csDeZdZdZdfdd ZdddZdd Zd d Zd d ZZ S)ra Requires that at least one C{ParseExpression} is found. If two expressions match, the expression that matches the longest string will be used. May be constructed using the C{'^'} operator. Example:: # construct Or using '^' operator number = Word(nums) ^ Combine(Word(nums) + '.' + Word(nums)) print(number.searchString("123 3.1416 789")) prints:: [['123'], ['3.1416'], ['789']] Fcs:tt|j|||jr0tdd|jD|_nd|_dS)Ncss|] }|jVqdS)N)r[)rrrwrwrxr\ szOr.__init__..T)rrrr4rr[)rr4rg)rHrwrxrY sz Or.__init__Tc CsTd}d}g}x|jD]}y|j||}Wnvtk rd} z d| _| j|krT| }| j}WYdd} ~ Xqtk rt||krt|t||j|}t|}YqX|j||fqW|r*|j dddx`|D]X\} }y|j |||Stk r$} z"d| _| j|kr| }| j}WYdd} ~ XqXqW|dk rB|j|_ |nt||d|dS)NrrcSs |d S)Nrrw)xrwrwrxryu szOr.parseImpl..)rz no defined alternatives to matchrs) r4rrr9rrrrarsortrtr) rr-rro maxExcLoc maxExceptionrrZloc2r_rwrwrxr` s<     z Or.parseImplcCst|trtj|}|j|S)N)rzrr$rQr)rrrwrwrx__ixor__ s  z Or.__ixor__cCs@t|dr|jS|jdkr:ddjdd|jDd|_|jS)Nrr<z ^ css|]}t|VqdS)N)r)rrrwrwrxr szOr.__str__..r=)rrrUrr4)rrwrwrxr s    z Or.__str__cCs0|dd|g}x|jD]}|j|qWdS)N)r4r)rrr;rrwrwrxr s zOr.checkRecursion)F)T) rrrrrrrCrrrrwrw)rHrxrK s   & csDeZdZdZdfdd ZdddZdd Zd d Zd d ZZ S)ra Requires that at least one C{ParseExpression} is found. If two expressions match, the first one listed is the one that will match. May be constructed using the C{'|'} operator. Example:: # construct MatchFirst using '|' operator # watch the order of expressions to match number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] # put more selective expression first number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] Fcs:tt|j|||jr0tdd|jD|_nd|_dS)Ncss|] }|jVqdS)N)r[)rrrwrwrxr sz&MatchFirst.__init__..T)rrrr4rr[)rr4rg)rHrwrxr szMatchFirst.__init__Tc Csd}d}x|jD]}y|j|||}|Stk r\}z|j|krL|}|j}WYdd}~Xqtk rt||krt|t||j|}t|}YqXqW|dk r|j|_|nt||d|dS)Nrrz no defined alternatives to matchrs)r4rtrrrrrar) rr-rror@rArrrrwrwrxr s$   zMatchFirst.parseImplcCst|trtj|}|j|S)N)rzrr$rQr)rrrwrwrx__ior__ s  zMatchFirst.__ior__cCs@t|dr|jS|jdkr:ddjdd|jDd|_|jS)Nrr<z | css|]}t|VqdS)N)r)rrrwrwrxr sz%MatchFirst.__str__..r=)rrrUrr4)rrwrwrxr s    zMatchFirst.__str__cCs0|dd|g}x|jD]}|j|qWdS)N)r4r)rrr;rrwrwrxr s zMatchFirst.checkRecursion)F)T) rrrrrrrDrrrrwrw)rHrxr s   cs<eZdZdZd fdd Zd ddZddZd d ZZS) r am Requires all given C{ParseExpression}s to be found, but in any order. Expressions may be separated by whitespace. May be constructed using the C{'&'} operator. Example:: color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") integer = Word(nums) shape_attr = "shape:" + shape_type("shape") posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") color_attr = "color:" + color("color") size_attr = "size:" + integer("size") # use Each (using operator '&') to accept attributes in any order # (shape and posn are required, color and size are optional) shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) shape_spec.runTests(''' shape: SQUARE color: BLACK posn: 100, 120 shape: CIRCLE size: 50 color: BLUE posn: 50,80 color:GREEN size:20 shape:TRIANGLE posn:20,40 ''' ) prints:: shape: SQUARE color: BLACK posn: 100, 120 ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] - color: BLACK - posn: ['100', ',', '120'] - x: 100 - y: 120 - shape: SQUARE shape: CIRCLE size: 50 color: BLUE posn: 50,80 ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] - color: BLUE - posn: ['50', ',', '80'] - x: 50 - y: 80 - shape: CIRCLE - size: 50 color: GREEN size: 20 shape: TRIANGLE posn: 20,40 ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] - color: GREEN - posn: ['20', ',', '40'] - x: 20 - y: 40 - shape: TRIANGLE - size: 20 Tcs8tt|j||tdd|jD|_d|_d|_dS)Ncss|] }|jVqdS)N)r[)rrrwrwrxrsz Each.__init__..T)rr rr6r4r[rXinitExprGroups)rr4rg)rHrwrxrsz Each.__init__c s|jrtdd|jD|_dd|jD}dd|jD}|||_dd|jD|_dd|jD|_dd|jD|_|j|j7_d |_|}|jdd}|jddg}d } x| rp||j|j} g} x~| D]v} y| j||}Wn t k r| j | YqX|j |jj t | | | |krD|j | q| krj | qWt| t| krd } qW|rd jd d|D} t ||d | |fdd|jD7}g}x*|D]"} | j|||\}}|j |qWt|tg}||fS)Ncss&|]}t|trt|j|fVqdS)N)rzrrr.)rrrwrwrxrsz!Each.parseImpl..cSsg|]}t|tr|jqSrw)rzrr.)rrrwrwrxrsz"Each.parseImpl..cSs"g|]}|jrt|t r|qSrw)r[rzr)rrrwrwrxrscSsg|]}t|tr|jqSrw)rzr2r.)rrrwrwrxr scSsg|]}t|tr|jqSrw)rzrr.)rrrwrwrxr!scSs g|]}t|tttfs|qSrw)rzrr2r)rrrwrwrxr"sFTz, css|]}t|VqdS)N)r)rrrwrwrxr=sz*Missing one or more required elements (%s)cs$g|]}t|tr|jkr|qSrw)rzrr.)rr)tmpOptrwrxrAs)rErr4Zopt1mapZ optionalsZmultioptionalsZ multirequiredZrequiredrrrrrremoverrrtsumr")rr-rroZopt1Zopt2ZtmpLocZtmpReqdZ matchOrderZ keepMatchingZtmpExprsZfailedrZmissingr:rZ finalResultsrw)rFrxrsP     zEach.parseImplcCs@t|dr|jS|jdkr:ddjdd|jDd|_|jS)Nrr<z & css|]}t|VqdS)N)r)rrrwrwrxrPszEach.__str__..r=)rrrUrr4)rrwrwrxrKs    z Each.__str__cCs0|dd|g}x|jD]}|j|qWdS)N)r4r)rrr;rrwrwrxrTs zEach.checkRecursion)T)T) rrrrrrrrrrwrw)rHrxr s 5 1 csleZdZdZdfdd ZdddZdd Zfd d Zfd d ZddZ gfddZ fddZ Z S)rza Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. Fcstt|j|t|tr@ttjtr2tj|}ntjt |}||_ d|_ |dk r|j |_ |j |_ |j|j|j|_|j|_|j|_|jj|jdS)N)rrrrzr issubclassr$rQr,rr.rUr`r[rrYrXrWrer]r)rr.rg)rHrwrxr^s    zParseElementEnhance.__init__TcCs2|jdk r|jj|||ddStd||j|dS)NF)rpr)r.rtrra)rr-rrorwrwrxrps zParseElementEnhance.parseImplcCs*d|_|jj|_|jdk r&|jj|S)NF)rXr.rr)rrwrwrxrvs    z#ParseElementEnhance.leaveWhitespacecsrt|trB||jkrntt|j||jdk rn|jj|jdn,tt|j||jdk rn|jj|jd|S)Nrrrsrs)rzr+r]rrrr.)rr)rHrwrxr}s    zParseElementEnhance.ignorecs&tt|j|jdk r"|jj|S)N)rrrr.)r)rHrwrxrs  zParseElementEnhance.streamlinecCsB||krt||g|dd|g}|jdk r>|jj|dS)N)r&r.r)rrr;rwrwrxrs  z"ParseElementEnhance.checkRecursioncCs6|dd|g}|jdk r(|jj||jgdS)N)r.rr)rrr7rwrwrxrs  zParseElementEnhance.validatec sVytt|jStk r"YnX|jdkrP|jdk rPd|jjt|jf|_|jS)Nz%s:(%s)) rrrrKrUr.rHrr)r)rHrwrxrszParseElementEnhance.__str__)F)T) rrrrrrrrrrrrrrwrw)rHrxrZs   cs*eZdZdZfddZdddZZS)ra Lookahead matching of the given parse expression. C{FollowedBy} does I{not} advance the parsing position within the input string, it only verifies that the specified parse expression matches at the current position. C{FollowedBy} always returns a null token list. Example:: # use FollowedBy to match a label only if it is followed by a ':' data_word = Word(alphas) label = data_word + FollowedBy(':') attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() prints:: [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] cstt|j|d|_dS)NT)rrrr[)rr.)rHrwrxrszFollowedBy.__init__TcCs|jj|||gfS)N)r.r)rr-rrorwrwrxrszFollowedBy.parseImpl)T)rrrrrrrrwrw)rHrxrs cs2eZdZdZfddZd ddZddZZS) ra Lookahead to disallow matching with the given parse expression. C{NotAny} does I{not} advance the parsing position within the input string, it only verifies that the specified parse expression does I{not} match at the current position. Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny} always returns a null token list. May be constructed using the '~' operator. Example:: cs0tt|j|d|_d|_dt|j|_dS)NFTzFound unwanted token, )rrrrXr[rr.ra)rr.)rHrwrxrszNotAny.__init__TcCs&|jj||rt|||j||gfS)N)r.rrra)rr-rrorwrwrxrszNotAny.parseImplcCs4t|dr|jS|jdkr.dt|jd|_|jS)Nrz~{r=)rrrUrr.)rrwrwrxrs   zNotAny.__str__)T)rrrrrrrrrwrw)rHrxrs   cs(eZdZdfdd ZdddZZS) _MultipleMatchNcsFtt|j|d|_|}t|tr.tj|}|dk r<|nd|_dS)NT) rrJrrWrzrr$rQ not_ender)rr.stopOnZender)rHrwrxrs   z_MultipleMatch.__init__Tc Cs|jj}|j}|jdk }|r$|jj}|r2|||||||dd\}}yZ|j } xJ|rb|||| rr|||} n|} ||| |\}} | s| jrT|| 7}qTWWnttfk rYnX||fS)NF)rp) r.rtrrKrr]rrr) rr-rroZself_expr_parseZself_skip_ignorablesZ check_enderZ try_not_enderrZhasIgnoreExprsrZ tmptokensrwrwrxrs,      z_MultipleMatch.parseImpl)N)T)rrrrrrrwrw)rHrxrJsrJc@seZdZdZddZdS)ra Repetition of one or more of the given expression. Parameters: - expr - expression that must match one or more times - stopOn - (default=C{None}) - expression for a terminating sentinel (only required if the sentinel would ordinarily match the repetition expression) Example:: data_word = Word(alphas) label = data_word + FollowedBy(':') attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) text = "shape: SQUARE posn: upper left color: BLACK" OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] # use stopOn attribute for OneOrMore to avoid reading label string as part of the data attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] # could also be written as (attr_expr * (1,)).parseString(text).pprint() cCs4t|dr|jS|jdkr.dt|jd|_|jS)Nrr<z}...)rrrUrr.)rrwrwrxr!s   zOneOrMore.__str__N)rrrrrrwrwrwrxrscs8eZdZdZd fdd Zd fdd Zdd ZZS) r2aw Optional repetition of zero or more of the given expression. Parameters: - expr - expression that must match zero or more times - stopOn - (default=C{None}) - expression for a terminating sentinel (only required if the sentinel would ordinarily match the repetition expression) Example: similar to L{OneOrMore} Ncstt|j||dd|_dS)N)rLT)rr2rr[)rr.rL)rHrwrxr6szZeroOrMore.__init__Tc s6ytt|j|||Sttfk r0|gfSXdS)N)rr2rrr)rr-rro)rHrwrxr:szZeroOrMore.parseImplcCs4t|dr|jS|jdkr.dt|jd|_|jS)Nrrz]...)rrrUrr.)rrwrwrxr@s   zZeroOrMore.__str__)N)T)rrrrrrrrrwrw)rHrxr2*s c@s eZdZddZeZddZdS) _NullTokencCsdS)NFrw)rrwrwrxrJsz_NullToken.__bool__cCsdS)Nrrw)rrwrwrxrMsz_NullToken.__str__N)rrrrr'rrwrwrwrxrMIsrMcs6eZdZdZeffdd Zd ddZddZZS) raa Optional matching of the given expression. Parameters: - expr - expression that must match zero or more times - default (optional) - value to be returned if the optional expression is not found. Example:: # US postal code can be a 5-digit zip, plus optional 4-digit qualifier zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) zip.runTests(''' # traditional ZIP code 12345 # ZIP+4 form 12101-0001 # invalid ZIP 98765- ''') prints:: # traditional ZIP code 12345 ['12345'] # ZIP+4 form 12101-0001 ['12101-0001'] # invalid ZIP 98765- ^ FAIL: Expected end of text (at char 5), (line:1, col:6) cs.tt|j|dd|jj|_||_d|_dS)NF)rgT)rrrr.rWrr[)rr.r)rHrwrxrts zOptional.__init__Tc Cszy|jj|||dd\}}WnTttfk rp|jtk rh|jjr^t|jg}|j||jj<ql|jg}ng}YnX||fS)NF)rp)r.rtrrr_optionalNotMatchedrVr")rr-rrorrwrwrxrzs    zOptional.parseImplcCs4t|dr|jS|jdkr.dt|jd|_|jS)Nrrr )rrrUrr.)rrwrwrxrs   zOptional.__str__)T) rrrrrNrrrrrwrw)rHrxrQs" cs,eZdZdZd fdd Zd ddZZS) r(a Token for skipping over all undefined text until the matched expression is found. Parameters: - expr - target expression marking the end of the data to be skipped - include - (default=C{False}) if True, the target expression is also parsed (the skipped text and target expression are returned as a 2-element list). - ignore - (default=C{None}) used to define grammars (typically quoted strings and comments) that might contain false matches to the target expression - failOn - (default=C{None}) define expressions that are not allowed to be included in the skipped test; if found before the target expression is found, the SkipTo is not a match Example:: report = ''' Outstanding Issues Report - 1 Jan 2000 # | Severity | Description | Days Open -----+----------+-------------------------------------------+----------- 101 | Critical | Intermittent system crash | 6 94 | Cosmetic | Spelling error on Login ('log|n') | 14 79 | Minor | System slow when running too many reports | 47 ''' integer = Word(nums) SEP = Suppress('|') # use SkipTo to simply match everything up until the next SEP # - ignore quoted strings, so that a '|' character inside a quoted string does not match # - parse action will call token.strip() for each matched token, i.e., the description body string_data = SkipTo(SEP, ignore=quotedString) string_data.setParseAction(tokenMap(str.strip)) ticket_expr = (integer("issue_num") + SEP + string_data("sev") + SEP + string_data("desc") + SEP + integer("days_open")) for tkt in ticket_expr.searchString(report): print tkt.dump() prints:: ['101', 'Critical', 'Intermittent system crash', '6'] - days_open: 6 - desc: Intermittent system crash - issue_num: 101 - sev: Critical ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] - days_open: 14 - desc: Spelling error on Login ('log|n') - issue_num: 94 - sev: Cosmetic ['79', 'Minor', 'System slow when running too many reports', '47'] - days_open: 47 - desc: System slow when running too many reports - issue_num: 79 - sev: Minor FNcs`tt|j|||_d|_d|_||_d|_t|t rFt j ||_ n||_ dt |j|_dS)NTFzNo match found for )rr(r ignoreExprr[r` includeMatchrrzrr$rQfailOnrr.ra)rrincluderrQ)rHrwrxrs zSkipTo.__init__Tc Cs,|}t|}|j}|jj}|jdk r,|jjnd}|jdk rB|jjnd} |} x| |kr|dk rh||| rhP| dk rx*y| || } Wqrtk rPYqrXqrWy||| dddWn tt fk r| d7} YqLXPqLWt|||j || }|||} t | } |j r$||||dd\}} | | 7} || fS)NF)rorprr)rp) rr.rtrQrrOrrrrrar"rP)rr-rror0rr.Z expr_parseZself_failOn_canParseNextZself_ignoreExpr_tryParseZtmplocZskiptextZ skipresultrrwrwrxrs<    zSkipTo.parseImpl)FNN)T)rrrrrrrrwrw)rHrxr(s6 csbeZdZdZdfdd ZddZddZd d Zd d Zgfd dZ ddZ fddZ Z S)raK Forward declaration of an expression to be defined later - used for recursive grammars, such as algebraic infix notation. When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator. Note: take care when assigning to C{Forward} not to overlook precedence of operators. Specifically, '|' has a lower precedence than '<<', so that:: fwdExpr << a | b | c will actually be evaluated as:: (fwdExpr << a) | b | c thereby leaving b and c out as parseable alternatives. It is recommended that you explicitly group the values inserted into the C{Forward}:: fwdExpr << (a | b | c) Converting to use the '<<=' operator instead will avoid this problem. See L{ParseResults.pprint} for an example of a recursive parser created using C{Forward}. Ncstt|j|dddS)NF)rg)rrr)rr)rHrwrxrszForward.__init__cCsjt|trtj|}||_d|_|jj|_|jj|_|j|jj |jj |_ |jj |_ |j j |jj |S)N)rzrr$rQr.rUr`r[rrYrXrWr]r)rrrwrwrx __lshift__s      zForward.__lshift__cCs||>S)Nrw)rrrwrwrx __ilshift__'szForward.__ilshift__cCs d|_|S)NF)rX)rrwrwrxr*szForward.leaveWhitespacecCs$|js d|_|jdk r |jj|S)NT)r_r.r)rrwrwrxr.s   zForward.streamlinecCs>||kr0|dd|g}|jdk r0|jj||jgdS)N)r.rr)rrr7rwrwrxr5s   zForward.validatec Cs>t|dr|jS|jjdSd}Wd|j|_X|jjd|S)Nrz: ...Nonez: )rrrHrZ _revertClass_ForwardNoRecurser.r)rZ retStringrwrwrxr<s   zForward.__str__cs.|jdk rtt|jSt}||K}|SdS)N)r.rrr)rr)rHrwrxrMs  z Forward.copy)N) rrrrrrSrTrrrrrrrwrw)rHrxrs  c@seZdZddZdS)rVcCsdS)Nz...rw)rrwrwrxrVsz_ForwardNoRecurse.__str__N)rrrrrwrwrwrxrVUsrVcs"eZdZdZdfdd ZZS)r-zQ Abstract subclass of C{ParseExpression}, for converting parsed results. Fcstt|j|d|_dS)NF)rr-rrW)rr.rg)rHrwrxr]szTokenConverter.__init__)F)rrrrrrrwrw)rHrxr-Yscs6eZdZdZd fdd ZfddZdd ZZS) r a Converter to concatenate all matching tokens to a single string. By default, the matching patterns must also be contiguous in the input string; this can be disabled by specifying C{'adjacent=False'} in the constructor. Example:: real = Word(nums) + '.' + Word(nums) print(real.parseString('3.1416')) # -> ['3', '.', '1416'] # will also erroneously match the following print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] real = Combine(Word(nums) + '.' + Word(nums)) print(real.parseString('3.1416')) # -> ['3.1416'] # no match when there are internal spaces print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) rTcs8tt|j||r|j||_d|_||_d|_dS)NT)rr rradjacentrX joinStringre)rr.rXrW)rHrwrxrrszCombine.__init__cs(|jrtj||ntt|j||S)N)rWr$rrr )rr)rHrwrxr|szCombine.ignorecCsP|j}|dd=|tdj|j|jg|jd7}|jrH|jrH|gS|SdS)Nr)r)rr"rr rXrbrVr)rr-rrZretToksrwrwrxrs  "zCombine.postParse)rT)rrrrrrrrrwrw)rHrxr as cs(eZdZdZfddZddZZS)ra Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions. Example:: ident = Word(alphas) num = Word(nums) term = ident | num func = ident + Optional(delimitedList(term)) print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] func = ident + Group(Optional(delimitedList(term))) print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] cstt|j|d|_dS)NT)rrrrW)rr.)rHrwrxrszGroup.__init__cCs|gS)Nrw)rr-rrrwrwrxrszGroup.postParse)rrrrrrrrwrw)rHrxrs  cs(eZdZdZfddZddZZS)r aW Converter to return a repetitive expression as a list, but also as a dictionary. Each element can also be referenced using the first token in the expression as its key. Useful for tabular report scraping when the first column can be used as a item key. Example:: data_word = Word(alphas) label = data_word + FollowedBy(':') attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) text = "shape: SQUARE posn: upper left color: light blue texture: burlap" attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) # print attributes as plain groups print(OneOrMore(attr_expr).parseString(text).dump()) # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names result = Dict(OneOrMore(Group(attr_expr))).parseString(text) print(result.dump()) # access named fields as dict entries, or output as dict print(result['shape']) print(result.asDict()) prints:: ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - color: light blue - posn: upper left - shape: SQUARE - texture: burlap SQUARE {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} See more examples at L{ParseResults} of accessing fields by results name. cstt|j|d|_dS)NT)rr rrW)rr.)rHrwrxrsz Dict.__init__cCsxt|D]\}}t|dkr q |d}t|trBt|dj}t|dkr^td|||<q t|dkrt|dt rt|d|||<q |j}|d=t|dkst|tr|j rt||||<q t|d|||<q W|j r|gS|SdS)Nrrrrrq) rrrzrurrrr"rrrV)rr-rrrtokZikeyZ dictvaluerwrwrxrs$   zDict.postParse)rrrrrrrrwrw)rHrxr s# c@s eZdZdZddZddZdS)r+aV Converter for ignoring the results of a parsed expression. Example:: source = "a, b, c,d" wd = Word(alphas) wd_list1 = wd + ZeroOrMore(',' + wd) print(wd_list1.parseString(source)) # often, delimiters that are useful during parsing are just in the # way afterward - use Suppress to keep them out of the parsed output wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) print(wd_list2.parseString(source)) prints:: ['a', ',', 'b', ',', 'c', ',', 'd'] ['a', 'b', 'c', 'd'] (See also L{delimitedList}.) cCsgS)Nrw)rr-rrrwrwrxrszSuppress.postParsecCs|S)Nrw)rrwrwrxrszSuppress.suppressN)rrrrrrrwrwrwrxr+sc@s(eZdZdZddZddZddZdS) rzI Wrapper for parse actions, to ensure they are only called once. cCst||_d|_dS)NF)rMcallablecalled)rZ methodCallrwrwrxrs zOnlyOnce.__init__cCs.|js|j|||}d|_|St||ddS)NTr)r[rZr)rrr5rvrrwrwrxrs zOnlyOnce.__call__cCs d|_dS)NF)r[)rrwrwrxreset szOnlyOnce.resetN)rrrrrrr\rwrwrwrxrsc s:tfdd}y j|_Wntk r4YnX|S)as Decorator for debugging parse actions. When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".} When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised. Example:: wd = Word(alphas) @traceParseAction def remove_duplicate_chars(tokens): return ''.join(sorted(set(''.join(tokens))) wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) print(wds.parseString("slkdjs sld sldd sdlf sdljf")) prints:: >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) <>entering %s(line: '%s', %d, %r) z<.z)rMrr)rr`rw)rrxrb s  ,FcCs`t|dt|dt|d}|rBt|t||j|S|tt||j|SdS)a Helper to define a delimited list of expressions - the delimiter defaults to ','. By default, the list elements and delimiters can have intervening whitespace, and comments, but this can be overridden by passing C{combine=True} in the constructor. If C{combine} is set to C{True}, the matching tokens are returned as a single token string, with the delimiters included; otherwise, the matching tokens are returned as a list of tokens, with the delimiters suppressed. Example:: delimitedList(Word(alphas)).parseString("aa,bb,cc") # -> ['aa', 'bb', 'cc'] delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] z [rz]...N)rr r2rir+)r.ZdelimcombineZdlNamerwrwrxr@9s $csjtfdd}|dkr0ttjdd}n|j}|jd|j|dd|jd td S) a: Helper to define a counted list of expressions. This helper defines a pattern of the form:: integer expr expr expr... where the leading integer tells how many expr expressions follow. The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed. If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value. Example:: countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] # in this parser, the leading integer value is given in binary, # '10' indicating that 2 values are in the array binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] cs.|d}|r ttg|p&tt>gS)Nr)rrrC)rr5rvr) arrayExprr.rwrxcountFieldParseAction_s"z+countedArray..countFieldParseActionNcSs t|dS)Nr)ru)rvrwrwrxrydszcountedArray..ZarrayLenT)rfz(len) z...)rr/rRrrrirxr)r.ZintExprrdrw)rcr.rxr<Ls cCs:g}x0|D](}t|tr(|jt|q |j|q W|S)N)rzrrrr)Lrrrwrwrxrks   rcs6tfdd}|j|ddjdt|S)a* Helper to define an expression that is indirectly defined from the tokens matched in a previous expression, that is, it looks for a 'repeat' of a previous expression. For example:: first = Word(nums) second = matchPreviousLiteral(first) matchExpr = first + ":" + second will match C{"1:1"}, but not C{"1:2"}. Because this matches a previous literal, will also match the leading C{"1:1"} in C{"1:10"}. If this is not desired, use C{matchPreviousExpr}. Do I{not} use with packrat parsing enabled. csP|rBt|dkr|d>qLt|j}tdd|D>n t>dS)Nrrrcss|]}t|VqdS)N)r)rttrwrwrxrszDmatchPreviousLiteral..copyTokenToRepeater..)rrrrr )rr5rvZtflat)reprwrxcopyTokenToRepeaters   z1matchPreviousLiteral..copyTokenToRepeaterT)rfz(prev) )rrxrir)r.rhrw)rgrxrOts  csFt|j}|Kfdd}|j|ddjdt|S)aS Helper to define an expression that is indirectly defined from the tokens matched in a previous expression, that is, it looks for a 'repeat' of a previous expression. For example:: first = Word(nums) second = matchPreviousExpr(first) matchExpr = first + ":" + second will match C{"1:1"}, but not C{"1:2"}. Because this matches by expressions, will I{not} match the leading C{"1:1"} in C{"1:10"}; the expressions are evaluated first, and then compared, so C{"1"} is compared with C{"10"}. Do I{not} use with packrat parsing enabled. cs*t|jfdd}j|dddS)Ncs$t|j}|kr tddddS)Nrr)rrr)rr5rvZ theseTokens) matchTokensrwrxmustMatchTheseTokenss zLmatchPreviousExpr..copyTokenToRepeater..mustMatchTheseTokensT)rf)rrr)rr5rvrj)rg)rirxrhs  z.matchPreviousExpr..copyTokenToRepeaterT)rfz(prev) )rrrxrir)r.Ze2rhrw)rgrxrNs cCs>xdD]}|j|t|}qW|jdd}|jdd}t|S)Nz\^-]rz\nr(z\t)r_bslashr)rrrwrwrxrs    rTc s|rdd}dd}tndd}dd}tg}t|trF|j}n&t|tjr\t|}ntj dt dd|svt Sd }x|t |d kr||}xnt ||d d D]N\}} || |r|||d =Pq||| r|||d =|j|| | }PqW|d 7}q|W| r|ryht |t d j|krZtd d jdd|Djdj|Stdjdd|Djdj|SWn&tk rtj dt ddYnXtfdd|Djdj|S)a Helper to quickly define a set of alternative Literals, and makes sure to do longest-first testing when there is a conflict, regardless of the input order, but returns a C{L{MatchFirst}} for best performance. Parameters: - strs - a string of space-delimited literals, or a collection of string literals - caseless - (default=C{False}) - treat all literals as caseless - useRegex - (default=C{True}) - as an optimization, will generate a Regex object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or if creating a C{Regex} raises an exception) Example:: comp_oper = oneOf("< = > <= >= !=") var = Word(alphas) number = Word(nums) term = var | number comparison_expr = term + comp_oper + term print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) prints:: [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] cSs|j|jkS)N)r)rbrwrwrxryszoneOf..cSs|jj|jS)N)rr)rrlrwrwrxryscSs||kS)Nrw)rrlrwrwrxryscSs |j|S)N)r)rrlrwrwrxrysz6Invalid argument to oneOf, expected string or iterablerq)rrrrNrz[%s]css|]}t|VqdS)N)r)rsymrwrwrxrszoneOf..z | |css|]}tj|VqdS)N)rdr )rrmrwrwrxrsz7Exception creating Regex for oneOf, building MatchFirstc3s|]}|VqdS)Nrw)rrm)parseElementClassrwrxrs)rrrzrrrr5rrrrrrrrrr'rirKr) ZstrsrZuseRegexZisequalZmasksZsymbolsrZcurrrrw)rorxrSsL         ((cCsttt||S)a Helper to easily and clearly define a dictionary by specifying the respective patterns for the key and value. Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens in the proper order. The key pattern can include delimiting markers or punctuation, as long as they are suppressed, thereby leaving the significant key text. The value pattern can include named results, so that the C{Dict} results can include named token fields. Example:: text = "shape: SQUARE posn: upper left color: light blue texture: burlap" attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) print(OneOrMore(attr_expr).parseString(text).dump()) attr_label = label attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) # similar to Dict, but simpler call format result = dictOf(attr_label, attr_value).parseString(text) print(result.dump()) print(result['shape']) print(result.shape) # object attribute access works too print(result.asDict()) prints:: [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - color: light blue - posn: upper left - shape: SQUARE - texture: burlap SQUARE SQUARE {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} )r r2r)rrrwrwrxrAs!cCs^tjdd}|j}d|_|d||d}|r@dd}ndd}|j||j|_|S) a Helper to return the original, untokenized text for a given expression. Useful to restore the parsed fields of an HTML start tag into the raw tag text itself, or to revert separate tokens with intervening whitespace back to the original matching input text. By default, returns astring containing the original parsed text. If the optional C{asString} argument is passed as C{False}, then the return value is a C{L{ParseResults}} containing any results names that were originally matched, and a single token containing the original matched text from the input string. So if the expression passed to C{L{originalTextFor}} contains expressions with defined results names, you must set C{asString} to C{False} if you want to preserve those results name values. Example:: src = "this is test bold text normal text " for tag in ("b","i"): opener,closer = makeHTMLTags(tag) patt = originalTextFor(opener + SkipTo(closer) + closer) print(patt.searchString(src)[0]) prints:: [' bold text '] ['text'] cSs|S)Nrw)rrrvrwrwrxry8sz!originalTextFor..F_original_start _original_endcSs||j|jS)N)rprq)rr5rvrwrwrxry=scSs&||jd|jdg|dd<dS)Nrprq)r)rr5rvrwrwrx extractText?sz$originalTextFor..extractText)r rrrer])r.ZasStringZ locMarkerZ endlocMarker matchExprrrrwrwrxrg s  cCst|jddS)zp Helper to undo pyparsing's default grouping of And expressions, even if all but one are non-empty. cSs|dS)Nrrw)rvrwrwrxryJszungroup..)r-r)r.rwrwrxrhEscCs4tjdd}t|d|d|jjdS)a Helper to decorate a returned token with its starting and ending locations in the input string. This helper adds the following results names: - locn_start = location where matched expression begins - locn_end = location where matched expression ends - value = the actual parsed results Be careful if the input text contains C{} characters, you may want to call C{L{ParserElement.parseWithTabs}} Example:: wd = Word(alphas) for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): print(match) prints:: [[0, 'ljsdf', 5]] [[8, 'lksdjjf', 15]] [[18, 'lkkjj', 23]] cSs|S)Nrw)rr5rvrwrwrxry`szlocatedExpr..Z locn_startrZlocn_end)r rrrr)r.ZlocatorrwrwrxrjLsz\[]-*.$+^?()~ )r cCs |ddS)Nrrrrw)rr5rvrwrwrxryksryz\\0?[xX][0-9a-fA-F]+cCstt|djddS)Nrz\0x)unichrrulstrip)rr5rvrwrwrxrylsz \\0[0-7]+cCstt|ddddS)Nrrr)ruru)rr5rvrwrwrxrymsz\])rr z\wr8rrZnegatebodyr c sBddy djfddtj|jDStk r<dSXdS)a Helper to easily define string ranges for use in Word construction. Borrows syntax from regexp '[]' string range definitions:: srange("[0-9]") -> "0123456789" srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" The input string must be enclosed in []'s, and the returned string is the expanded character set joined into a single string. The values enclosed in the []'s may be: - a single character - an escaped character with a leading backslash (such as C{\-} or C{\]}) - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) (C{\0x##} is also supported for backwards compatibility) - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character) - a range of any of the above, separated by a dash (C{'a-z'}, etc.) - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.) cSs<t|ts|Sdjddtt|dt|ddDS)Nrcss|]}t|VqdS)N)ru)rrrwrwrxrsz+srange....rrr)rzr"rrord)prwrwrxryszsrange..rc3s|]}|VqdS)Nrw)rpart) _expandedrwrxrszsrange..N)r_reBracketExprrrxrK)rrw)r|rxr_rs  csfdd}|S)zt Helper method for defining parse actions that require matching at a specific column in the input text. cs"t||krt||ddS)Nzmatched token not at column %d)r9r)r)Zlocnr1)rrwrx verifyColsz!matchOnlyAtCol..verifyColrw)rr~rw)rrxrMs cs fddS)a Helper method for common parse actions that simply return a literal value. Especially useful when used with C{L{transformString}()}. Example:: num = Word(nums).setParseAction(lambda toks: int(toks[0])) na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) term = na | num OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] csgS)Nrw)rr5rv)replStrrwrxryszreplaceWith..rw)rrw)rrxr\s cCs|dddS)a Helper parse action for removing quotation marks from parsed quoted strings. Example:: # by default, quotation marks are included in parsed results quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] # use removeQuotes to strip quotation marks from parsed results quotedString.setParseAction(removeQuotes) quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] rrrrsrw)rr5rvrwrwrxrZs c sNfdd}ytdtdj}Wntk rBt}YnX||_|S)aG Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional args are passed, they are forwarded to the given function as additional arguments after the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the parsed data to an integer using base 16. Example (compare the last to example in L{ParserElement.transformString}:: hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) hex_ints.runTests(''' 00 11 22 aa FF 0a 0d 1a ''') upperword = Word(alphas).setParseAction(tokenMap(str.upper)) OneOrMore(upperword).runTests(''' my kingdom for a horse ''') wd = Word(alphas).setParseAction(tokenMap(str.title)) OneOrMore(wd).setParseAction(' '.join).runTests(''' now is the winter of our discontent made glorious summer by this sun of york ''') prints:: 00 11 22 aa FF 0a 0d 1a [0, 17, 34, 170, 255, 10, 13, 26] my kingdom for a horse ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] now is the winter of our discontent made glorious summer by this sun of york ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] csfdd|DS)Ncsg|]}|fqSrwrw)rZtokn)rr6rwrxrsz(tokenMap..pa..rw)rr5rv)rr6rwrxr}sztokenMap..parrH)rJrrKr{)r6rr}rLrw)rr6rxrms cCs t|jS)N)rr)rvrwrwrxryscCs t|jS)N)rlower)rvrwrwrxryscCst|tr|}t|| d}n|j}tttd}|rtjj t }t d|dt t t|t d|tddgdjd j d d t d }nd jddtD}tjj t t|B}t d|dt t t|j ttt d|tddgdjd j dd t d }ttd|d }|jdd j|jddjjjd|}|jdd j|jddjjjd|}||_||_||fS)zRInternal helper to construct opening and closing tag expressions, given a tag name)rz_-:rtag=/F)rrCcSs |ddkS)Nrrrw)rr5rvrwrwrxrysz_makeTags..rrcss|]}|dkr|VqdS)rNrw)rrrwrwrxrsz_makeTags..cSs |ddkS)Nrrrw)rr5rvrwrwrxryszrz)rzrrrr/r4r3r>rrrZr+r r2rrrmrrVrYrBr _Lrtitlerrir)tagStrZxmlZresnameZ tagAttrNameZ tagAttrValueZopenTagZprintablesLessRAbrackZcloseTagrwrwrx _makeTagss" T\..rcCs t|dS)a  Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values. Example:: text = 'More info at the pyparsing wiki page' # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple a,a_end = makeHTMLTags("A") link_expr = a + SkipTo(a_end)("link_text") + a_end for link in link_expr.searchString(text): # attributes in the tag (like "href" shown here) are also accessible as named results print(link.link_text, '->', link.href) prints:: pyparsing -> http://pyparsing.wikispaces.com F)r)rrwrwrxrKscCs t|dS)z Helper to construct opening and closing tag expressions for XML, given a tag name. Matches tags only in the given upper/lower case. Example: similar to L{makeHTMLTags} T)r)rrwrwrxrLscs8|r|ddn|jddDfdd}|S)a< Helper to create a validating parse action to be used with start tags created with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag with a required attribute value, to avoid false matches on common tags such as C{} or C{
}. Call C{withAttribute} with a series of attribute names and values. Specify the list of filter attributes names and values as: - keyword arguments, as in C{(align="right")}, or - as an explicit dict with C{**} operator, when an attribute name is also a Python reserved word, as in C{**{"class":"Customer", "align":"right"}} - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) For attribute names with a namespace prefix, you must use the second form. Attribute names are matched insensitive to upper/lower case. If just testing for C{class} (with or without a namespace), use C{L{withClass}}. To verify that the attribute exists, but without specifying a value, pass C{withAttribute.ANY_VALUE} as the value. Example:: html = '''
Some text
1 4 0 1 0
1,3 2,3 1,1
this has no type
''' div,div_end = makeHTMLTags("div") # only match div tag having a type attribute with value "grid" div_grid = div().setParseAction(withAttribute(type="grid")) grid_expr = div_grid + SkipTo(div | div_end)("body") for grid_header in grid_expr.searchString(html): print(grid_header.body) # construct a match with any div tag having a type attribute, regardless of the value div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) div_expr = div_any_type + SkipTo(div | div_end)("body") for div_header in div_expr.searchString(html): print(div_header.body) prints:: 1 4 0 1 0 1 4 0 1 0 1,3 2,3 1,1 NcSsg|]\}}||fqSrwrw)rrrrwrwrxrQsz!withAttribute..cs^xXD]P\}}||kr&t||d||tjkr|||krt||d||||fqWdS)Nzno matching attribute z+attribute '%s' has value '%s', must be '%s')rre ANY_VALUE)rr5rZattrNameZ attrValue)attrsrwrxr}Rs zwithAttribute..pa)r)rZattrDictr}rw)rrxres 2 cCs|r d|nd}tf||iS)a Simplified version of C{L{withAttribute}} when matching on a div class - made difficult because C{class} is a reserved word in Python. Example:: html = '''
Some text
1 4 0 1 0
1,3 2,3 1,1
this <div> has no class
''' div,div_end = makeHTMLTags("div") div_grid = div().setParseAction(withClass("grid")) grid_expr = div_grid + SkipTo(div | div_end)("body") for grid_header in grid_expr.searchString(html): print(grid_header.body) div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) div_expr = div_any_type + SkipTo(div | div_end)("body") for div_header in div_expr.searchString(html): print(div_header.body) prints:: 1 4 0 1 0 1 4 0 1 0 1,3 2,3 1,1 z%s:classclass)re)Z classname namespaceZ classattrrwrwrxrk\s (rcCst}||||B}x`t|D]R\}}|d dd\}} } } | dkrTd|nd|} | dkr|dksxt|dkrtd|\} }tj| }| tjkrd| dkrt||t|t |}n| dkr|dk rt|||t|t ||}nt||t|t |}nD| dkrZt|| |||t|| |||}ntd n| tj krH| dkrt |t st |}t|j |t||}n| dkr|dk rt|||t|t ||}nt||t|t |}nD| dkr>t|| |||t|| |||}ntd ntd | r`|j| ||j| |BK}|}q"W||K}|S) a Helper method for constructing grammars of expressions made up of operators working in a precedence hierarchy. Operators may be unary or binary, left- or right-associative. Parse actions can also be attached to operator expressions. The generated parser will also recognize the use of parentheses to override operator precedences (see example below). Note: if you define a deep operator list, you may see performance issues when using infixNotation. See L{ParserElement.enablePackrat} for a mechanism to potentially improve your parser performance. Parameters: - baseExpr - expression representing the most basic element for the nested - opList - list of tuples, one for each operator precedence level in the expression grammar; each tuple is of the form (opExpr, numTerms, rightLeftAssoc, parseAction), where: - opExpr is the pyparsing expression for the operator; may also be a string, which will be converted to a Literal; if numTerms is 3, opExpr is a tuple of two expressions, for the two operators separating the 3 terms - numTerms is the number of terms for this operator (must be 1, 2, or 3) - rightLeftAssoc is the indicator whether the operator is right or left associative, using the pyparsing-defined constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. - parseAction is the parse action to be associated with expressions matching this operator expression (the parse action tuple member may be omitted) - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) Example:: # simple example of four-function arithmetic with ints and variable names integer = pyparsing_common.signed_integer varname = pyparsing_common.identifier arith_expr = infixNotation(integer | varname, [ ('-', 1, opAssoc.RIGHT), (oneOf('* /'), 2, opAssoc.LEFT), (oneOf('+ -'), 2, opAssoc.LEFT), ]) arith_expr.runTests(''' 5+3*6 (5+3)*6 -2--11 ''', fullDump=False) prints:: 5+3*6 [[5, '+', [3, '*', 6]]] (5+3)*6 [[[5, '+', 3], '*', 6]] -2--11 [[['-', 2], '-', ['-', 11]]] Nrroz%s termz %s%s termrqz@if numterms=3, opExpr must be a tuple or list of two expressionsrrz6operator must be unary (1), binary (2), or ternary (3)z2operator must indicate right or left associativity)N)rrrrrirTLEFTrrrRIGHTrzrr.r)ZbaseExprZopListZlparZrparrZlastExprrZoperDefZopExprZarityZrightLeftAssocr}ZtermNameZopExpr1ZopExpr2ZthisExprrsrwrwrxrisR;    &       &   z4"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*"z string enclosed in double quotesz4'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*'z string enclosed in single quotesz*quotedString using single or double quotesuzunicode string literalcCs||krtd|dkr(t|to,t|tr t|dkrt|dkr|dk rtt|t||tjddj dd}n$t j t||tjj dd}nx|dk rtt|t |t |ttjddj dd}n4ttt |t |ttjddj d d}ntd t }|dk rb|tt|t||B|Bt|K}n$|tt|t||Bt|K}|jd ||f|S) a~ Helper method for defining nested lists enclosed in opening and closing delimiters ("(" and ")" are the default). Parameters: - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression - content - expression for items within the nested lists (default=C{None}) - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) If an expression is not provided for the content argument, the nested expression will capture all whitespace-delimited content between delimiters as a list of separate values. Use the C{ignoreExpr} argument to define expressions that may contain opening or closing characters that should not be treated as opening or closing characters for nesting, such as quotedString or a comment expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. The default is L{quotedString}, but if no expressions are to be ignored, then pass C{None} for this argument. Example:: data_type = oneOf("void int short long char float double") decl_data_type = Combine(data_type + Optional(Word('*'))) ident = Word(alphas+'_', alphanums+'_') number = pyparsing_common.number arg = Group(decl_data_type + ident) LPAR,RPAR = map(Suppress, "()") code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) c_function = (decl_data_type("type") + ident("name") + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + code_body("body")) c_function.ignore(cStyleComment) source_code = ''' int is_odd(int x) { return (x%2); } int dec_to_hex(char hchar) { if (hchar >= '0' && hchar <= '9') { return (ord(hchar)-ord('0')); } else { return (10+ord(hchar)-ord('A')); } } ''' for func in c_function.searchString(source_code): print("%(name)s (%(type)s) args: %(args)s" % func) prints:: is_odd (int) args: [['int', 'x']] dec_to_hex (int) args: [['char', 'hchar']] z.opening and closing strings cannot be the sameNrr)r cSs |djS)Nr)r)rvrwrwrxry9sznestedExpr..cSs |djS)Nr)r)rvrwrwrxry<scSs |djS)Nr)r)rvrwrwrxryBscSs |djS)Nr)r)rvrwrwrxryFszOopening and closing arguments must be strings if no content expression is givenznested %s%s expression)rrzrrr rr r$rNrrCrrrrr+r2ri)openerZcloserZcontentrOrrwrwrxrPs4:     *$c sfdd}fdd}fdd}ttjdj}ttj|jd}tj|jd }tj|jd } |rtt||t|t|t|| } n$tt|t|t|t|} |j t t| jd S) a Helper method for defining space-delimited indentation blocks, such as those used to define block statements in Python source code. Parameters: - blockStatementExpr - expression defining syntax of statement that is repeated within the indented block - indentStack - list created by caller to manage indentation stack (multiple statementWithIndentedBlock expressions within a single grammar should share a common indentStack) - indent - boolean indicating whether block must be indented beyond the the current level; set to False for block of left-most statements (default=C{True}) A valid block must contain at least one C{blockStatement}. Example:: data = ''' def A(z): A1 B = 100 G = A2 A2 A3 B def BB(a,b,c): BB1 def BBA(): bba1 bba2 bba3 C D def spam(x,y): def eggs(z): pass ''' indentStack = [1] stmt = Forward() identifier = Word(alphas, alphanums) funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") func_body = indentedBlock(stmt, indentStack) funcDef = Group( funcDecl + func_body ) rvalue = Forward() funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") rvalue << (funcCall | identifier | Word(nums)) assignment = Group(identifier + "=" + rvalue) stmt << ( funcDef | assignment | identifier ) module_body = OneOrMore(stmt) parseTree = module_body.parseString(data) parseTree.pprint() prints:: [['def', 'A', ['(', 'z', ')'], ':', [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], 'B', ['def', 'BB', ['(', 'a', 'b', 'c', ')'], ':', [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], 'C', 'D', ['def', 'spam', ['(', 'x', 'y', ')'], ':', [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] csN|t|krdSt||}|dkrJ|dkr>t||dt||ddS)Nrrzillegal nestingznot a peer entryrsrs)rr9r!r)rr5rvcurCol) indentStackrwrxcheckPeerIndents     z&indentedBlock..checkPeerIndentcs2t||}|dkr"j|n t||ddS)Nrrznot a subentryrs)r9rr)rr5rvr)rrwrxcheckSubIndents   z%indentedBlock..checkSubIndentcsN|t|krdSt||}o4|dko4|dksBt||djdS)Nrrrqznot an unindentrsr:)rr9rr)rr5rvr)rrwrx checkUnindents    z$indentedBlock..checkUnindentz INDENTrZUNINDENTzindented block) rrrrr rrirrrrk) ZblockStatementExprrrrrrr!rZPEERZUNDENTZsmExprrw)rrxrfQsN   ,z#[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]z[\0xa1-\0xbf\0xd7\0xf7]z_:zany tagzgt lt amp nbsp quot aposz><& "'z &(?Prnz);zcommon HTML entitycCs tj|jS)zRHelper parser action to replace common HTML entities with their special characters)_htmlEntityMaprZentity)rvrwrwrxr[sz/\*(?:[^*]|\*(?!/))*z*/zC style commentzz HTML commentz.*z rest of linez//(?:\\\n|[^\n])*z // commentzC++ style commentz#.*zPython style comment)rz commaItem)rc@seZdZdZeeZeeZe e j dj eZ e ej dj eedZedj dj eZej edej ej dZejd d eeeed jeBj d Zejeed j dj eZedj dj eZeeBeBjZedj dj eZe ededj dZedj dZ edj dZ!e!de!dj dZ"ee!de!d>dee!de!d?j dZ#e#j$d d d!e j d"Z%e&e"e%Be#Bj d#j d#Z'ed$j d%Z(e)d@d'd(Z*e)dAd*d+Z+ed,j d-Z,ed.j d/Z-ed0j d1Z.e/je0jBZ1e)d2d3Z2e&e3e4d4e5e e6d4d5ee7d6jj d7Z8e9ee:j;e8Bd8d9j d:Zd=S)Brna Here are some common low-level expressions that may be useful in jump-starting parser development: - numeric forms (L{integers}, L{reals}, L{scientific notation}) - common L{programming identifiers} - network addresses (L{MAC}, L{IPv4}, L{IPv6}) - ISO8601 L{dates} and L{datetime} - L{UUID} - L{comma-separated list} Parse actions: - C{L{convertToInteger}} - C{L{convertToFloat}} - C{L{convertToDate}} - C{L{convertToDatetime}} - C{L{stripHTMLTags}} - C{L{upcaseTokens}} - C{L{downcaseTokens}} Example:: pyparsing_common.number.runTests(''' # any int or real number, returned as the appropriate type 100 -100 +100 3.14159 6.02e23 1e-12 ''') pyparsing_common.fnumber.runTests(''' # any int or real number, returned as float 100 -100 +100 3.14159 6.02e23 1e-12 ''') pyparsing_common.hex_integer.runTests(''' # hex numbers 100 FF ''') pyparsing_common.fraction.runTests(''' # fractions 1/2 -3/4 ''') pyparsing_common.mixed_integer.runTests(''' # mixed fractions 1 1/2 -3/4 1-3/4 ''') import uuid pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) pyparsing_common.uuid.runTests(''' # uuid 12345678-1234-5678-1234-567812345678 ''') prints:: # any int or real number, returned as the appropriate type 100 [100] -100 [-100] +100 [100] 3.14159 [3.14159] 6.02e23 [6.02e+23] 1e-12 [1e-12] # any int or real number, returned as float 100 [100.0] -100 [-100.0] +100 [100.0] 3.14159 [3.14159] 6.02e23 [6.02e+23] 1e-12 [1e-12] # hex numbers 100 [256] FF [255] # fractions 1/2 [0.5] -3/4 [-0.75] # mixed fractions 1 [1] 1/2 [0.5] -3/4 [-0.75] 1-3/4 [1.75] # uuid 12345678-1234-5678-1234-567812345678 [UUID('12345678-1234-5678-1234-567812345678')] integerz hex integerrtz[+-]?\d+zsigned integerrfractioncCs|d|dS)Nrrrrsrw)rvrwrwrxryszpyparsing_common.r8z"fraction or mixed integer-fractionz [+-]?\d+\.\d*z real numberz+[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)z$real number with scientific notationz[+-]?\d+\.?\d*([eE][+-]?\d+)?fnumberrB identifierzK(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}z IPv4 addressz[0-9a-fA-F]{1,4} hex_integerrzfull IPv6 addressrrBz::zshort IPv6 addresscCstdd|DdkS)Ncss|]}tjj|rdVqdS)rrN)rn _ipv6_partr)rrfrwrwrxrsz,pyparsing_common...rw)rH)rvrwrwrxrysz::ffff:zmixed IPv6 addressz IPv6 addressz:[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}z MAC address%Y-%m-%dcsfdd}|S)a Helper to create a parse action for converting parsed date string to Python datetime.date Params - - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) Example:: date_expr = pyparsing_common.iso8601_date.copy() date_expr.setParseAction(pyparsing_common.convertToDate()) print(date_expr.parseString("1999-12-31")) prints:: [datetime.date(1999, 12, 31)] csLytj|djStk rF}zt||t|WYdd}~XnXdS)Nr)rstrptimeZdaterrr{)rr5rvve)fmtrwrxcvt_fnsz.pyparsing_common.convertToDate..cvt_fnrw)rrrw)rrx convertToDates zpyparsing_common.convertToDate%Y-%m-%dT%H:%M:%S.%fcsfdd}|S)a Helper to create a parse action for converting parsed datetime string to Python datetime.datetime Params - - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) Example:: dt_expr = pyparsing_common.iso8601_datetime.copy() dt_expr.setParseAction(pyparsing_common.convertToDatetime()) print(dt_expr.parseString("1999-12-31T23:59:59.999")) prints:: [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] csHytj|dStk rB}zt||t|WYdd}~XnXdS)Nr)rrrrr{)rr5rvr)rrwrxrsz2pyparsing_common.convertToDatetime..cvt_fnrw)rrrw)rrxconvertToDatetimes z"pyparsing_common.convertToDatetimez7(?P\d{4})(?:-(?P\d\d)(?:-(?P\d\d))?)?z ISO8601 datez(?P\d{4})-(?P\d\d)-(?P\d\d)[T ](?P\d\d):(?P\d\d)(:(?P\d\d(\.\d*)?)?)?(?PZ|[+-]\d\d:?\d\d)?zISO8601 datetimez2[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}UUIDcCstjj|dS)a Parse action to remove HTML tags from web page HTML source Example:: # strip HTML links from normal text text = 'More info at the
pyparsing wiki page' td,td_end = makeHTMLTags("TD") table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' r)rn_html_stripperr)rr5rrwrwrx stripHTMLTagss zpyparsing_common.stripHTMLTagsra)rz rr)rzcomma separated listcCs t|jS)N)rr)rvrwrwrxryscCs t|jS)N)rr)rvrwrwrxrysN)rrB)rrB)r)r)?rrrrrmruZconvertToIntegerfloatZconvertToFloatr/rRrirrrDrr'Zsigned_integerrrxrrZ mixed_integerrHrealZsci_realrnumberrr4r3rZ ipv4_addressrZ_full_ipv6_addressZ_short_ipv6_addressr~Z_mixed_ipv6_addressr Z ipv6_addressZ mac_addressrrrZ iso8601_dateZiso8601_datetimeuuidr7r6rrrrrrVr. _commasepitemr@rYrZcomma_separated_listrdrBrwrwrwrxrnsN"" 2   8__main__Zselectfromz_$r])rbcolumnsrjZtablesZcommandaK # '*' as column list and dotted table name select * from SYS.XYZZY # caseless match on "SELECT", and casts back to "select" SELECT * from XYZZY, ABC # list of column names, and mixed case SELECT keyword Select AA,BB,CC from Sys.dual # multiple tables Select A, B, C from Sys.dual, Table2 # invalid SELECT keyword - should fail Xelect A, B, C from Sys.dual # incomplete command - should fail Select # invalid column name - should fail Select ^^^ frox Sys.dual z] 100 -100 +100 3.14159 6.02e23 1e-12 z 100 FF z6 12345678-1234-5678-1234-567812345678 )rq)raF)N)FT)T)r)T)r __version__Z__versionTime__ __author__rweakrefrrrr~rrdrrr"r<rr_threadr ImportErrorZ threadingrrZ ordereddict__all__r version_infor;rmaxsizerr{rchrrurrHrrreversedrrrr6r r rIZmaxintZxrangerZ __builtin__rZfnamerrJrrrrrrZascii_uppercaseZascii_lowercaser4rRrDr3rkrZ printablerVrKrrr!r#r&rr"MutableMappingregisterr9rJrGr/r2r4rQrMr$r,r rrrrQrrrrlr/r'r%r r.r0rrrr*r)r1r0r rrrr rrrrJrr2rMrNrr(rrVr-r rr r+rrbr@r<rrOrNrrSrArgrhrjrirCrIrHrar`rZ _escapedPuncZ_escapedHexCharZ_escapedOctCharUNICODEZ _singleCharZ _charRangermr}r_rMr\rZrmrdrBrrKrLrerrkrTrrrirUr>r^rYrcrPrfr5rWr7r6rrrrr;r[r8rErr]r?r=rFrXrrr:rnrZ selectTokenZ fromTokenZidentZ columnNameZcolumnNameListZ columnSpecZ tableNameZ tableNameListZ simpleSQLrrrrrrrwrwrwrx=s                 8      @d &A= I G3pLOD|M &#@sQ,A,    I# %     &0 ,   ? #k Zr   (  0     "__pycache__/six.cpython-36.opt-1.pyc000064400000057532147205126200013157 0ustar003 9fuI@srdZddlmZddlZddlZddlZddlZddlZdZdZ ej ddkZ ej ddkZ ej dddzkZ e refZefZefZeZeZejZnefZeefZeejfZeZeZejjd red|ZnLGd d d eZ ye!e Wn e"k r ed~ZYn XedZ[ ddZ#ddZ$GdddeZ%Gddde%Z&Gdddej'Z(Gddde%Z)GdddeZ*e*e+Z,Gddde(Z-e)ddd d!e)d"d#d$d%d"e)d&d#d#d'd&e)d(d)d$d*d(e)d+d)d,e)d-d#d$d.d-e)d/d0d0d1d/e)d2d0d0d/d2e)d3d)d$d4d3e)d5d)e rd6nd7d8e)d9d)d:e)d;de)d!d!d e)d?d?d@e)dAdAd@e)dBdBd@e)d4d)d$d4d3e)dCd#d$dDdCe)dEd#d#dFdEe&d$d)e&dGdHe&dIdJe&dKdLdMe&dNdOdNe&dPdQdRe&dSdTdUe&dVdWdXe&dYdZd[e&d\d]d^e&d_d`dae&dbdcdde&dedfdge&dhdidje&dkdkdle&dmdmdle&dndndle&dododpe&dqdre&dsdte&dudve&dwdxdwe&dydze&d{d|d}e&d~dde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&de+dde&de+dde&de+de+de&ddde&ddde&dddg>Z.ejdkrZe.e&ddg7Z.x:e.D]2Z/e0e-e/j1e/e2e/e&r`e,j3e/de/j1q`W[/e.e-_.e-e+dZ4e,j3e4dGddde(Z5e)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)d>dde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)dddgZ6xe6D]Z/e0e5e/j1e/qW[/e6e5_.e,j3e5e+dddӃGddՄde(Z7e)ddde)ddde)dddgZ8xe8D]Z/e0e7e/j1e/q$W[/e8e7_.e,j3e7e+ddd܃Gddބde(Z9e)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)dddg!Z:xe:D]Z/e0e9e/j1e/qW[/e:e9_.e,j3e9e+dddGddde(Z;e)ddde)ddde)d dde)d ddgZxe>D]Z/e0e=e/j1e/qW[/e>e=_.e,j3e=e+dddGdddej'Z?e,j3e?e+ddddZ@ddZAe rjdZBdZCdZDdZEdZFd ZGn$d!ZBd"ZCd#ZDd$ZEd%ZFd&ZGyeHZIWn"eJk rd'd(ZIYnXeIZHyeKZKWn"eJk rd)d*ZKYnXe rd+d,ZLejMZNd-d.ZOeZPn>d/d,ZLd0d1ZNd2d.ZOGd3d4d4eZPeKZKe#eLd5ejQeBZRejQeCZSejQeDZTejQeEZUejQeFZVejQeGZWe rd6d7ZXd8d9ZYd:d;ZZd<d=Z[ej\d>Z]ej\d?Z^ej\d@Z_nTdAd7ZXdBd9ZYdCd;ZZdDd=Z[ej\dEZ]ej\dFZ^ej\dGZ_e#eXdHe#eYdIe#eZdJe#e[dKe rdLdMZ`dNdOZaebZcddldZdedjedPjfZg[dejhdZiejjZkelZmddlnZnenjoZoenjpZpdQZqej d d k rdRZrdSZsn dTZrdUZsnjdVdMZ`dWdOZaecZcebZgdXdYZidZd[ZkejtejuevZmddloZoeojoZoZpd\ZqdRZrdSZse#e`d]e#ead^d_dQZwd`dTZxdadUZye reze4j{dbZ|ddcddZ}nddedfZ|e|dgej dddk re|dhn.ej dddk r8e|din djdkZ~eze4j{dldZedk rjdmdnZej dddk reZdodnZe#e}dpej dddk rejejfdqdrZnejZdsdtZdudvZdwdxZgZe+Zejdydk rge_ejrbx>eejD]0\ZZeej+dkr*ej1e+kr*eje=Pq*W[[ejje,dS(z6Utilities for writing code that runs on Python 2 and 3)absolute_importNz'Benjamin Peterson z1.10.0javac@seZdZddZdS)XcCsdS)Nrrl)selfr r /usr/lib/python3.6/six.py__len__>sz X.__len__N)__name__ __module__ __qualname__r r r r r r <sr ?cCs ||_dS)z Add documentation to a function.N)__doc__)funcdocr r r _add_docKsrcCst|tj|S)z7Import module, returning the module after the last dot.) __import__sysmodules)namer r r _import_modulePsrc@seZdZddZddZdS) _LazyDescrcCs ||_dS)N)r)r rr r r __init__Xsz_LazyDescr.__init__c CsB|j}t||j|yt|j|jWntk r<YnX|S)N)_resolvesetattrrdelattr __class__AttributeError)r objtpresultr r r __get__[sz_LazyDescr.__get__N)rrrrr%r r r r rVsrcs.eZdZdfdd ZddZddZZS) MovedModuleNcs2tt|j|tr(|dkr |}||_n||_dS)N)superr&rPY3mod)r roldnew)r r r ris zMovedModule.__init__cCs t|jS)N)rr))r r r r rrszMovedModule._resolvecCs"|j}t||}t||||S)N)rgetattrr)r attr_modulevaluer r r __getattr__us  zMovedModule.__getattr__)N)rrrrrr0 __classcell__r r )r r r&gs r&cs(eZdZfddZddZgZZS) _LazyModulecstt|j||jj|_dS)N)r'r2rr r)r r)r r r r~sz_LazyModule.__init__cCs ddg}|dd|jD7}|S)NrrcSsg|] }|jqSr )r).0r-r r r sz'_LazyModule.__dir__..)_moved_attributes)r Zattrsr r r __dir__sz_LazyModule.__dir__)rrrrr6r5r1r r )r r r2|s r2cs&eZdZdfdd ZddZZS)MovedAttributeNcsdtt|j|trH|dkr |}||_|dkr@|dkr<|}n|}||_n||_|dkrZ|}||_dS)N)r'r7rr(r)r-)r rZold_modZnew_modZold_attrZnew_attr)r r r rszMovedAttribute.__init__cCst|j}t||jS)N)rr)r,r-)r moduler r r rs zMovedAttribute._resolve)NN)rrrrrr1r r )r r r7sr7c@sVeZdZdZddZddZddZdd d Zd d Zd dZ ddZ ddZ e Z dS)_SixMetaPathImporterz A meta path importer to import six.moves and its submodules. This class implements a PEP302 finder and loader. It should be compatible with Python 2.5 and all existing versions of Python3 cCs||_i|_dS)N)r known_modules)r Zsix_module_namer r r rsz_SixMetaPathImporter.__init__cGs&x |D]}||j|jd|<qWdS)N.)r:r)r r)Z fullnamesfullnamer r r _add_modules z _SixMetaPathImporter._add_modulecCs|j|jd|S)Nr;)r:r)r r<r r r _get_modulesz _SixMetaPathImporter._get_moduleNcCs||jkr|SdS)N)r:)r r<pathr r r find_modules z _SixMetaPathImporter.find_modulec Cs0y |j|Stk r*td|YnXdS)Nz!This loader does not know module )r:KeyError ImportError)r r<r r r Z __get_modules z!_SixMetaPathImporter.__get_modulec CsRy tj|Stk rYnX|j|}t|tr>|j}n||_|tj|<|S)N)rrrA _SixMetaPathImporter__get_module isinstancer&r __loader__)r r<r)r r r load_modules     z _SixMetaPathImporter.load_modulecCst|j|dS)z Return true, if the named module is a package. We need this method to get correct spec objects with Python 3.4 (see PEP451) __path__)hasattrrC)r r<r r r is_packagesz_SixMetaPathImporter.is_packagecCs|j|dS)z;Return None Required, if is_package is implementedN)rC)r r<r r r get_codes z_SixMetaPathImporter.get_code)N) rrrrrr=r>r@rCrFrIrJ get_sourcer r r r r9s  r9c@seZdZdZgZdS) _MovedItemszLazy loading of moved objectsN)rrrrrGr r r r rLsrLZ cStringIOioStringIOfilter itertoolsbuiltinsZifilter filterfalseZ ifilterfalseinputZ __builtin__Z raw_inputinternrmapimapgetcwdosZgetcwdugetcwdbrangeZxrangeZ reload_module importlibZimpreloadreduce functoolsZ shlex_quoteZpipesZshlexZquoteUserDict collectionsUserList UserStringzipZizip zip_longestZ izip_longestZ configparserZ ConfigParsercopyregZcopy_regZdbm_gnuZgdbmzdbm.gnuZ _dummy_threadZ dummy_threadZhttp_cookiejarZ cookielibzhttp.cookiejarZ http_cookiesZCookiez http.cookiesZ html_entitiesZhtmlentitydefsz html.entitiesZ html_parserZ HTMLParserz html.parserZ http_clientZhttplibz http.clientZemail_mime_multipartzemail.MIMEMultipartzemail.mime.multipartZemail_mime_nonmultipartzemail.MIMENonMultipartzemail.mime.nonmultipartZemail_mime_textzemail.MIMETextzemail.mime.textZemail_mime_basezemail.MIMEBasezemail.mime.baseZBaseHTTPServerz http.serverZ CGIHTTPServerZSimpleHTTPServerZcPicklepickleZqueueZQueuereprlibreprZ socketserverZ SocketServer_threadZthreadZtkinterZTkinterZtkinter_dialogZDialogztkinter.dialogZtkinter_filedialogZ FileDialogztkinter.filedialogZtkinter_scrolledtextZ ScrolledTextztkinter.scrolledtextZtkinter_simpledialogZ SimpleDialogztkinter.simpledialogZ tkinter_tixZTixz tkinter.tixZ tkinter_ttkZttkz tkinter.ttkZtkinter_constantsZ Tkconstantsztkinter.constantsZ tkinter_dndZTkdndz tkinter.dndZtkinter_colorchooserZtkColorChooserztkinter.colorchooserZtkinter_commondialogZtkCommonDialogztkinter.commondialogZtkinter_tkfiledialogZ tkFileDialogZ tkinter_fontZtkFontz tkinter.fontZtkinter_messageboxZ tkMessageBoxztkinter.messageboxZtkinter_tksimpledialogZtkSimpleDialogZ urllib_parsez.moves.urllib_parsez urllib.parseZ urllib_errorz.moves.urllib_errorz urllib.errorZurllibz .moves.urllibZurllib_robotparser robotparserzurllib.robotparserZ xmlrpc_clientZ xmlrpclibz xmlrpc.clientZ xmlrpc_serverZSimpleXMLRPCServerz xmlrpc.serverZwin32winreg_winregzmoves.z.movesmovesc@seZdZdZdS)Module_six_moves_urllib_parsez7Lazy loading of moved objects in six.moves.urllib_parseN)rrrrr r r r rn@srnZ ParseResultZurlparseZ SplitResultZparse_qsZ parse_qslZ urldefragZurljoinZurlsplitZ urlunparseZ urlunsplitZ quote_plusZunquoteZ unquote_plusZ urlencodeZ splitqueryZsplittagZ splituserZ uses_fragmentZ uses_netlocZ uses_paramsZ uses_queryZ uses_relativezmoves.urllib_parsezmoves.urllib.parsec@seZdZdZdS)Module_six_moves_urllib_errorz7Lazy loading of moved objects in six.moves.urllib_errorN)rrrrr r r r rohsroZURLErrorZurllib2Z HTTPErrorZContentTooShortErrorz.moves.urllib.errorzmoves.urllib_errorzmoves.urllib.errorc@seZdZdZdS)Module_six_moves_urllib_requestz9Lazy loading of moved objects in six.moves.urllib_requestN)rrrrr r r r rp|srpZurlopenzurllib.requestZinstall_openerZ build_openerZ pathname2urlZ url2pathnameZ getproxiesZRequestZOpenerDirectorZHTTPDefaultErrorHandlerZHTTPRedirectHandlerZHTTPCookieProcessorZ ProxyHandlerZ BaseHandlerZHTTPPasswordMgrZHTTPPasswordMgrWithDefaultRealmZAbstractBasicAuthHandlerZHTTPBasicAuthHandlerZProxyBasicAuthHandlerZAbstractDigestAuthHandlerZHTTPDigestAuthHandlerZProxyDigestAuthHandlerZ HTTPHandlerZ HTTPSHandlerZ FileHandlerZ FTPHandlerZCacheFTPHandlerZUnknownHandlerZHTTPErrorProcessorZ urlretrieveZ urlcleanupZ URLopenerZFancyURLopenerZ proxy_bypassz.moves.urllib.requestzmoves.urllib_requestzmoves.urllib.requestc@seZdZdZdS) Module_six_moves_urllib_responsez:Lazy loading of moved objects in six.moves.urllib_responseN)rrrrr r r r rqsrqZaddbasezurllib.responseZ addclosehookZaddinfoZ addinfourlz.moves.urllib.responsezmoves.urllib_responsezmoves.urllib.responsec@seZdZdZdS)#Module_six_moves_urllib_robotparserz=Lazy loading of moved objects in six.moves.urllib_robotparserN)rrrrr r r r rrsrrZRobotFileParserz.moves.urllib.robotparserzmoves.urllib_robotparserzmoves.urllib.robotparserc@sNeZdZdZgZejdZejdZejdZ ejdZ ejdZ ddZ d S) Module_six_moves_urllibzICreate a six.moves.urllib namespace that resembles the Python 3 namespacezmoves.urllib_parsezmoves.urllib_errorzmoves.urllib_requestzmoves.urllib_responsezmoves.urllib_robotparsercCsdddddgS)Nparseerrorrequestresponserjr )r r r r r6szModule_six_moves_urllib.__dir__N) rrrrrG _importerr>rtrurvrwrjr6r r r r rss     rsz moves.urllibcCstt|j|dS)zAdd an item to six.moves.N)rrLr)Zmover r r add_movesrycCsXytt|WnDtk rRy tj|=Wn"tk rLtd|fYnXYnXdS)zRemove item from six.moves.zno such move, %rN)rrLr!rm__dict__rA)rr r r remove_moves r{__func____self__ __closure____code__ __defaults__ __globals__im_funcZim_selfZ func_closureZ func_codeZ func_defaultsZ func_globalscCs|jS)N)next)itr r r advance_iterator srcCstddt|jDS)Ncss|]}d|jkVqdS)__call__N)rz)r3klassr r r szcallable..)anytype__mro__)r"r r r callablesrcCs|S)Nr )unboundr r r get_unbound_functionsrcCs|S)Nr )rclsr r r create_unbound_methodsrcCs|jS)N)r)rr r r r"scCstj|||jS)N)types MethodTyper )rr"r r r create_bound_method%srcCstj|d|S)N)rr)rrr r r r(sc@seZdZddZdS)IteratorcCst|j|S)N)r__next__)r r r r r-sz Iterator.nextN)rrrrr r r r r+srz3Get the function out of a possibly unbound functioncKst|jf|S)N)iterkeys)dkwr r r iterkeys>srcKst|jf|S)N)rvalues)rrr r r itervaluesAsrcKst|jf|S)N)ritems)rrr r r iteritemsDsrcKst|jf|S)N)rZlists)rrr r r iterlistsGsrrrrcKs |jf|S)N)r)rrr r r rPscKs |jf|S)N)r)rrr r r rSscKs |jf|S)N)r)rrr r r rVscKs |jf|S)N)r)rrr r r rYsviewkeys viewvalues viewitemsz1Return an iterator over the keys of a dictionary.z3Return an iterator over the values of a dictionary.z?Return an iterator over the (key, value) pairs of a dictionary.zBReturn an iterator over the (key, [values]) pairs of a dictionary.cCs |jdS)Nzlatin-1)encode)sr r r bksrcCs|S)Nr )rr r r unsrz>BassertCountEqualZassertRaisesRegexpZassertRegexpMatchesassertRaisesRegex assertRegexcCs|S)Nr )rr r r rscCst|jdddS)Nz\\z\\\\Zunicode_escape)unicodereplace)rr r r rscCs t|dS)Nr)ord)Zbsr r r byte2intsrcCs t||S)N)r)Zbufir r r indexbytessrZassertItemsEqualz Byte literalz Text literalcOst|t||S)N)r,_assertCountEqual)r argskwargsr r r rscOst|t||S)N)r,_assertRaisesRegex)r rrr r r rscOst|t||S)N)r, _assertRegex)r rrr r r rsexeccCs*|dkr|}|j|k r"|j||dS)N) __traceback__with_traceback)r#r/tbr r r reraises   rcCsB|dkr*tjd}|j}|dkr&|j}~n |dkr6|}tddS)zExecute code in a namespace.Nrzexec _code_ in _globs_, _locs_)r _getframe f_globalsf_localsr)Z_code_Z_globs_Z_locs_framer r r exec_s rz9def reraise(tp, value, tb=None): raise tp, value, tb zrdef raise_from(value, from_value): if from_value is None: raise value raise value from from_value zCdef raise_from(value, from_value): raise value from from_value cCs|dS)Nr )r/Z from_valuer r r raise_fromsrprintc s6|jdtjdkrdSfdd}d}|jdd}|dk r`t|trNd}nt|ts`td|jd d}|dk rt|trd}nt|tstd |rtd |sx|D]}t|trd}PqW|rtd }td }nd }d }|dkr|}|dkr|}x,t|D] \} }| r||||qW||dS)z4The new-style print function for Python 2.4 and 2.5.fileNcsdt|tst|}ttrVt|trVjdk rVtdd}|dkrHd}|jj|}j|dS)Nerrorsstrict) rD basestringstrrrencodingr,rwrite)datar)fpr r rs     zprint_..writeFsepTzsep must be None or a stringendzend must be None or a stringz$invalid keyword arguments to print()  )poprstdoutrDrr TypeError enumerate) rrrZ want_unicoderrargnewlineZspacerr )rr print_sL           rcOs<|jdtj}|jdd}t|||r8|dk r8|jdS)NrflushF)getrrr_printr)rrrrr r r r s    zReraise an exception.csfdd}|S)Ncstj|}|_|S)N)r^wraps __wrapped__)f)assignedupdatedwrappedr r wrapperszwraps..wrapperr )rrrrr )rrrr rsrcs&Gfddd}tj|dfiS)z%Create a base class with a metaclass.cseZdZfddZdS)z!with_metaclass..metaclasscs ||S)Nr )rrZ this_basesr)basesmetar r __new__'sz)with_metaclass..metaclass.__new__N)rrrrr )rrr r metaclass%srZtemporary_class)rr)rrrr )rrr with_metaclass srcsfdd}|S)z6Class decorator for creating a class with a metaclass.csl|jj}|jd}|dk rDt|tr,|g}x|D]}|j|q2W|jdd|jdd|j|j|S)N __slots__rz __weakref__)rzcopyrrDrrr __bases__)rZ orig_varsslotsZ slots_var)rr r r.s      zadd_metaclass..wrapperr )rrr )rr add_metaclass,s rcCs2tr.d|jkrtd|j|j|_dd|_|S)a A decorator that defines __unicode__ and __str__ methods under Python 2. Under Python 3 it does nothing. To support Python 2 and 3 with a single code base, define a __str__ method returning text and apply this decorator to the class. __str__zY@python_2_unicode_compatible cannot be applied to %s because it doesn't define __str__().cSs|jjdS)Nzutf-8) __unicode__r)r r r r Jsz-python_2_unicode_compatible..)PY2rz ValueErrorrrr)rr r r python_2_unicode_compatible<s   r__spec__)rrlilill)N)NN)rr)rr)rr)rr)rZ __future__rr^rPoperatorrr __author__ __version__ version_inforr(ZPY34rZ string_typesintZ integer_typesrZ class_typesZ text_typebytesZ binary_typemaxsizeZMAXSIZErZlongZ ClassTyperplatform startswithobjectr len OverflowErrorrrrr& ModuleTyper2r7r9rrxrLr5r-rrrDr=rmrnZ_urllib_parse_moved_attributesroZ_urllib_error_moved_attributesrpZ _urllib_request_moved_attributesrqZ!_urllib_response_moved_attributesrrZ$_urllib_robotparser_moved_attributesrsryr{Z _meth_funcZ _meth_selfZ _func_closureZ _func_codeZ_func_defaultsZ _func_globalsrr NameErrorrrrrrr attrgetterZget_method_functionZget_method_selfZget_function_closureZget_function_codeZget_function_defaultsZget_function_globalsrrrr methodcallerrrrrrchrZunichrstructStructpackZint2byte itemgetterrgetitemrrZ iterbytesrMrNBytesIOrrrpartialrVrrrrr,rQrrrrrWRAPPER_ASSIGNMENTSWRAPPER_UPDATESrrrrrG __package__globalsrrsubmodule_search_locations meta_pathrrZimporterappendr r r r s     >                                                                                                                                                          5     __pycache__/six.cpython-36.pyc000064400000057532147205126200012220 0ustar003 9fuI@srdZddlmZddlZddlZddlZddlZddlZdZdZ ej ddkZ ej ddkZ ej dddzkZ e refZefZefZeZeZejZnefZeefZeejfZeZeZejjd red|ZnLGd d d eZ ye!e Wn e"k r ed~ZYn XedZ[ ddZ#ddZ$GdddeZ%Gddde%Z&Gdddej'Z(Gddde%Z)GdddeZ*e*e+Z,Gddde(Z-e)ddd d!e)d"d#d$d%d"e)d&d#d#d'd&e)d(d)d$d*d(e)d+d)d,e)d-d#d$d.d-e)d/d0d0d1d/e)d2d0d0d/d2e)d3d)d$d4d3e)d5d)e rd6nd7d8e)d9d)d:e)d;de)d!d!d e)d?d?d@e)dAdAd@e)dBdBd@e)d4d)d$d4d3e)dCd#d$dDdCe)dEd#d#dFdEe&d$d)e&dGdHe&dIdJe&dKdLdMe&dNdOdNe&dPdQdRe&dSdTdUe&dVdWdXe&dYdZd[e&d\d]d^e&d_d`dae&dbdcdde&dedfdge&dhdidje&dkdkdle&dmdmdle&dndndle&dododpe&dqdre&dsdte&dudve&dwdxdwe&dydze&d{d|d}e&d~dde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&de+dde&de+dde&de+de+de&ddde&ddde&dddg>Z.ejdkrZe.e&ddg7Z.x:e.D]2Z/e0e-e/j1e/e2e/e&r`e,j3e/de/j1q`W[/e.e-_.e-e+dZ4e,j3e4dGddde(Z5e)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)d>dde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)dddgZ6xe6D]Z/e0e5e/j1e/qW[/e6e5_.e,j3e5e+dddӃGddՄde(Z7e)ddde)ddde)dddgZ8xe8D]Z/e0e7e/j1e/q$W[/e8e7_.e,j3e7e+ddd܃Gddބde(Z9e)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)dddg!Z:xe:D]Z/e0e9e/j1e/qW[/e:e9_.e,j3e9e+dddGddde(Z;e)ddde)ddde)d dde)d ddgZxe>D]Z/e0e=e/j1e/qW[/e>e=_.e,j3e=e+dddGdddej'Z?e,j3e?e+ddddZ@ddZAe rjdZBdZCdZDdZEdZFd ZGn$d!ZBd"ZCd#ZDd$ZEd%ZFd&ZGyeHZIWn"eJk rd'd(ZIYnXeIZHyeKZKWn"eJk rd)d*ZKYnXe rd+d,ZLejMZNd-d.ZOeZPn>d/d,ZLd0d1ZNd2d.ZOGd3d4d4eZPeKZKe#eLd5ejQeBZRejQeCZSejQeDZTejQeEZUejQeFZVejQeGZWe rd6d7ZXd8d9ZYd:d;ZZd<d=Z[ej\d>Z]ej\d?Z^ej\d@Z_nTdAd7ZXdBd9ZYdCd;ZZdDd=Z[ej\dEZ]ej\dFZ^ej\dGZ_e#eXdHe#eYdIe#eZdJe#e[dKe rdLdMZ`dNdOZaebZcddldZdedjedPjfZg[dejhdZiejjZkelZmddlnZnenjoZoenjpZpdQZqej d d k rdRZrdSZsn dTZrdUZsnjdVdMZ`dWdOZaecZcebZgdXdYZidZd[ZkejtejuevZmddloZoeojoZoZpd\ZqdRZrdSZse#e`d]e#ead^d_dQZwd`dTZxdadUZye reze4j{dbZ|ddcddZ}nddedfZ|e|dgej dddk re|dhn.ej dddk r8e|din djdkZ~eze4j{dldZedk rjdmdnZej dddk reZdodnZe#e}dpej dddk rejejfdqdrZnejZdsdtZdudvZdwdxZgZe+Zejdydk rge_ejrbx>eejD]0\ZZeej+dkr*ej1e+kr*eje=Pq*W[[ejje,dS(z6Utilities for writing code that runs on Python 2 and 3)absolute_importNz'Benjamin Peterson z1.10.0javac@seZdZddZdS)XcCsdS)Nrrl)selfr r /usr/lib/python3.6/six.py__len__>sz X.__len__N)__name__ __module__ __qualname__r r r r r r <sr ?cCs ||_dS)z Add documentation to a function.N)__doc__)funcdocr r r _add_docKsrcCst|tj|S)z7Import module, returning the module after the last dot.) __import__sysmodules)namer r r _import_modulePsrc@seZdZddZddZdS) _LazyDescrcCs ||_dS)N)r)r rr r r __init__Xsz_LazyDescr.__init__c CsB|j}t||j|yt|j|jWntk r<YnX|S)N)_resolvesetattrrdelattr __class__AttributeError)r objtpresultr r r __get__[sz_LazyDescr.__get__N)rrrrr%r r r r rVsrcs.eZdZdfdd ZddZddZZS) MovedModuleNcs2tt|j|tr(|dkr |}||_n||_dS)N)superr&rPY3mod)r roldnew)r r r ris zMovedModule.__init__cCs t|jS)N)rr))r r r r rrszMovedModule._resolvecCs"|j}t||}t||||S)N)rgetattrr)r attr_modulevaluer r r __getattr__us  zMovedModule.__getattr__)N)rrrrrr0 __classcell__r r )r r r&gs r&cs(eZdZfddZddZgZZS) _LazyModulecstt|j||jj|_dS)N)r'r2rr r)r r)r r r r~sz_LazyModule.__init__cCs ddg}|dd|jD7}|S)NrrcSsg|] }|jqSr )r).0r-r r r sz'_LazyModule.__dir__..)_moved_attributes)r Zattrsr r r __dir__sz_LazyModule.__dir__)rrrrr6r5r1r r )r r r2|s r2cs&eZdZdfdd ZddZZS)MovedAttributeNcsdtt|j|trH|dkr |}||_|dkr@|dkr<|}n|}||_n||_|dkrZ|}||_dS)N)r'r7rr(r)r-)r rZold_modZnew_modZold_attrZnew_attr)r r r rszMovedAttribute.__init__cCst|j}t||jS)N)rr)r,r-)r moduler r r rs zMovedAttribute._resolve)NN)rrrrrr1r r )r r r7sr7c@sVeZdZdZddZddZddZdd d Zd d Zd dZ ddZ ddZ e Z dS)_SixMetaPathImporterz A meta path importer to import six.moves and its submodules. This class implements a PEP302 finder and loader. It should be compatible with Python 2.5 and all existing versions of Python3 cCs||_i|_dS)N)r known_modules)r Zsix_module_namer r r rsz_SixMetaPathImporter.__init__cGs&x |D]}||j|jd|<qWdS)N.)r:r)r r)Z fullnamesfullnamer r r _add_modules z _SixMetaPathImporter._add_modulecCs|j|jd|S)Nr;)r:r)r r<r r r _get_modulesz _SixMetaPathImporter._get_moduleNcCs||jkr|SdS)N)r:)r r<pathr r r find_modules z _SixMetaPathImporter.find_modulec Cs0y |j|Stk r*td|YnXdS)Nz!This loader does not know module )r:KeyError ImportError)r r<r r r Z __get_modules z!_SixMetaPathImporter.__get_modulec CsRy tj|Stk rYnX|j|}t|tr>|j}n||_|tj|<|S)N)rrrA _SixMetaPathImporter__get_module isinstancer&r __loader__)r r<r)r r r load_modules     z _SixMetaPathImporter.load_modulecCst|j|dS)z Return true, if the named module is a package. We need this method to get correct spec objects with Python 3.4 (see PEP451) __path__)hasattrrC)r r<r r r is_packagesz_SixMetaPathImporter.is_packagecCs|j|dS)z;Return None Required, if is_package is implementedN)rC)r r<r r r get_codes z_SixMetaPathImporter.get_code)N) rrrrrr=r>r@rCrFrIrJ get_sourcer r r r r9s  r9c@seZdZdZgZdS) _MovedItemszLazy loading of moved objectsN)rrrrrGr r r r rLsrLZ cStringIOioStringIOfilter itertoolsbuiltinsZifilter filterfalseZ ifilterfalseinputZ __builtin__Z raw_inputinternrmapimapgetcwdosZgetcwdugetcwdbrangeZxrangeZ reload_module importlibZimpreloadreduce functoolsZ shlex_quoteZpipesZshlexZquoteUserDict collectionsUserList UserStringzipZizip zip_longestZ izip_longestZ configparserZ ConfigParsercopyregZcopy_regZdbm_gnuZgdbmzdbm.gnuZ _dummy_threadZ dummy_threadZhttp_cookiejarZ cookielibzhttp.cookiejarZ http_cookiesZCookiez http.cookiesZ html_entitiesZhtmlentitydefsz html.entitiesZ html_parserZ HTMLParserz html.parserZ http_clientZhttplibz http.clientZemail_mime_multipartzemail.MIMEMultipartzemail.mime.multipartZemail_mime_nonmultipartzemail.MIMENonMultipartzemail.mime.nonmultipartZemail_mime_textzemail.MIMETextzemail.mime.textZemail_mime_basezemail.MIMEBasezemail.mime.baseZBaseHTTPServerz http.serverZ CGIHTTPServerZSimpleHTTPServerZcPicklepickleZqueueZQueuereprlibreprZ socketserverZ SocketServer_threadZthreadZtkinterZTkinterZtkinter_dialogZDialogztkinter.dialogZtkinter_filedialogZ FileDialogztkinter.filedialogZtkinter_scrolledtextZ ScrolledTextztkinter.scrolledtextZtkinter_simpledialogZ SimpleDialogztkinter.simpledialogZ tkinter_tixZTixz tkinter.tixZ tkinter_ttkZttkz tkinter.ttkZtkinter_constantsZ Tkconstantsztkinter.constantsZ tkinter_dndZTkdndz tkinter.dndZtkinter_colorchooserZtkColorChooserztkinter.colorchooserZtkinter_commondialogZtkCommonDialogztkinter.commondialogZtkinter_tkfiledialogZ tkFileDialogZ tkinter_fontZtkFontz tkinter.fontZtkinter_messageboxZ tkMessageBoxztkinter.messageboxZtkinter_tksimpledialogZtkSimpleDialogZ urllib_parsez.moves.urllib_parsez urllib.parseZ urllib_errorz.moves.urllib_errorz urllib.errorZurllibz .moves.urllibZurllib_robotparser robotparserzurllib.robotparserZ xmlrpc_clientZ xmlrpclibz xmlrpc.clientZ xmlrpc_serverZSimpleXMLRPCServerz xmlrpc.serverZwin32winreg_winregzmoves.z.movesmovesc@seZdZdZdS)Module_six_moves_urllib_parsez7Lazy loading of moved objects in six.moves.urllib_parseN)rrrrr r r r rn@srnZ ParseResultZurlparseZ SplitResultZparse_qsZ parse_qslZ urldefragZurljoinZurlsplitZ urlunparseZ urlunsplitZ quote_plusZunquoteZ unquote_plusZ urlencodeZ splitqueryZsplittagZ splituserZ uses_fragmentZ uses_netlocZ uses_paramsZ uses_queryZ uses_relativezmoves.urllib_parsezmoves.urllib.parsec@seZdZdZdS)Module_six_moves_urllib_errorz7Lazy loading of moved objects in six.moves.urllib_errorN)rrrrr r r r rohsroZURLErrorZurllib2Z HTTPErrorZContentTooShortErrorz.moves.urllib.errorzmoves.urllib_errorzmoves.urllib.errorc@seZdZdZdS)Module_six_moves_urllib_requestz9Lazy loading of moved objects in six.moves.urllib_requestN)rrrrr r r r rp|srpZurlopenzurllib.requestZinstall_openerZ build_openerZ pathname2urlZ url2pathnameZ getproxiesZRequestZOpenerDirectorZHTTPDefaultErrorHandlerZHTTPRedirectHandlerZHTTPCookieProcessorZ ProxyHandlerZ BaseHandlerZHTTPPasswordMgrZHTTPPasswordMgrWithDefaultRealmZAbstractBasicAuthHandlerZHTTPBasicAuthHandlerZProxyBasicAuthHandlerZAbstractDigestAuthHandlerZHTTPDigestAuthHandlerZProxyDigestAuthHandlerZ HTTPHandlerZ HTTPSHandlerZ FileHandlerZ FTPHandlerZCacheFTPHandlerZUnknownHandlerZHTTPErrorProcessorZ urlretrieveZ urlcleanupZ URLopenerZFancyURLopenerZ proxy_bypassz.moves.urllib.requestzmoves.urllib_requestzmoves.urllib.requestc@seZdZdZdS) Module_six_moves_urllib_responsez:Lazy loading of moved objects in six.moves.urllib_responseN)rrrrr r r r rqsrqZaddbasezurllib.responseZ addclosehookZaddinfoZ addinfourlz.moves.urllib.responsezmoves.urllib_responsezmoves.urllib.responsec@seZdZdZdS)#Module_six_moves_urllib_robotparserz=Lazy loading of moved objects in six.moves.urllib_robotparserN)rrrrr r r r rrsrrZRobotFileParserz.moves.urllib.robotparserzmoves.urllib_robotparserzmoves.urllib.robotparserc@sNeZdZdZgZejdZejdZejdZ ejdZ ejdZ ddZ d S) Module_six_moves_urllibzICreate a six.moves.urllib namespace that resembles the Python 3 namespacezmoves.urllib_parsezmoves.urllib_errorzmoves.urllib_requestzmoves.urllib_responsezmoves.urllib_robotparsercCsdddddgS)Nparseerrorrequestresponserjr )r r r r r6szModule_six_moves_urllib.__dir__N) rrrrrG _importerr>rtrurvrwrjr6r r r r rss     rsz moves.urllibcCstt|j|dS)zAdd an item to six.moves.N)rrLr)Zmover r r add_movesrycCsXytt|WnDtk rRy tj|=Wn"tk rLtd|fYnXYnXdS)zRemove item from six.moves.zno such move, %rN)rrLr!rm__dict__rA)rr r r remove_moves r{__func____self__ __closure____code__ __defaults__ __globals__im_funcZim_selfZ func_closureZ func_codeZ func_defaultsZ func_globalscCs|jS)N)next)itr r r advance_iterator srcCstddt|jDS)Ncss|]}d|jkVqdS)__call__N)rz)r3klassr r r szcallable..)anytype__mro__)r"r r r callablesrcCs|S)Nr )unboundr r r get_unbound_functionsrcCs|S)Nr )rclsr r r create_unbound_methodsrcCs|jS)N)r)rr r r r"scCstj|||jS)N)types MethodTyper )rr"r r r create_bound_method%srcCstj|d|S)N)rr)rrr r r r(sc@seZdZddZdS)IteratorcCst|j|S)N)r__next__)r r r r r-sz Iterator.nextN)rrrrr r r r r+srz3Get the function out of a possibly unbound functioncKst|jf|S)N)iterkeys)dkwr r r iterkeys>srcKst|jf|S)N)rvalues)rrr r r itervaluesAsrcKst|jf|S)N)ritems)rrr r r iteritemsDsrcKst|jf|S)N)rZlists)rrr r r iterlistsGsrrrrcKs |jf|S)N)r)rrr r r rPscKs |jf|S)N)r)rrr r r rSscKs |jf|S)N)r)rrr r r rVscKs |jf|S)N)r)rrr r r rYsviewkeys viewvalues viewitemsz1Return an iterator over the keys of a dictionary.z3Return an iterator over the values of a dictionary.z?Return an iterator over the (key, value) pairs of a dictionary.zBReturn an iterator over the (key, [values]) pairs of a dictionary.cCs |jdS)Nzlatin-1)encode)sr r r bksrcCs|S)Nr )rr r r unsrz>BassertCountEqualZassertRaisesRegexpZassertRegexpMatchesassertRaisesRegex assertRegexcCs|S)Nr )rr r r rscCst|jdddS)Nz\\z\\\\Zunicode_escape)unicodereplace)rr r r rscCs t|dS)Nr)ord)Zbsr r r byte2intsrcCs t||S)N)r)Zbufir r r indexbytessrZassertItemsEqualz Byte literalz Text literalcOst|t||S)N)r,_assertCountEqual)r argskwargsr r r rscOst|t||S)N)r,_assertRaisesRegex)r rrr r r rscOst|t||S)N)r, _assertRegex)r rrr r r rsexeccCs*|dkr|}|j|k r"|j||dS)N) __traceback__with_traceback)r#r/tbr r r reraises   rcCsB|dkr*tjd}|j}|dkr&|j}~n |dkr6|}tddS)zExecute code in a namespace.Nrzexec _code_ in _globs_, _locs_)r _getframe f_globalsf_localsr)Z_code_Z_globs_Z_locs_framer r r exec_s rz9def reraise(tp, value, tb=None): raise tp, value, tb zrdef raise_from(value, from_value): if from_value is None: raise value raise value from from_value zCdef raise_from(value, from_value): raise value from from_value cCs|dS)Nr )r/Z from_valuer r r raise_fromsrprintc s6|jdtjdkrdSfdd}d}|jdd}|dk r`t|trNd}nt|ts`td|jd d}|dk rt|trd}nt|tstd |rtd |sx|D]}t|trd}PqW|rtd }td }nd }d }|dkr|}|dkr|}x,t|D] \} }| r||||qW||dS)z4The new-style print function for Python 2.4 and 2.5.fileNcsdt|tst|}ttrVt|trVjdk rVtdd}|dkrHd}|jj|}j|dS)Nerrorsstrict) rD basestringstrrrencodingr,rwrite)datar)fpr r rs     zprint_..writeFsepTzsep must be None or a stringendzend must be None or a stringz$invalid keyword arguments to print()  )poprstdoutrDrr TypeError enumerate) rrrZ want_unicoderrargnewlineZspacerr )rr print_sL           rcOs<|jdtj}|jdd}t|||r8|dk r8|jdS)NrflushF)getrrr_printr)rrrrr r r r s    zReraise an exception.csfdd}|S)Ncstj|}|_|S)N)r^wraps __wrapped__)f)assignedupdatedwrappedr r wrapperszwraps..wrapperr )rrrrr )rrrr rsrcs&Gfddd}tj|dfiS)z%Create a base class with a metaclass.cseZdZfddZdS)z!with_metaclass..metaclasscs ||S)Nr )rrZ this_basesr)basesmetar r __new__'sz)with_metaclass..metaclass.__new__N)rrrrr )rrr r metaclass%srZtemporary_class)rr)rrrr )rrr with_metaclass srcsfdd}|S)z6Class decorator for creating a class with a metaclass.csl|jj}|jd}|dk rDt|tr,|g}x|D]}|j|q2W|jdd|jdd|j|j|S)N __slots__rz __weakref__)rzcopyrrDrrr __bases__)rZ orig_varsslotsZ slots_var)rr r r.s      zadd_metaclass..wrapperr )rrr )rr add_metaclass,s rcCs2tr.d|jkrtd|j|j|_dd|_|S)a A decorator that defines __unicode__ and __str__ methods under Python 2. Under Python 3 it does nothing. To support Python 2 and 3 with a single code base, define a __str__ method returning text and apply this decorator to the class. __str__zY@python_2_unicode_compatible cannot be applied to %s because it doesn't define __str__().cSs|jjdS)Nzutf-8) __unicode__r)r r r r Jsz-python_2_unicode_compatible..)PY2rz ValueErrorrrr)rr r r python_2_unicode_compatible<s   r__spec__)rrlilill)N)NN)rr)rr)rr)rr)rZ __future__rr^rPoperatorrr __author__ __version__ version_inforr(ZPY34rZ string_typesintZ integer_typesrZ class_typesZ text_typebytesZ binary_typemaxsizeZMAXSIZErZlongZ ClassTyperplatform startswithobjectr len OverflowErrorrrrr& ModuleTyper2r7r9rrxrLr5r-rrrDr=rmrnZ_urllib_parse_moved_attributesroZ_urllib_error_moved_attributesrpZ _urllib_request_moved_attributesrqZ!_urllib_response_moved_attributesrrZ$_urllib_robotparser_moved_attributesrsryr{Z _meth_funcZ _meth_selfZ _func_closureZ _func_codeZ_func_defaultsZ _func_globalsrr NameErrorrrrrrr attrgetterZget_method_functionZget_method_selfZget_function_closureZget_function_codeZget_function_defaultsZget_function_globalsrrrr methodcallerrrrrrchrZunichrstructStructpackZint2byte itemgetterrgetitemrrZ iterbytesrMrNBytesIOrrrpartialrVrrrrr,rQrrrrrWRAPPER_ASSIGNMENTSWRAPPER_UPDATESrrrrrG __package__globalsrrsubmodule_search_locations meta_pathrrZimporterappendr r r r s     >                                                                                                                                                          5     packaging/__pycache__/__about__.cpython-36.opt-1.pyc000064400000001177147205126200016200 0ustar003 9f@sPddlmZmZmZdddddddd gZd Zd Zd Zd ZdZ dZ dZ de Z dS))absolute_importdivisionprint_function __title__ __summary____uri__ __version__ __author__ __email__ __license__ __copyright__Z packagingz"Core utilities for Python packagesz!https://github.com/pypa/packagingz16.8z)Donald Stufft and individual contributorszdonald@stufft.ioz"BSD or Apache License, Version 2.0zCopyright 2014-2016 %sN) Z __future__rrr__all__rrrrr r r r rr/usr/lib/python3.6/__about__.pys  packaging/__pycache__/__about__.cpython-36.pyc000064400000001177147205126200015241 0ustar003 9f@sPddlmZmZmZdddddddd gZd Zd Zd Zd ZdZ dZ dZ de Z dS))absolute_importdivisionprint_function __title__ __summary____uri__ __version__ __author__ __email__ __license__ __copyright__Z packagingz"Core utilities for Python packagesz!https://github.com/pypa/packagingz16.8z)Donald Stufft and individual contributorszdonald@stufft.ioz"BSD or Apache License, Version 2.0zCopyright 2014-2016 %sN) Z __future__rrr__all__rrrrr r r r rr/usr/lib/python3.6/__about__.pys  packaging/__pycache__/__init__.cpython-36.opt-1.pyc000064400000000735147205126200016030 0ustar003 9f@sTddlmZmZmZddlmZmZmZmZm Z m Z m Z m Z dddddd d d gZ d S) )absolute_importdivisionprint_function) __author__ __copyright__ __email__ __license__ __summary__ __title____uri__ __version__r r r r rrr rN)Z __future__rrr __about__rrrr r r r r __all__rr/usr/lib/python3.6/__init__.pys( packaging/__pycache__/__init__.cpython-36.pyc000064400000000735147205126200015071 0ustar003 9f@sTddlmZmZmZddlmZmZmZmZm Z m Z m Z m Z dddddd d d gZ d S) )absolute_importdivisionprint_function) __author__ __copyright__ __email__ __license__ __summary__ __title____uri__ __version__r r r r rrr rN)Z __future__rrr __about__rrrr r r r r __all__rr/usr/lib/python3.6/__init__.pys( packaging/__pycache__/_compat.cpython-36.opt-1.pyc000064400000001634147205126200015712 0ustar003 9f\@sVddlmZmZmZddlZejddkZejddkZerDefZ ne fZ ddZ dS))absolute_importdivisionprint_functionNcs&Gfddd}tj|dfiS)z/ Create a base class with a metaclass. cseZdZfddZdS)z!with_metaclass..metaclasscs ||S)N)clsnameZ this_basesd)basesmetar/usr/lib/python3.6/_compat.py__new__sz)with_metaclass..metaclass.__new__N)__name__ __module__ __qualname__rr)r r rr metaclasssrZtemporary_class)typer)r r rr)r r r with_metaclasssr) Z __future__rrrsys version_infoZPY2ZPY3strZ string_typesZ basestringrrrrr spackaging/__pycache__/_compat.cpython-36.pyc000064400000001634147205126200014753 0ustar003 9f\@sVddlmZmZmZddlZejddkZejddkZerDefZ ne fZ ddZ dS))absolute_importdivisionprint_functionNcs&Gfddd}tj|dfiS)z/ Create a base class with a metaclass. cseZdZfddZdS)z!with_metaclass..metaclasscs ||S)N)clsnameZ this_basesd)basesmetar/usr/lib/python3.6/_compat.py__new__sz)with_metaclass..metaclass.__new__N)__name__ __module__ __qualname__rr)r r rr metaclasssrZtemporary_class)typer)r r rr)r r r with_metaclasssr) Z __future__rrrsys version_infoZPY2ZPY3strZ string_typesZ basestringrrrrr spackaging/__pycache__/_structures.cpython-36.opt-1.pyc000064400000005335147205126200016654 0ustar003 9f@sDddlmZmZmZGdddeZeZGdddeZeZdS))absolute_importdivisionprint_functionc@sTeZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ dS)InfinitycCsdS)Nr)selfrr!/usr/lib/python3.6/_structures.py__repr__ szInfinity.__repr__cCs tt|S)N)hashrepr)rrrr__hash__ szInfinity.__hash__cCsdS)NFr)rotherrrr__lt__szInfinity.__lt__cCsdS)NFr)rr rrr__le__szInfinity.__le__cCs t||jS)N) isinstance __class__)rr rrr__eq__szInfinity.__eq__cCst||j S)N)rr)rr rrr__ne__szInfinity.__ne__cCsdS)NTr)rr rrr__gt__szInfinity.__gt__cCsdS)NTr)rr rrr__ge__szInfinity.__ge__cCstS)N)NegativeInfinity)rrrr__neg__!szInfinity.__neg__N) __name__ __module__ __qualname__r r rrrrrrrrrrrrsrc@sTeZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ dS)rcCsdS)Nz -Infinityr)rrrrr )szNegativeInfinity.__repr__cCs tt|S)N)r r )rrrrr ,szNegativeInfinity.__hash__cCsdS)NTr)rr rrrr/szNegativeInfinity.__lt__cCsdS)NTr)rr rrrr2szNegativeInfinity.__le__cCs t||jS)N)rr)rr rrrr5szNegativeInfinity.__eq__cCst||j S)N)rr)rr rrrr8szNegativeInfinity.__ne__cCsdS)NFr)rr rrrr;szNegativeInfinity.__gt__cCsdS)NFr)rr rrrr>szNegativeInfinity.__ge__cCstS)N)r)rrrrrAszNegativeInfinity.__neg__N) rrrr r rrrrrrrrrrrr'srN)Z __future__rrrobjectrrrrrrspackaging/__pycache__/_structures.cpython-36.pyc000064400000005335147205126200015715 0ustar003 9f@sDddlmZmZmZGdddeZeZGdddeZeZdS))absolute_importdivisionprint_functionc@sTeZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ dS)InfinitycCsdS)Nr)selfrr!/usr/lib/python3.6/_structures.py__repr__ szInfinity.__repr__cCs tt|S)N)hashrepr)rrrr__hash__ szInfinity.__hash__cCsdS)NFr)rotherrrr__lt__szInfinity.__lt__cCsdS)NFr)rr rrr__le__szInfinity.__le__cCs t||jS)N) isinstance __class__)rr rrr__eq__szInfinity.__eq__cCst||j S)N)rr)rr rrr__ne__szInfinity.__ne__cCsdS)NTr)rr rrr__gt__szInfinity.__gt__cCsdS)NTr)rr rrr__ge__szInfinity.__ge__cCstS)N)NegativeInfinity)rrrr__neg__!szInfinity.__neg__N) __name__ __module__ __qualname__r r rrrrrrrrrrrrsrc@sTeZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ dS)rcCsdS)Nz -Infinityr)rrrrr )szNegativeInfinity.__repr__cCs tt|S)N)r r )rrrrr ,szNegativeInfinity.__hash__cCsdS)NTr)rr rrrr/szNegativeInfinity.__lt__cCsdS)NTr)rr rrrr2szNegativeInfinity.__le__cCs t||jS)N)rr)rr rrrr5szNegativeInfinity.__eq__cCst||j S)N)rr)rr rrrr8szNegativeInfinity.__ne__cCsdS)NFr)rr rrrr;szNegativeInfinity.__gt__cCsdS)NFr)rr rrrr>szNegativeInfinity.__ge__cCstS)N)r)rrrrrAszNegativeInfinity.__neg__N) rrrr r rrrrrrrrrrrr'srN)Z __future__rrrobjectrrrrrrspackaging/__pycache__/markers.cpython-36.opt-1.pyc000064400000020772147205126200015740 0ustar003 9f8 @s@ddlmZmZmZddlZddlZddlZddlZddlm Z m Z m Z m Z ddlm Z mZmZmZddlmZddlmZddlmZmZd d d d d gZGdd d eZGdd d eZGdd d eZGdddeZGdddeZGdddeZ GdddeZ!ededBedBedBedBedBedBed Bed!Bed"Bed#Bed$Bed%Bed&Bed'Bed(Bed)Bed*BZ"d#d"ddddd+Z#e"j$d,d-ed.ed/Bed0Bed1Bed2Bed3Bed4Bed5BZ%e%ed6Bed7BZ&e&j$d8d-ed9ed:BZ'e'j$d;d-ed<ed=BZ(e"e'BZ)ee)e&e)Z*e*j$d>d-ed?j+Z,ed@j+Z-eZ.e*ee,e.e-BZ/e.e/e e(e.>e e.e Z0dAdBZ1dSdDdEZ2dFd-dGd-ej3ej4ej5ej6ej7ej8dHZ9dIdJZ:eZ;dKdLZdQd Z?GdRd d eZ@dS)T)absolute_importdivisionprint_functionN)ParseException ParseResults stringStart stringEnd) ZeroOrMoreGroupForward QuotedString)Literal) string_types) SpecifierInvalidSpecifier InvalidMarkerUndefinedComparisonUndefinedEnvironmentNameMarkerdefault_environmentc@seZdZdZdS)rzE An invalid marker was found, users should refer to PEP 508. N)__name__ __module__ __qualname____doc__rr/usr/lib/python3.6/markers.pyrsc@seZdZdZdS)rzP An invalid operation was attempted on a value that doesn't support it. N)rrrrrrrrrsc@seZdZdZdS)rz\ A name was attempted to be used that does not exist inside of the environment. N)rrrrrrrrr%sc@s,eZdZddZddZddZddZd S) NodecCs ||_dS)N)value)selfrrrr__init__.sz Node.__init__cCs t|jS)N)strr)rrrr__str__1sz Node.__str__cCsdj|jjt|S)Nz <{0}({1!r})>)format __class__rr!)rrrr__repr__4sz Node.__repr__cCstdS)N)NotImplementedError)rrrr serialize7szNode.serializeN)rrrr r"r%r'rrrrr,src@seZdZddZdS)VariablecCst|S)N)r!)rrrrr'=szVariable.serializeN)rrrr'rrrrr(;sr(c@seZdZddZdS)ValuecCs dj|S)Nz"{0}")r#)rrrrr'CszValue.serializeN)rrrr'rrrrr)Asr)c@seZdZddZdS)OpcCst|S)N)r!)rrrrr'Isz Op.serializeN)rrrr'rrrrr*Gsr*implementation_versionplatform_python_implementationimplementation_namepython_full_versionplatform_releaseplatform_versionplatform_machineplatform_systempython_version sys_platformos_namezos.namez sys.platformzplatform.versionzplatform.machinezplatform.python_implementationpython_implementationZextra)zos.namez sys.platformzplatform.versionzplatform.machinezplatform.python_implementationr6cCsttj|d|dS)Nr)r(ALIASESget)sltrrrisr<z===z==z>=z<=z!=z~=>sz(_coerce_parse_result..) isinstancer)resultsrrrrGs rGTcCst|tr4t|dkr4t|dttfr4t|dSt|trndd|D}|rZdj|Sddj|dSn"t|trdjdd |DS|SdS) Nrrcss|]}t|ddVqdS)F)firstN)_format_marker)rHmrrr sz!_format_marker.. rErFcSsg|] }|jqSr)r')rHrOrrrrJsz"_format_marker..)rKlistlenrDrNjoin)markerrMinnerrrrrNs    rNcCs||kS)Nr)lhsrhsrrrr<scCs||kS)Nr)rWrXrrrr<s)r?znot inr>z<=z==z!=z>=r=c Cslytdj|j|g}Wntk r.Yn X|j|Stj|j}|dkrbtdj||||||S)Nz#Undefined {0!r} on {1!r} and {2!r}.) rrTr'rcontains _operatorsr8rr#)rWoprXspecZoperrrr_eval_ops r^cCs&|j|t}|tkr"tdj||S)Nz/{0!r} does not exist in evaluation environment.)r8 _undefinedrr#) environmentnamerrrr_get_envs   rbc Csgg}x|D]}t|tr0|djt||q t|tr|\}}}t|trbt||j}|j}n|j}t||j}|djt|||q |dkr |jgq Wt dd|DS)NrrCcss|]}t|VqdS)N)all)rHitemrrrrPsz$_evaluate_markers..re) rKrRappend_evaluate_markersrDr(rbrr^any) Zmarkersr`groupsrUrWr\rXZ lhs_valueZ rhs_valuerrrrgs       rgcCs2dj|}|j}|dkr.||dt|j7}|S)Nz{0.major}.{0.minor}.{0.micro}finalr)r# releaselevelr!serial)infoversionZkindrrrformat_full_versions  roc Cslttdr ttjj}tjj}nd}d}||tjtjtj tj tjtj tj tj ddtjd S)Nimplementation0rY) r-r+r5r1r/r2r0r.r,r3r4) hasattrsysrorprnraosplatformmachinereleasesystemr3r6)Ziverr-rrrrs    c@s.eZdZddZddZddZd dd ZdS) rcCs`yttj||_WnFtk rZ}z*dj|||j|jd}t|WYdd}~XnXdS)Nz+Invalid marker: {0!r}, parse error at {1!r})rGMARKERZ parseString_markersrr#locr)rrUeZerr_strrrrr s zMarker.__init__cCs t|jS)N)rNr|)rrrrr"szMarker.__str__cCsdjt|S)Nz)r#r!)rrrrr%szMarker.__repr__NcCs$t}|dk r|j|t|j|S)a$Evaluate a marker. Return the boolean from evaluating the given marker against the environment. environment is an optional argument to override all or part of the determined environment. The environment is determined from the current Python process. N)rupdatergr|)rr`Zcurrent_environmentrrrevaluate s  zMarker.evaluate)N)rrrr r"r%rrrrrrs)T)AZ __future__rrroperatorrurvrtZpkg_resources.extern.pyparsingrrrrr r r r r LZ_compatrZ specifiersrr__all__ ValueErrorrrrobjectrr(r)r*ZVARIABLEr7ZsetParseActionZ VERSION_CMPZ MARKER_OPZ MARKER_VALUEZBOOLOPZ MARKER_VARZ MARKER_ITEMsuppressZLPARENZRPARENZ MARKER_EXPRZ MARKER_ATOMr{rGrNltleeqnegegtr[r^r_rbrgrorrrrrrsx    6       packaging/__pycache__/markers.cpython-36.pyc000064400000021144147205126200014773 0ustar003 9f8 @s@ddlmZmZmZddlZddlZddlZddlZddlm Z m Z m Z m Z ddlm Z mZmZmZddlmZddlmZddlmZmZd d d d d gZGdd d eZGdd d eZGdd d eZGdddeZGdddeZGdddeZ GdddeZ!ededBedBedBedBedBedBed Bed!Bed"Bed#Bed$Bed%Bed&Bed'Bed(Bed)Bed*BZ"d#d"ddddd+Z#e"j$d,d-ed.ed/Bed0Bed1Bed2Bed3Bed4Bed5BZ%e%ed6Bed7BZ&e&j$d8d-ed9ed:BZ'e'j$d;d-ed<ed=BZ(e"e'BZ)ee)e&e)Z*e*j$d>d-ed?j+Z,ed@j+Z-eZ.e*ee,e.e-BZ/e.e/e e(e.>e e.e Z0dAdBZ1dSdDdEZ2dFd-dGd-ej3ej4ej5ej6ej7ej8dHZ9dIdJZ:eZ;dKdLZdQd Z?GdRd d eZ@dS)T)absolute_importdivisionprint_functionN)ParseException ParseResults stringStart stringEnd) ZeroOrMoreGroupForward QuotedString)Literal) string_types) SpecifierInvalidSpecifier InvalidMarkerUndefinedComparisonUndefinedEnvironmentNameMarkerdefault_environmentc@seZdZdZdS)rzE An invalid marker was found, users should refer to PEP 508. N)__name__ __module__ __qualname____doc__rr/usr/lib/python3.6/markers.pyrsc@seZdZdZdS)rzP An invalid operation was attempted on a value that doesn't support it. N)rrrrrrrrrsc@seZdZdZdS)rz\ A name was attempted to be used that does not exist inside of the environment. N)rrrrrrrrr%sc@s,eZdZddZddZddZddZd S) NodecCs ||_dS)N)value)selfrrrr__init__.sz Node.__init__cCs t|jS)N)strr)rrrr__str__1sz Node.__str__cCsdj|jjt|S)Nz <{0}({1!r})>)format __class__rr!)rrrr__repr__4sz Node.__repr__cCstdS)N)NotImplementedError)rrrr serialize7szNode.serializeN)rrrr r"r%r'rrrrr,src@seZdZddZdS)VariablecCst|S)N)r!)rrrrr'=szVariable.serializeN)rrrr'rrrrr(;sr(c@seZdZddZdS)ValuecCs dj|S)Nz"{0}")r#)rrrrr'CszValue.serializeN)rrrr'rrrrr)Asr)c@seZdZddZdS)OpcCst|S)N)r!)rrrrr'Isz Op.serializeN)rrrr'rrrrr*Gsr*implementation_versionplatform_python_implementationimplementation_namepython_full_versionplatform_releaseplatform_versionplatform_machineplatform_systempython_version sys_platformos_namezos.namez sys.platformzplatform.versionzplatform.machinezplatform.python_implementationpython_implementationZextra)zos.namez sys.platformzplatform.versionzplatform.machinezplatform.python_implementationr6cCsttj|d|dS)Nr)r(ALIASESget)sltrrrisr<z===z==z>=z<=z!=z~=>sz(_coerce_parse_result..) isinstancer)resultsrrrrGs rGTcCst|tttfstt|trHt|dkrHt|dttfrHt|dSt|trdd|D}|rndj|Sddj|dSn"t|trdjdd |DS|SdS) Nrrcss|]}t|ddVqdS)F)firstN)_format_marker)rHmrrr sz!_format_marker.. rErFcSsg|] }|jqSr)r')rHrOrrrrJsz"_format_marker..)rKlistrDrAssertionErrorlenrNjoin)markerrMinnerrrrrNs    rNcCs||kS)Nr)lhsrhsrrrr<scCs||kS)Nr)rXrYrrrr<s)r?znot inr>z<=z==z!=z>=r=c Cslytdj|j|g}Wntk r.Yn X|j|Stj|j}|dkrbtdj||||||S)Nz#Undefined {0!r} on {1!r} and {2!r}.) rrUr'rcontains _operatorsr8rr#)rXoprYspecZoperrrr_eval_ops r_cCs&|j|t}|tkr"tdj||S)Nz/{0!r} does not exist in evaluation environment.)r8 _undefinedrr#) environmentnamerrrr_get_envs   rcc Csgg}x|D]}t|tttfs$tt|trD|djt||q t|tr|\}}}t|trvt||j }|j }n|j }t||j }|djt |||q |dkst|dkr |jgq Wt dd|DS) NrrBrCcss|]}t|VqdS)N)all)rHitemrrrrPsz$_evaluate_markers..rf)rBrC) rKrRrDrrSappend_evaluate_markersr(rcrr_any) ZmarkersragroupsrVrXr]rYZ lhs_valueZ rhs_valuerrrrhs"        rhcCs2dj|}|j}|dkr.||dt|j7}|S)Nz{0.major}.{0.minor}.{0.micro}finalr)r# releaselevelr!serial)infoversionZkindrrrformat_full_versions  rpc Cslttdr ttjj}tjj}nd}d}||tjtjtj tj tjtj tj tj ddtjd S)Nimplementation0rZ) r-r+r5r1r/r2r0r.r,r3r4) hasattrsysrprqrorbosplatformmachinereleasesystemr3r6)Ziverr-rrrrs    c@s.eZdZddZddZddZd dd ZdS) rcCs`yttj||_WnFtk rZ}z*dj|||j|jd}t|WYdd}~XnXdS)Nz+Invalid marker: {0!r}, parse error at {1!r})rGMARKERZ parseString_markersrr#locr)rrVeZerr_strrrrr s zMarker.__init__cCs t|jS)N)rNr})rrrrr"szMarker.__str__cCsdjt|S)Nz)r#r!)rrrrr%szMarker.__repr__NcCs$t}|dk r|j|t|j|S)a$Evaluate a marker. Return the boolean from evaluating the given marker against the environment. environment is an optional argument to override all or part of the determined environment. The environment is determined from the current Python process. N)rupdaterhr})rraZcurrent_environmentrrrevaluate s  zMarker.evaluate)N)rrrr r"r%rrrrrrs)T)AZ __future__rrroperatorrvrwruZpkg_resources.extern.pyparsingrrrrr r r r r LZ_compatrZ specifiersrr__all__ ValueErrorrrrobjectrr(r)r*ZVARIABLEr7ZsetParseActionZ VERSION_CMPZ MARKER_OPZ MARKER_VALUEZBOOLOPZ MARKER_VARZ MARKER_ITEMsuppressZLPARENZRPARENZ MARKER_EXPRZ MARKER_ATOMr|rGrNltleeqnegegtr\r_r`rcrhrprrrrrrsx    6       packaging/__pycache__/requirements.cpython-36.opt-1.pyc000064400000007330147205126200017012 0ustar003 9f@srddlmZmZmZddlZddlZddlmZmZm Z m Z ddlm Z m Z m Z mZmZddlmZddlmZddlmZmZdd lmZmZmZGd d d eZe ejejZ ed j!Z"ed j!Z#edj!Z$edj!Z%edj!Z&edj!Z'edj!Z(e dZ)e e e)e BZ*ee e e*Z+e+dZ,e+Z-eddZ.e(e.Z/e-e e&e-Z0e"e e0e#dZ1eej2ej3ej4BZ5eej2ej3ej4BZ6e5e6AZ7ee7e e&e7ddddZ8e e$e8e%e8BZ9e9j:dde e9dZ;e;j:dde edZej:d de'Ze/e e=Z?e,e e1e?e>BZ@ee@eZAGd!d"d"eBZCdS)#)absolute_importdivisionprint_functionN) stringStart stringEndoriginalTextForParseException) ZeroOrMoreWordOptionalRegexCombine)Literal)parse) MARKER_EXPRMarker)LegacySpecifier Specifier SpecifierSetc@seZdZdZdS)InvalidRequirementzJ An invalid requirement was found, users should refer to PEP 508. N)__name__ __module__ __qualname____doc__rr"/usr/lib/python3.6/requirements.pyrsr[](),;@z-_.namez[^ ]+urlextrasF)Z joinStringZadjacent _raw_speccCs |jpdS)N)r')sltrrr6sr, specifiercCs|dS)Nrr)r)r*r+rrrr,9smarkercCst||j|jS)N)rZ_original_startZ _original_end)r)r*r+rrrr,=sc@s(eZdZdZddZddZddZdS) RequirementzParse a requirement. Parse a given requirement string into its parts, such as name, specifier, URL, and extras. Raises InvalidRequirement on a badly-formed requirement string. cCsytj|}Wn@tk rN}z$tdj||j|jdWYdd}~XnX|j|_|jrtj|j}|j ot|j s|j r|j rtd|j|_nd|_t |j r|j j ng|_ t|j|_|jr|jnd|_dS)Nz+Invalid requirement, parse error at "{0!r}"zInvalid URL given) REQUIREMENTZ parseStringrrformatlocr$r%urlparseschemeZnetlocsetr&ZasListrr-r.)selfZrequirement_stringZreqeZ parsed_urlrrr__init__Xs"*   zRequirement.__init__cCsz|jg}|jr*|jdjdjt|j|jr@|jt|j|jrX|jdj|j|j rp|jdj|j dj|S)Nz[{0}]r!z@ {0}z; {0}r() r$r&appendr2joinsortedr-strr%r.)r7partsrrr__str__mszRequirement.__str__cCsdjt|S)Nz)r2r=)r7rrr__repr__~szRequirement.__repr__N)rrrrr9r?r@rrrrr/Ksr/)DZ __future__rrrstringreZpkg_resources.extern.pyparsingrrrrr r r r r rLZ%pkg_resources.extern.six.moves.urllibrr4ZmarkersrrZ specifiersrrr ValueErrorrZ ascii_lettersZdigitsZALPHANUMsuppressZLBRACKETZRBRACKETZLPARENZRPARENCOMMAZ SEMICOLONATZ PUNCTUATIONZIDENTIFIER_ENDZ IDENTIFIERNAMEZEXTRAZURIZURLZ EXTRAS_LISTZEXTRASZ _regex_strVERBOSE IGNORECASEZVERSION_PEP440ZVERSION_LEGACYZ VERSION_ONEZ VERSION_MANYZ _VERSION_SPECZsetParseActionZ VERSION_SPECZMARKER_SEPERATORZMARKERZVERSION_AND_MARKERZURL_AND_MARKERZNAMED_REQUIREMENTr1objectr/rrrrsZ               packaging/__pycache__/requirements.cpython-36.pyc000064400000007330147205126200016053 0ustar003 9f@srddlmZmZmZddlZddlZddlmZmZm Z m Z ddlm Z m Z m Z mZmZddlmZddlmZddlmZmZdd lmZmZmZGd d d eZe ejejZ ed j!Z"ed j!Z#edj!Z$edj!Z%edj!Z&edj!Z'edj!Z(e dZ)e e e)e BZ*ee e e*Z+e+dZ,e+Z-eddZ.e(e.Z/e-e e&e-Z0e"e e0e#dZ1eej2ej3ej4BZ5eej2ej3ej4BZ6e5e6AZ7ee7e e&e7ddddZ8e e$e8e%e8BZ9e9j:dde e9dZ;e;j:dde edZej:d de'Ze/e e=Z?e,e e1e?e>BZ@ee@eZAGd!d"d"eBZCdS)#)absolute_importdivisionprint_functionN) stringStart stringEndoriginalTextForParseException) ZeroOrMoreWordOptionalRegexCombine)Literal)parse) MARKER_EXPRMarker)LegacySpecifier Specifier SpecifierSetc@seZdZdZdS)InvalidRequirementzJ An invalid requirement was found, users should refer to PEP 508. N)__name__ __module__ __qualname____doc__rr"/usr/lib/python3.6/requirements.pyrsr[](),;@z-_.namez[^ ]+urlextrasF)Z joinStringZadjacent _raw_speccCs |jpdS)N)r')sltrrr6sr, specifiercCs|dS)Nrr)r)r*r+rrrr,9smarkercCst||j|jS)N)rZ_original_startZ _original_end)r)r*r+rrrr,=sc@s(eZdZdZddZddZddZdS) RequirementzParse a requirement. Parse a given requirement string into its parts, such as name, specifier, URL, and extras. Raises InvalidRequirement on a badly-formed requirement string. cCsytj|}Wn@tk rN}z$tdj||j|jdWYdd}~XnX|j|_|jrtj|j}|j ot|j s|j r|j rtd|j|_nd|_t |j r|j j ng|_ t|j|_|jr|jnd|_dS)Nz+Invalid requirement, parse error at "{0!r}"zInvalid URL given) REQUIREMENTZ parseStringrrformatlocr$r%urlparseschemeZnetlocsetr&ZasListrr-r.)selfZrequirement_stringZreqeZ parsed_urlrrr__init__Xs"*   zRequirement.__init__cCsz|jg}|jr*|jdjdjt|j|jr@|jt|j|jrX|jdj|j|j rp|jdj|j dj|S)Nz[{0}]r!z@ {0}z; {0}r() r$r&appendr2joinsortedr-strr%r.)r7partsrrr__str__mszRequirement.__str__cCsdjt|S)Nz)r2r=)r7rrr__repr__~szRequirement.__repr__N)rrrrr9r?r@rrrrr/Ksr/)DZ __future__rrrstringreZpkg_resources.extern.pyparsingrrrrr r r r r rLZ%pkg_resources.extern.six.moves.urllibrr4ZmarkersrrZ specifiersrrr ValueErrorrZ ascii_lettersZdigitsZALPHANUMsuppressZLBRACKETZRBRACKETZLPARENZRPARENCOMMAZ SEMICOLONATZ PUNCTUATIONZIDENTIFIER_ENDZ IDENTIFIERNAMEZEXTRAZURIZURLZ EXTRAS_LISTZEXTRASZ _regex_strVERBOSE IGNORECASEZVERSION_PEP440ZVERSION_LEGACYZ VERSION_ONEZ VERSION_MANYZ _VERSION_SPECZsetParseActionZ VERSION_SPECZMARKER_SEPERATORZMARKERZVERSION_AND_MARKERZURL_AND_MARKERZNAMED_REQUIREMENTr1objectr/rrrrsZ               packaging/__pycache__/specifiers.cpython-36.opt-1.pyc000064400000046437147205126200016436 0ustar003 9fym@sddlmZmZmZddlZddlZddlZddlZddlm Z m Z ddl m Z m Z mZGdddeZGdd d e ejeZGd d d eZGd d d eZddZGdddeZejdZddZddZGdddeZdS))absolute_importdivisionprint_functionN) string_typeswith_metaclass)Version LegacyVersionparsec@seZdZdZdS)InvalidSpecifierzH An invalid specifier was found, users should refer to PEP 440. N)__name__ __module__ __qualname____doc__rr /usr/lib/python3.6/specifiers.pyr sr c@seZdZejddZejddZejddZejddZej d d Z e j d d Z ejdd dZ ejdddZ d S) BaseSpecifiercCsdS)z Returns the str representation of this Specifier like object. This should be representative of the Specifier itself. Nr)selfrrr__str__szBaseSpecifier.__str__cCsdS)zF Returns a hash value for this Specifier like object. Nr)rrrr__hash__szBaseSpecifier.__hash__cCsdS)zq Returns a boolean representing whether or not the two Specifier like objects are equal. Nr)rotherrrr__eq__$szBaseSpecifier.__eq__cCsdS)zu Returns a boolean representing whether or not the two Specifier like objects are not equal. Nr)rrrrr__ne__+szBaseSpecifier.__ne__cCsdS)zg Returns whether or not pre-releases as a whole are allowed by this specifier. Nr)rrrr prereleases2szBaseSpecifier.prereleasescCsdS)zd Sets whether or not pre-releases as a whole are allowed by this specifier. Nr)rvaluerrrr9sNcCsdS)zR Determines if the given item is contained within this specifier. Nr)ritemrrrrcontains@szBaseSpecifier.containscCsdS)z Takes an iterable of items and filters them so that only items which are contained within this specifier are allowed in it. Nr)riterablerrrrfilterFszBaseSpecifier.filter)N)N)r r rabcabstractmethodrrrrabstractpropertyrsetterrrrrrrrs rc@seZdZiZd ddZddZddZd d Zd d Zd dZ ddZ ddZ e ddZ e ddZe ddZejddZddZd!ddZd"ddZdS)#_IndividualSpecifierNcCsF|jj|}|stdj||jdj|jdjf|_||_dS)NzInvalid specifier: '{0}'operatorversion)_regexsearchr formatgroupstrip_spec _prereleases)rspecrmatchrrr__init__Rs   z_IndividualSpecifier.__init__cCs0|jdk rdj|jnd}dj|jjt||S)Nz, prereleases={0!r}r$z<{0}({1!r}{2})>)r-r)r __class__r str)rprerrr__repr___s z_IndividualSpecifier.__repr__cCs dj|jS)Nz{0}{1})r)r,)rrrrrlsz_IndividualSpecifier.__str__cCs t|jS)N)hashr,)rrrrrosz_IndividualSpecifier.__hash__c CsLt|tr0y|j|}Wq@tk r,tSXnt||js@tS|j|jkS)N) isinstancerr1r NotImplementedr,)rrrrrrrs  z_IndividualSpecifier.__eq__c CsLt|tr0y|j|}Wq@tk r,tSXnt||js@tS|j|jkS)N)r6rr1r r7r,)rrrrrr}s  z_IndividualSpecifier.__ne__cCst|dj|j|S)Nz _compare_{0})getattrr) _operators)roprrr _get_operatorsz"_IndividualSpecifier._get_operatorcCst|ttfst|}|S)N)r6r rr )rr&rrr_coerce_versionsz$_IndividualSpecifier._coerce_versioncCs |jdS)Nr)r,)rrrrr%sz_IndividualSpecifier.operatorcCs |jdS)Nr)r,)rrrrr&sz_IndividualSpecifier.versioncCs|jS)N)r-)rrrrrsz _IndividualSpecifier.prereleasescCs ||_dS)N)r-)rrrrrrscCs |j|S)N)r)rrrrr __contains__sz!_IndividualSpecifier.__contains__cCs<|dkr|j}|j|}|jr(| r(dS|j|j||jS)NF)rr< is_prereleaser;r%r&)rrrrrrrs   z_IndividualSpecifier.containsccsd}g}d|dk r|ndi}xL|D]D}|j|}|j|f|r"|jr\|pL|j r\|j|q"d}|Vq"W| r|rx|D] }|VqzWdS)NFrT)r<rr>rappend)rrrZyieldedfound_prereleaseskwr&parsed_versionrrrrs       z_IndividualSpecifier.filter)r$N)N)N)r r rr9r0r4rrrrr;r<propertyr%r&rr"r=rrrrrrr#Ns         r#c@sveZdZdZejdedejejBZdddddd d Z d d Z d dZ ddZ ddZ ddZddZddZdS)LegacySpecifiera (?P(==|!=|<=|>=|<|>)) \s* (?P [^,;\s)]* # Since this is a "legacy" specifier, and the version # string can be just about anything, we match everything # except for whitespace, a semi-colon for marker support, # a closing paren since versions can be enclosed in # them, and a comma since it's a version separator. ) z^\s*z\s*$equal not_equalless_than_equalgreater_than_equal less_than greater_than)z==z!=z<=z>=<>cCst|tstt|}|S)N)r6r r2)rr&rrrr<s  zLegacySpecifier._coerce_versioncCs||j|kS)N)r<)r prospectiver.rrr_compare_equalszLegacySpecifier._compare_equalcCs||j|kS)N)r<)rrMr.rrr_compare_not_equalsz"LegacySpecifier._compare_not_equalcCs||j|kS)N)r<)rrMr.rrr_compare_less_than_equalsz(LegacySpecifier._compare_less_than_equalcCs||j|kS)N)r<)rrMr.rrr_compare_greater_than_equalsz+LegacySpecifier._compare_greater_than_equalcCs||j|kS)N)r<)rrMr.rrr_compare_less_thansz"LegacySpecifier._compare_less_thancCs||j|kS)N)r<)rrMr.rrr_compare_greater_thansz%LegacySpecifier._compare_greater_thanN)r r r _regex_strrecompileVERBOSE IGNORECASEr'r9r<rNrOrPrQrRrSrrrrrDs  rDcstjfdd}|S)Ncst|tsdS|||S)NF)r6r)rrMr.)fnrrwrapped s z)_require_version_compare..wrapped) functoolswraps)rYrZr)rYr_require_version_compare sr]c @seZdZdZejdedejejBZdddddd d d d Z e d dZ e ddZ e ddZ e ddZe ddZe ddZe ddZddZeddZejddZd S)! Specifiera (?P(~=|==|!=|<=|>=|<|>|===)) (?P (?: # The identity operators allow for an escape hatch that will # do an exact string match of the version you wish to install. # This will not be parsed by PEP 440 and we cannot determine # any semantic meaning from it. This operator is discouraged # but included entirely as an escape hatch. (?<====) # Only match for the identity operator \s* [^\s]* # We just match everything, except for whitespace # since we are only testing for strict identity. ) | (?: # The (non)equality operators allow for wild card and local # versions to be specified so we have to define these two # operators separately to enable that. (?<===|!=) # Only match for equals and not equals \s* v? (?:[0-9]+!)? # epoch [0-9]+(?:\.[0-9]+)* # release (?: # pre release [-_\.]? (a|b|c|rc|alpha|beta|pre|preview) [-_\.]? [0-9]* )? (?: # post release (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) )? # You cannot use a wild card and a dev or local version # together so group them with a | and make them optional. (?: (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local | \.\* # Wild card syntax of .* )? ) | (?: # The compatible operator requires at least two digits in the # release segment. (?<=~=) # Only match for the compatible operator \s* v? (?:[0-9]+!)? # epoch [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) (?: # pre release [-_\.]? (a|b|c|rc|alpha|beta|pre|preview) [-_\.]? [0-9]* )? (?: # post release (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) )? (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release ) | (?: # All other operators only allow a sub set of what the # (non)equality operators do. Specifically they do not allow # local versions to be specified nor do they allow the prefix # matching wild cards. (?=rKrLz===cCsNdjttjddt|dd}|d7}|jd||oL|jd||S) N.cSs|jd o|jd S)NZpostZdev) startswith)xrrrs z/Specifier._compare_compatible..rz.*z>=z==)joinlist itertools takewhile_version_splitr;)rrMr.prefixrrr_compare_compatibles   zSpecifier._compare_compatiblecCsp|jdrPt|j}t|dd}tt|}|dt|}t||\}}nt|}|jsht|j}||kS)Nz.*)endswithrZpublicrhr2len _pad_versionlocal)rrMr.rrrrNs    zSpecifier._compare_equalcCs|j|| S)N)rN)rrMr.rrrrOszSpecifier._compare_not_equalcCs |t|kS)N)r)rrMr.rrrrPsz"Specifier._compare_less_than_equalcCs |t|kS)N)r)rrMr.rrrrQsz%Specifier._compare_greater_than_equalcCs>t|}||ksdS|j r:|jr:t|jt|jkr:dSdS)NFT)rr> base_version)rrMr.rrrrRszSpecifier._compare_less_thancCs`t|}||ksdS|j r:|jr:t|jt|jkr:dS|jdk r\t|jt|jkr\dSdS)NFT)rZis_postreleaserqrp)rrMr.rrrrSs zSpecifier._compare_greater_thancCst|jt|jkS)N)r2lower)rrMr.rrr_compare_arbitraryszSpecifier._compare_arbitrarycCsR|jdk r|jS|j\}}|d krN|dkr@|jdr@|dd }t|jrNdSd S) N==>=<=~====z.*rkTF)rtrurvrwrxrl)r-r,rmr r>)rr%r&rrrrs    zSpecifier.prereleasescCs ||_dS)N)r-)rrrrrrsN)r r rrTrUrVrWrXr'r9r]rjrNrOrPrQrRrSrsrCrr"rrrrr^s*^  #      r^z^([0-9]+)((?:a|b|c|rc)[0-9]+)$cCsDg}x:|jdD],}tj|}|r2|j|jq|j|qW|S)Nr_)split _prefix_regexr(extendgroupsr?)r&resultrr/rrrrh's rhc Csgg}}|jttjdd||jttjdd||j|t|dd|j|t|dd|jddgtdt|dt|d|jddgtdt|dt|dttj|ttj|fS)NcSs|jS)N)isdigit)rarrrrb6sz_pad_version..cSs|jS)N)r~)rarrrrb7srr0)r?rerfrgrninsertmaxchain)leftrightZ left_splitZ right_splitrrrro2s && roc@seZdZdddZddZddZd d Zd d Zd dZddZ ddZ ddZ e ddZ e jddZ ddZdddZd ddZdS)! SpecifierSetr$Nc Csrdd|jdD}t}xB|D]:}y|jt|Wq tk rX|jt|Yq Xq Wt||_||_dS)NcSsg|]}|jr|jqSr)r+).0srrr Rsz)SpecifierSet.__init__..,) rysetaddr^r rD frozenset_specsr-)rZ specifiersrZparsed specifierrrrr0Os  zSpecifierSet.__init__cCs*|jdk rdj|jnd}djt||S)Nz, prereleases={0!r}r$z)r-r)rr2)rr3rrrr4dszSpecifierSet.__repr__cCsdjtdd|jDS)Nrcss|]}t|VqdS)N)r2)rrrrr nsz'SpecifierSet.__str__..)rdsortedr)rrrrrmszSpecifierSet.__str__cCs t|jS)N)r5r)rrrrrpszSpecifierSet.__hash__cCst|trt|}nt|ts"tSt}t|j|jB|_|jdkrX|jdk rX|j|_n<|jdk rv|jdkrv|j|_n|j|jkr|j|_ntd|S)NzFCannot combine SpecifierSets with True and False prerelease overrides.)r6rrr7rrr- ValueError)rrrrrr__and__ss       zSpecifierSet.__and__cCsFt|trt|}n&t|tr,tt|}nt|ts:tS|j|jkS)N)r6rrr#r2r7r)rrrrrrs    zSpecifierSet.__eq__cCsFt|trt|}n&t|tr,tt|}nt|ts:tS|j|jkS)N)r6rrr#r2r7r)rrrrrrs    zSpecifierSet.__ne__cCs t|jS)N)rnr)rrrr__len__szSpecifierSet.__len__cCs t|jS)N)iterr)rrrr__iter__szSpecifierSet.__iter__cCs.|jdk r|jS|jsdStdd|jDS)Ncss|] }|jVqdS)N)r)rrrrrrsz+SpecifierSet.prereleases..)r-rany)rrrrrs  zSpecifierSet.prereleasescCs ||_dS)N)r-)rrrrrrscCs |j|S)N)r)rrrrrr=szSpecifierSet.__contains__csNtttfstdkr$|j r4jr4dStfdd|jDS)NFc3s|]}|jdVqdS))rN)r)rr)rrrrrsz(SpecifierSet.contains..)r6r rr rr>allr)rrrr)rrrrs  zSpecifierSet.containscCs|dkr|j}|jr:x |jD]}|j|t|d}qW|Sg}g}xZ|D]R}t|ttfsdt|}n|}t|trtqH|jr| r|s|j |qH|j |qHW| r|r|dkr|S|SdS)N)r) rrrboolr6r rr r>r?)rrrr.Zfilteredr@rrBrrrrs*      zSpecifierSet.filter)r$N)N)N)r r rr0r4rrrrrrrrCrr"r=rrrrrrrMs      r)Z __future__rrrrr[rfrUZ_compatrrr&rr r rr ABCMetaobjectrr#rDr]r^rVrzrhrorrrrrs&9 4   packaging/__pycache__/specifiers.cpython-36.pyc000064400000046437147205126200015477 0ustar003 9fym@sddlmZmZmZddlZddlZddlZddlZddlm Z m Z ddl m Z m Z mZGdddeZGdd d e ejeZGd d d eZGd d d eZddZGdddeZejdZddZddZGdddeZdS))absolute_importdivisionprint_functionN) string_typeswith_metaclass)Version LegacyVersionparsec@seZdZdZdS)InvalidSpecifierzH An invalid specifier was found, users should refer to PEP 440. N)__name__ __module__ __qualname____doc__rr /usr/lib/python3.6/specifiers.pyr sr c@seZdZejddZejddZejddZejddZej d d Z e j d d Z ejdd dZ ejdddZ d S) BaseSpecifiercCsdS)z Returns the str representation of this Specifier like object. This should be representative of the Specifier itself. Nr)selfrrr__str__szBaseSpecifier.__str__cCsdS)zF Returns a hash value for this Specifier like object. Nr)rrrr__hash__szBaseSpecifier.__hash__cCsdS)zq Returns a boolean representing whether or not the two Specifier like objects are equal. Nr)rotherrrr__eq__$szBaseSpecifier.__eq__cCsdS)zu Returns a boolean representing whether or not the two Specifier like objects are not equal. Nr)rrrrr__ne__+szBaseSpecifier.__ne__cCsdS)zg Returns whether or not pre-releases as a whole are allowed by this specifier. Nr)rrrr prereleases2szBaseSpecifier.prereleasescCsdS)zd Sets whether or not pre-releases as a whole are allowed by this specifier. Nr)rvaluerrrr9sNcCsdS)zR Determines if the given item is contained within this specifier. Nr)ritemrrrrcontains@szBaseSpecifier.containscCsdS)z Takes an iterable of items and filters them so that only items which are contained within this specifier are allowed in it. Nr)riterablerrrrfilterFszBaseSpecifier.filter)N)N)r r rabcabstractmethodrrrrabstractpropertyrsetterrrrrrrrs rc@seZdZiZd ddZddZddZd d Zd d Zd dZ ddZ ddZ e ddZ e ddZe ddZejddZddZd!ddZd"ddZdS)#_IndividualSpecifierNcCsF|jj|}|stdj||jdj|jdjf|_||_dS)NzInvalid specifier: '{0}'operatorversion)_regexsearchr formatgroupstrip_spec _prereleases)rspecrmatchrrr__init__Rs   z_IndividualSpecifier.__init__cCs0|jdk rdj|jnd}dj|jjt||S)Nz, prereleases={0!r}r$z<{0}({1!r}{2})>)r-r)r __class__r str)rprerrr__repr___s z_IndividualSpecifier.__repr__cCs dj|jS)Nz{0}{1})r)r,)rrrrrlsz_IndividualSpecifier.__str__cCs t|jS)N)hashr,)rrrrrosz_IndividualSpecifier.__hash__c CsLt|tr0y|j|}Wq@tk r,tSXnt||js@tS|j|jkS)N) isinstancerr1r NotImplementedr,)rrrrrrrs  z_IndividualSpecifier.__eq__c CsLt|tr0y|j|}Wq@tk r,tSXnt||js@tS|j|jkS)N)r6rr1r r7r,)rrrrrr}s  z_IndividualSpecifier.__ne__cCst|dj|j|S)Nz _compare_{0})getattrr) _operators)roprrr _get_operatorsz"_IndividualSpecifier._get_operatorcCst|ttfst|}|S)N)r6r rr )rr&rrr_coerce_versionsz$_IndividualSpecifier._coerce_versioncCs |jdS)Nr)r,)rrrrr%sz_IndividualSpecifier.operatorcCs |jdS)Nr)r,)rrrrr&sz_IndividualSpecifier.versioncCs|jS)N)r-)rrrrrsz _IndividualSpecifier.prereleasescCs ||_dS)N)r-)rrrrrrscCs |j|S)N)r)rrrrr __contains__sz!_IndividualSpecifier.__contains__cCs<|dkr|j}|j|}|jr(| r(dS|j|j||jS)NF)rr< is_prereleaser;r%r&)rrrrrrrs   z_IndividualSpecifier.containsccsd}g}d|dk r|ndi}xL|D]D}|j|}|j|f|r"|jr\|pL|j r\|j|q"d}|Vq"W| r|rx|D] }|VqzWdS)NFrT)r<rr>rappend)rrrZyieldedfound_prereleaseskwr&parsed_versionrrrrs       z_IndividualSpecifier.filter)r$N)N)N)r r rr9r0r4rrrrr;r<propertyr%r&rr"r=rrrrrrr#Ns         r#c@sveZdZdZejdedejejBZdddddd d Z d d Z d dZ ddZ ddZ ddZddZddZdS)LegacySpecifiera (?P(==|!=|<=|>=|<|>)) \s* (?P [^,;\s)]* # Since this is a "legacy" specifier, and the version # string can be just about anything, we match everything # except for whitespace, a semi-colon for marker support, # a closing paren since versions can be enclosed in # them, and a comma since it's a version separator. ) z^\s*z\s*$equal not_equalless_than_equalgreater_than_equal less_than greater_than)z==z!=z<=z>=<>cCst|tstt|}|S)N)r6r r2)rr&rrrr<s  zLegacySpecifier._coerce_versioncCs||j|kS)N)r<)r prospectiver.rrr_compare_equalszLegacySpecifier._compare_equalcCs||j|kS)N)r<)rrMr.rrr_compare_not_equalsz"LegacySpecifier._compare_not_equalcCs||j|kS)N)r<)rrMr.rrr_compare_less_than_equalsz(LegacySpecifier._compare_less_than_equalcCs||j|kS)N)r<)rrMr.rrr_compare_greater_than_equalsz+LegacySpecifier._compare_greater_than_equalcCs||j|kS)N)r<)rrMr.rrr_compare_less_thansz"LegacySpecifier._compare_less_thancCs||j|kS)N)r<)rrMr.rrr_compare_greater_thansz%LegacySpecifier._compare_greater_thanN)r r r _regex_strrecompileVERBOSE IGNORECASEr'r9r<rNrOrPrQrRrSrrrrrDs  rDcstjfdd}|S)Ncst|tsdS|||S)NF)r6r)rrMr.)fnrrwrapped s z)_require_version_compare..wrapped) functoolswraps)rYrZr)rYr_require_version_compare sr]c @seZdZdZejdedejejBZdddddd d d d Z e d dZ e ddZ e ddZ e ddZe ddZe ddZe ddZddZeddZejddZd S)! Specifiera (?P(~=|==|!=|<=|>=|<|>|===)) (?P (?: # The identity operators allow for an escape hatch that will # do an exact string match of the version you wish to install. # This will not be parsed by PEP 440 and we cannot determine # any semantic meaning from it. This operator is discouraged # but included entirely as an escape hatch. (?<====) # Only match for the identity operator \s* [^\s]* # We just match everything, except for whitespace # since we are only testing for strict identity. ) | (?: # The (non)equality operators allow for wild card and local # versions to be specified so we have to define these two # operators separately to enable that. (?<===|!=) # Only match for equals and not equals \s* v? (?:[0-9]+!)? # epoch [0-9]+(?:\.[0-9]+)* # release (?: # pre release [-_\.]? (a|b|c|rc|alpha|beta|pre|preview) [-_\.]? [0-9]* )? (?: # post release (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) )? # You cannot use a wild card and a dev or local version # together so group them with a | and make them optional. (?: (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local | \.\* # Wild card syntax of .* )? ) | (?: # The compatible operator requires at least two digits in the # release segment. (?<=~=) # Only match for the compatible operator \s* v? (?:[0-9]+!)? # epoch [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) (?: # pre release [-_\.]? (a|b|c|rc|alpha|beta|pre|preview) [-_\.]? [0-9]* )? (?: # post release (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) )? (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release ) | (?: # All other operators only allow a sub set of what the # (non)equality operators do. Specifically they do not allow # local versions to be specified nor do they allow the prefix # matching wild cards. (?=rKrLz===cCsNdjttjddt|dd}|d7}|jd||oL|jd||S) N.cSs|jd o|jd S)NZpostZdev) startswith)xrrrs z/Specifier._compare_compatible..rz.*z>=z==)joinlist itertools takewhile_version_splitr;)rrMr.prefixrrr_compare_compatibles   zSpecifier._compare_compatiblecCsp|jdrPt|j}t|dd}tt|}|dt|}t||\}}nt|}|jsht|j}||kS)Nz.*)endswithrZpublicrhr2len _pad_versionlocal)rrMr.rrrrNs    zSpecifier._compare_equalcCs|j|| S)N)rN)rrMr.rrrrOszSpecifier._compare_not_equalcCs |t|kS)N)r)rrMr.rrrrPsz"Specifier._compare_less_than_equalcCs |t|kS)N)r)rrMr.rrrrQsz%Specifier._compare_greater_than_equalcCs>t|}||ksdS|j r:|jr:t|jt|jkr:dSdS)NFT)rr> base_version)rrMr.rrrrRszSpecifier._compare_less_thancCs`t|}||ksdS|j r:|jr:t|jt|jkr:dS|jdk r\t|jt|jkr\dSdS)NFT)rZis_postreleaserqrp)rrMr.rrrrSs zSpecifier._compare_greater_thancCst|jt|jkS)N)r2lower)rrMr.rrr_compare_arbitraryszSpecifier._compare_arbitrarycCsR|jdk r|jS|j\}}|d krN|dkr@|jdr@|dd }t|jrNdSd S) N==>=<=~====z.*rkTF)rtrurvrwrxrl)r-r,rmr r>)rr%r&rrrrs    zSpecifier.prereleasescCs ||_dS)N)r-)rrrrrrsN)r r rrTrUrVrWrXr'r9r]rjrNrOrPrQrRrSrsrCrr"rrrrr^s*^  #      r^z^([0-9]+)((?:a|b|c|rc)[0-9]+)$cCsDg}x:|jdD],}tj|}|r2|j|jq|j|qW|S)Nr_)split _prefix_regexr(extendgroupsr?)r&resultrr/rrrrh's rhc Csgg}}|jttjdd||jttjdd||j|t|dd|j|t|dd|jddgtdt|dt|d|jddgtdt|dt|dttj|ttj|fS)NcSs|jS)N)isdigit)rarrrrb6sz_pad_version..cSs|jS)N)r~)rarrrrb7srr0)r?rerfrgrninsertmaxchain)leftrightZ left_splitZ right_splitrrrro2s && roc@seZdZdddZddZddZd d Zd d Zd dZddZ ddZ ddZ e ddZ e jddZ ddZdddZd ddZdS)! SpecifierSetr$Nc Csrdd|jdD}t}xB|D]:}y|jt|Wq tk rX|jt|Yq Xq Wt||_||_dS)NcSsg|]}|jr|jqSr)r+).0srrr Rsz)SpecifierSet.__init__..,) rysetaddr^r rD frozenset_specsr-)rZ specifiersrZparsed specifierrrrr0Os  zSpecifierSet.__init__cCs*|jdk rdj|jnd}djt||S)Nz, prereleases={0!r}r$z)r-r)rr2)rr3rrrr4dszSpecifierSet.__repr__cCsdjtdd|jDS)Nrcss|]}t|VqdS)N)r2)rrrrr nsz'SpecifierSet.__str__..)rdsortedr)rrrrrmszSpecifierSet.__str__cCs t|jS)N)r5r)rrrrrpszSpecifierSet.__hash__cCst|trt|}nt|ts"tSt}t|j|jB|_|jdkrX|jdk rX|j|_n<|jdk rv|jdkrv|j|_n|j|jkr|j|_ntd|S)NzFCannot combine SpecifierSets with True and False prerelease overrides.)r6rrr7rrr- ValueError)rrrrrr__and__ss       zSpecifierSet.__and__cCsFt|trt|}n&t|tr,tt|}nt|ts:tS|j|jkS)N)r6rrr#r2r7r)rrrrrrs    zSpecifierSet.__eq__cCsFt|trt|}n&t|tr,tt|}nt|ts:tS|j|jkS)N)r6rrr#r2r7r)rrrrrrs    zSpecifierSet.__ne__cCs t|jS)N)rnr)rrrr__len__szSpecifierSet.__len__cCs t|jS)N)iterr)rrrr__iter__szSpecifierSet.__iter__cCs.|jdk r|jS|jsdStdd|jDS)Ncss|] }|jVqdS)N)r)rrrrrrsz+SpecifierSet.prereleases..)r-rany)rrrrrs  zSpecifierSet.prereleasescCs ||_dS)N)r-)rrrrrrscCs |j|S)N)r)rrrrrr=szSpecifierSet.__contains__csNtttfstdkr$|j r4jr4dStfdd|jDS)NFc3s|]}|jdVqdS))rN)r)rr)rrrrrsz(SpecifierSet.contains..)r6r rr rr>allr)rrrr)rrrrs  zSpecifierSet.containscCs|dkr|j}|jr:x |jD]}|j|t|d}qW|Sg}g}xZ|D]R}t|ttfsdt|}n|}t|trtqH|jr| r|s|j |qH|j |qHW| r|r|dkr|S|SdS)N)r) rrrboolr6r rr r>r?)rrrr.Zfilteredr@rrBrrrrs*      zSpecifierSet.filter)r$N)N)N)r r rr0r4rrrrrrrrCrr"r=rrrrrrrMs      r)Z __future__rrrrr[rfrUZ_compatrrr&rr r rr ABCMetaobjectrr#rDr]r^rVrzrhrorrrrrs&9 4   packaging/__pycache__/utils.cpython-36.opt-1.pyc000064400000000630147205126200015423 0ustar003 9f@s2ddlmZmZmZddlZejdZddZdS))absolute_importdivisionprint_functionNz[-_.]+cCstjd|jS)N-)_canonicalize_regexsublower)namer /usr/lib/python3.6/utils.pycanonicalize_name sr )Z __future__rrrrecompilerr r r r r s packaging/__pycache__/utils.cpython-36.pyc000064400000000630147205126200014464 0ustar003 9f@s2ddlmZmZmZddlZejdZddZdS))absolute_importdivisionprint_functionNz[-_.]+cCstjd|jS)N-)_canonicalize_regexsublower)namer /usr/lib/python3.6/utils.pycanonicalize_name sr )Z __future__rrrrecompilerr r r r r s packaging/__pycache__/version.cpython-36.opt-1.pyc000064400000024426147205126200015761 0ustar003 9f$-@sddlmZmZmZddlZddlZddlZddlmZddddd gZ ej d d d d dddgZ ddZ Gddde ZGdddeZGdddeZejdejZddddddZddZddZdZGd ddeZd!d"Zejd#Zd$d%Zd&d'ZdS)()absolute_importdivisionprint_functionN)InfinityparseVersion LegacyVersionInvalidVersionVERSION_PATTERN_Versionepochreleasedevprepostlocalc Cs&yt|Stk r t|SXdS)z Parse the given version string and return either a :class:`Version` object or a :class:`LegacyVersion` object depending on if the given version is a valid PEP 440 version or a legacy version. N)rr r )versionr/usr/lib/python3.6/version.pyrsc@seZdZdZdS)r zF An invalid version was found, users should refer to PEP 440. N)__name__ __module__ __qualname____doc__rrrrr $sc@sLeZdZddZddZddZddZd d Zd d Zd dZ ddZ dS) _BaseVersioncCs t|jS)N)hash_key)selfrrr__hash__,sz_BaseVersion.__hash__cCs|j|ddS)NcSs||kS)Nr)sorrr0sz%_BaseVersion.__lt__..)_compare)rotherrrr__lt__/sz_BaseVersion.__lt__cCs|j|ddS)NcSs||kS)Nr)rr rrrr!3sz%_BaseVersion.__le__..)r")rr#rrr__le__2sz_BaseVersion.__le__cCs|j|ddS)NcSs||kS)Nr)rr rrrr!6sz%_BaseVersion.__eq__..)r")rr#rrr__eq__5sz_BaseVersion.__eq__cCs|j|ddS)NcSs||kS)Nr)rr rrrr!9sz%_BaseVersion.__ge__..)r")rr#rrr__ge__8sz_BaseVersion.__ge__cCs|j|ddS)NcSs||kS)Nr)rr rrrr!<sz%_BaseVersion.__gt__..)r")rr#rrr__gt__;sz_BaseVersion.__gt__cCs|j|ddS)NcSs||kS)Nr)rr rrrr!?sz%_BaseVersion.__ne__..)r")rr#rrr__ne__>sz_BaseVersion.__ne__cCst|tstS||j|jS)N) isinstancerNotImplementedr)rr#methodrrrr"As z_BaseVersion._compareN) rrrrr$r%r&r'r(r)r"rrrrr*src@s`eZdZddZddZddZeddZed d Zed d Z ed dZ eddZ dS)r cCst||_t|j|_dS)N)str_version_legacy_cmpkeyr)rrrrr__init__Js zLegacyVersion.__init__cCs|jS)N)r.)rrrr__str__NszLegacyVersion.__str__cCsdjtt|S)Nz)formatreprr-)rrrr__repr__QszLegacyVersion.__repr__cCs|jS)N)r.)rrrrpublicTszLegacyVersion.publiccCs|jS)N)r.)rrrr base_versionXszLegacyVersion.base_versioncCsdS)Nr)rrrrr\szLegacyVersion.localcCsdS)NFr)rrrr is_prerelease`szLegacyVersion.is_prereleasecCsdS)NFr)rrrris_postreleasedszLegacyVersion.is_postreleaseN) rrrr0r1r4propertyr5r6rr7r8rrrrr Hs    z(\d+ | [a-z]+ | \.| -)czfinal-@)rpreview-rcrccsbxVtj|D]H}tj||}| s |dkr,q |dddkrJ|jdVq d|Vq WdVdS)N.r 0123456789*z*final)_legacy_version_component_resplit_legacy_version_replacement_mapgetzfill)rpartrrr_parse_version_partsrs rIcCsd}g}xlt|jD]\}|jdrh|dkrJx|rH|ddkrH|jq.Wx|rf|ddkrf|jqLW|j|qWt|}||fS) NrrBz*finalz*final-Z00000000rJrJ)rIlower startswithpopappendtuple)rr partsrHrrrr/s   r/a v? (?: (?:(?P[0-9]+)!)? # epoch (?P[0-9]+(?:\.[0-9]+)*) # release segment (?P
                                          # pre-release
            [-_\.]?
            (?P(a|b|c|rc|alpha|beta|pre|preview))
            [-_\.]?
            (?P[0-9]+)?
        )?
        (?P                                         # post release
            (?:-(?P[0-9]+))
            |
            (?:
                [-_\.]?
                (?Ppost|rev|r)
                [-_\.]?
                (?P[0-9]+)?
            )
        )?
        (?P                                          # dev release
            [-_\.]?
            (?Pdev)
            [-_\.]?
            (?P[0-9]+)?
        )?
    )
    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
c@s|eZdZejdedejejBZddZ	ddZ
ddZed	d
Z
eddZed
dZeddZeddZdS)rz^\s*z\s*$c	Cs|jj|}|stdj|t|jdr8t|jdndtdd|jdjdDt	|jd|jd	t	|jd
|jdp|jdt	|jd
|jdt
|jdd|_t|jj
|jj|jj|jj|jj|jj|_dS)NzInvalid version: '{0}'r
rcss|]}t|VqdS)N)int).0irrr	sz#Version.__init__..rr?Zpre_lZpre_nZpost_lZpost_n1Zpost_n2Zdev_lZdev_nr)r
rrrrr)_regexsearchr
r2rgrouprQrOrD_parse_letter_version_parse_local_versionr._cmpkeyr
rrrrrr)rrmatchrrrr0s.

zVersion.__init__cCsdjtt|S)Nz)r2r3r-)rrrrr4szVersion.__repr__cCsg}|jjdkr$|jdj|jj|jdjdd|jjD|jjdk	rl|jdjdd|jjD|jjdk	r|jdj|jjd	|jjdk	r|jd
j|jjd	|jj	dk	r|jdjdjdd|jj	Ddj|S)
Nrz{0}!r?css|]}t|VqdS)N)r-)rRxrrrrTsz"Version.__str__..css|]}t|VqdS)N)r-)rRr\rrrrTsz.post{0}rz.dev{0}z+{0}css|]}t|VqdS)N)r-)rRr\rrrrTs)
r.r
rNr2joinrrrrr)rrPrrrr1s zVersion.__str__cCst|jdddS)N+rr)r-rD)rrrrr5
szVersion.publiccCsLg}|jjdkr$|jdj|jj|jdjdd|jjDdj|S)Nrz{0}!r?css|]}t|VqdS)N)r-)rRr\rrrrTsz'Version.base_version..r])r.r
rNr2r^r)rrPrrrr6s
zVersion.base_versioncCs$t|}d|kr |jdddSdS)Nr_r)r-rD)rZversion_stringrrrrsz
Version.localcCst|jjp|jjS)N)boolr.rr)rrrrr7!szVersion.is_prereleasecCst|jjS)N)r`r.r)rrrrr8%szVersion.is_postreleaseN)rrrrecompilerVERBOSE
IGNORECASErUr0r4r1r9r5r6rr7r8rrrrrs
#
cCsx|rZ|dkrd}|j}|dkr&d}n(|dkr4d}n|d
krBd	}n|dkrNd}|t|fS|rt|rtd}|t|fSdS)NrZalphaaZbetabr:rr<r>revrr)r:rr<)rgrh)rKrQ)ZletterZnumberrrrrX*s 
rXz[\._-]cCs$|dk	r tddtj|DSdS)zR
    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
    Ncss&|]}|js|jnt|VqdS)N)isdigitrKrQ)rRrHrrrrTRsz'_parse_local_version..)rO_local_version_seperatorsrD)rrrrrYLsrYcCsttttjddt|}|dkr@|dkr@|dk	r@t}n|dkrLt}|dkrZt}|dkrft}|dkrvt}ntdd|D}||||||fS)NcSs|dkS)Nrr)r\rrrr!`sz_cmpkey..css*|]"}t|tr|dfnt|fVqdS)r]N)r*rQr)rRrSrrrrTsz_cmpkey..)rOreversedlist	itertools	dropwhiler)r
rrrrrrrrrZWs&		
rZ)Z
__future__rrrcollectionsrmraZ_structuresr__all__
namedtuplerr
ValueErrorr
objectrr	rbrcrCrErIr/rrrXrjrYrZrrrrs.!
9k
packaging/__pycache__/version.cpython-36.pyc000064400000024426147205126200015022 0ustar003

9f$-@sddlmZmZmZddlZddlZddlZddlmZddddd	gZ	ej
d
ddd
dddgZddZGddde
ZGdddeZGdddeZejdejZddddddZddZddZdZGd ddeZd!d"Zejd#Zd$d%Zd&d'ZdS)()absolute_importdivisionprint_functionN)InfinityparseVersion
LegacyVersionInvalidVersionVERSION_PATTERN_VersionepochreleasedevprepostlocalcCs&yt|Stk
r t|SXdS)z
    Parse the given version string and return either a :class:`Version` object
    or a :class:`LegacyVersion` object depending on if the given version is
    a valid PEP 440 version or a legacy version.
    N)rr
r	)versionr/usr/lib/python3.6/version.pyrsc@seZdZdZdS)r
zF
    An invalid version was found, users should refer to PEP 440.
    N)__name__
__module____qualname____doc__rrrrr
$sc@sLeZdZddZddZddZddZd	d
ZddZd
dZ	ddZ
dS)_BaseVersioncCs
t|jS)N)hash_key)selfrrr__hash__,sz_BaseVersion.__hash__cCs|j|ddS)NcSs||kS)Nr)sorrr0sz%_BaseVersion.__lt__..)_compare)rotherrrr__lt__/sz_BaseVersion.__lt__cCs|j|ddS)NcSs||kS)Nr)rr rrrr!3sz%_BaseVersion.__le__..)r")rr#rrr__le__2sz_BaseVersion.__le__cCs|j|ddS)NcSs||kS)Nr)rr rrrr!6sz%_BaseVersion.__eq__..)r")rr#rrr__eq__5sz_BaseVersion.__eq__cCs|j|ddS)NcSs||kS)Nr)rr rrrr!9sz%_BaseVersion.__ge__..)r")rr#rrr__ge__8sz_BaseVersion.__ge__cCs|j|ddS)NcSs||kS)Nr)rr rrrr!<sz%_BaseVersion.__gt__..)r")rr#rrr__gt__;sz_BaseVersion.__gt__cCs|j|ddS)NcSs||kS)Nr)rr rrrr!?sz%_BaseVersion.__ne__..)r")rr#rrr__ne__>sz_BaseVersion.__ne__cCst|tstS||j|jS)N)
isinstancerNotImplementedr)rr#methodrrrr"As
z_BaseVersion._compareN)rrrrr$r%r&r'r(r)r"rrrrr*src@s`eZdZddZddZddZeddZed	d
ZeddZ	ed
dZ
eddZdS)r	cCst||_t|j|_dS)N)str_version_legacy_cmpkeyr)rrrrr__init__Js
zLegacyVersion.__init__cCs|jS)N)r.)rrrr__str__NszLegacyVersion.__str__cCsdjtt|S)Nz)formatreprr-)rrrr__repr__QszLegacyVersion.__repr__cCs|jS)N)r.)rrrrpublicTszLegacyVersion.publiccCs|jS)N)r.)rrrrbase_versionXszLegacyVersion.base_versioncCsdS)Nr)rrrrr\szLegacyVersion.localcCsdS)NFr)rrrr
is_prerelease`szLegacyVersion.is_prereleasecCsdS)NFr)rrrris_postreleasedszLegacyVersion.is_postreleaseN)rrrr0r1r4propertyr5r6rr7r8rrrrr	Hsz(\d+ | [a-z]+ | \.| -)czfinal-@)rpreview-rcrccsbxVtj|D]H}tj||}|s|dkr,q|dddkrJ|jdVqd|VqWdVdS)N.r
0123456789*z*final)_legacy_version_component_resplit_legacy_version_replacement_mapgetzfill)rpartrrr_parse_version_partsrsrIcCsd}g}xlt|jD]\}|jdrh|dkrJx|rH|ddkrH|jq.Wx|rf|ddkrf|jqLW|j|qWt|}||fS)	NrrBz*finalz*final-Z00000000rJrJ)rIlower
startswithpopappendtuple)rr
partsrHrrrr/s
r/a
    v?
    (?:
        (?:(?P[0-9]+)!)?                           # epoch
        (?P[0-9]+(?:\.[0-9]+)*)                  # release segment
        (?P
                                          # pre-release
            [-_\.]?
            (?P(a|b|c|rc|alpha|beta|pre|preview))
            [-_\.]?
            (?P[0-9]+)?
        )?
        (?P                                         # post release
            (?:-(?P[0-9]+))
            |
            (?:
                [-_\.]?
                (?Ppost|rev|r)
                [-_\.]?
                (?P[0-9]+)?
            )
        )?
        (?P                                          # dev release
            [-_\.]?
            (?Pdev)
            [-_\.]?
            (?P[0-9]+)?
        )?
    )
    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
c@s|eZdZejdedejejBZddZ	ddZ
ddZed	d
Z
eddZed
dZeddZeddZdS)rz^\s*z\s*$c	Cs|jj|}|stdj|t|jdr8t|jdndtdd|jdjdDt	|jd|jd	t	|jd
|jdp|jdt	|jd
|jdt
|jdd|_t|jj
|jj|jj|jj|jj|jj|_dS)NzInvalid version: '{0}'r
rcss|]}t|VqdS)N)int).0irrr	sz#Version.__init__..rr?Zpre_lZpre_nZpost_lZpost_n1Zpost_n2Zdev_lZdev_nr)r
rrrrr)_regexsearchr
r2rgrouprQrOrD_parse_letter_version_parse_local_versionr._cmpkeyr
rrrrrr)rrmatchrrrr0s.

zVersion.__init__cCsdjtt|S)Nz)r2r3r-)rrrrr4szVersion.__repr__cCsg}|jjdkr$|jdj|jj|jdjdd|jjD|jjdk	rl|jdjdd|jjD|jjdk	r|jdj|jjd	|jjdk	r|jd
j|jjd	|jj	dk	r|jdjdjdd|jj	Ddj|S)
Nrz{0}!r?css|]}t|VqdS)N)r-)rRxrrrrTsz"Version.__str__..css|]}t|VqdS)N)r-)rRr\rrrrTsz.post{0}rz.dev{0}z+{0}css|]}t|VqdS)N)r-)rRr\rrrrTs)
r.r
rNr2joinrrrrr)rrPrrrr1s zVersion.__str__cCst|jdddS)N+rr)r-rD)rrrrr5
szVersion.publiccCsLg}|jjdkr$|jdj|jj|jdjdd|jjDdj|S)Nrz{0}!r?css|]}t|VqdS)N)r-)rRr\rrrrTsz'Version.base_version..r])r.r
rNr2r^r)rrPrrrr6s
zVersion.base_versioncCs$t|}d|kr |jdddSdS)Nr_r)r-rD)rZversion_stringrrrrsz
Version.localcCst|jjp|jjS)N)boolr.rr)rrrrr7!szVersion.is_prereleasecCst|jjS)N)r`r.r)rrrrr8%szVersion.is_postreleaseN)rrrrecompilerVERBOSE
IGNORECASErUr0r4r1r9r5r6rr7r8rrrrrs
#
cCsx|rZ|dkrd}|j}|dkr&d}n(|dkr4d}n|d
krBd	}n|dkrNd}|t|fS|rt|rtd}|t|fSdS)NrZalphaaZbetabr:rr<r>revrr)r:rr<)rgrh)rKrQ)ZletterZnumberrrrrX*s 
rXz[\._-]cCs$|dk	r tddtj|DSdS)zR
    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
    Ncss&|]}|js|jnt|VqdS)N)isdigitrKrQ)rRrHrrrrTRsz'_parse_local_version..)rO_local_version_seperatorsrD)rrrrrYLsrYcCsttttjddt|}|dkr@|dkr@|dk	r@t}n|dkrLt}|dkrZt}|dkrft}|dkrvt}ntdd|D}||||||fS)NcSs|dkS)Nrr)r\rrrr!`sz_cmpkey..css*|]"}t|tr|dfnt|fVqdS)r]N)r*rQr)rRrSrrrrTsz_cmpkey..)rOreversedlist	itertools	dropwhiler)r
rrrrrrrrrZWs&		
rZ)Z
__future__rrrcollectionsrmraZ_structuresr__all__
namedtuplerr
ValueErrorr
objectrr	rbrcrCrErIr/rrrXrjrYrZrrrrs.!
9k
packaging/__about__.py000064400000001320147205126200010743 0ustar00# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

__all__ = [
    "__title__", "__summary__", "__uri__", "__version__", "__author__",
    "__email__", "__license__", "__copyright__",
]

__title__ = "packaging"
__summary__ = "Core utilities for Python packages"
__uri__ = "https://github.com/pypa/packaging"

__version__ = "16.8"

__author__ = "Donald Stufft and individual contributors"
__email__ = "donald@stufft.io"

__license__ = "BSD or Apache License, Version 2.0"
__copyright__ = "Copyright 2014-2016 %s" % __author__
packaging/__init__.py000064400000001001147205126200010570 0ustar00# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

from .__about__ import (
    __author__, __copyright__, __email__, __license__, __summary__, __title__,
    __uri__, __version__
)

__all__ = [
    "__title__", "__summary__", "__uri__", "__version__", "__author__",
    "__email__", "__license__", "__copyright__",
]
packaging/_compat.py000064400000001534147205126200010466 0ustar00# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

import sys


PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3

# flake8: noqa

if PY3:
    string_types = str,
else:
    string_types = basestring,


def with_metaclass(meta, *bases):
    """
    Create a base class with a metaclass.
    """
    # This requires a bit of explanation: the basic idea is to make a dummy
    # metaclass for one level of class instantiation that replaces itself with
    # the actual metaclass.
    class metaclass(meta):
        def __new__(cls, name, this_bases, d):
            return meta(name, bases, d)
    return type.__new__(metaclass, 'temporary_class', (), {})
packaging/_structures.py000064400000002610147205126200011422 0ustar00# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function


class Infinity(object):

    def __repr__(self):
        return "Infinity"

    def __hash__(self):
        return hash(repr(self))

    def __lt__(self, other):
        return False

    def __le__(self, other):
        return False

    def __eq__(self, other):
        return isinstance(other, self.__class__)

    def __ne__(self, other):
        return not isinstance(other, self.__class__)

    def __gt__(self, other):
        return True

    def __ge__(self, other):
        return True

    def __neg__(self):
        return NegativeInfinity

Infinity = Infinity()


class NegativeInfinity(object):

    def __repr__(self):
        return "-Infinity"

    def __hash__(self):
        return hash(repr(self))

    def __lt__(self, other):
        return True

    def __le__(self, other):
        return True

    def __eq__(self, other):
        return isinstance(other, self.__class__)

    def __ne__(self, other):
        return not isinstance(other, self.__class__)

    def __gt__(self, other):
        return False

    def __ge__(self, other):
        return False

    def __neg__(self):
        return Infinity

NegativeInfinity = NegativeInfinity()
packaging/markers.py000064400000020070147205126200010504 0ustar00# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

import operator
import os
import platform
import sys

from pkg_resources.extern.pyparsing import ParseException, ParseResults, stringStart, stringEnd
from pkg_resources.extern.pyparsing import ZeroOrMore, Group, Forward, QuotedString
from pkg_resources.extern.pyparsing import Literal as L  # noqa

from ._compat import string_types
from .specifiers import Specifier, InvalidSpecifier


__all__ = [
    "InvalidMarker", "UndefinedComparison", "UndefinedEnvironmentName",
    "Marker", "default_environment",
]


class InvalidMarker(ValueError):
    """
    An invalid marker was found, users should refer to PEP 508.
    """


class UndefinedComparison(ValueError):
    """
    An invalid operation was attempted on a value that doesn't support it.
    """


class UndefinedEnvironmentName(ValueError):
    """
    A name was attempted to be used that does not exist inside of the
    environment.
    """


class Node(object):

    def __init__(self, value):
        self.value = value

    def __str__(self):
        return str(self.value)

    def __repr__(self):
        return "<{0}({1!r})>".format(self.__class__.__name__, str(self))

    def serialize(self):
        raise NotImplementedError


class Variable(Node):

    def serialize(self):
        return str(self)


class Value(Node):

    def serialize(self):
        return '"{0}"'.format(self)


class Op(Node):

    def serialize(self):
        return str(self)


VARIABLE = (
    L("implementation_version") |
    L("platform_python_implementation") |
    L("implementation_name") |
    L("python_full_version") |
    L("platform_release") |
    L("platform_version") |
    L("platform_machine") |
    L("platform_system") |
    L("python_version") |
    L("sys_platform") |
    L("os_name") |
    L("os.name") |  # PEP-345
    L("sys.platform") |  # PEP-345
    L("platform.version") |  # PEP-345
    L("platform.machine") |  # PEP-345
    L("platform.python_implementation") |  # PEP-345
    L("python_implementation") |  # undocumented setuptools legacy
    L("extra")
)
ALIASES = {
    'os.name': 'os_name',
    'sys.platform': 'sys_platform',
    'platform.version': 'platform_version',
    'platform.machine': 'platform_machine',
    'platform.python_implementation': 'platform_python_implementation',
    'python_implementation': 'platform_python_implementation'
}
VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0])))

VERSION_CMP = (
    L("===") |
    L("==") |
    L(">=") |
    L("<=") |
    L("!=") |
    L("~=") |
    L(">") |
    L("<")
)

MARKER_OP = VERSION_CMP | L("not in") | L("in")
MARKER_OP.setParseAction(lambda s, l, t: Op(t[0]))

MARKER_VALUE = QuotedString("'") | QuotedString('"')
MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0]))

BOOLOP = L("and") | L("or")

MARKER_VAR = VARIABLE | MARKER_VALUE

MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR)
MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0]))

LPAREN = L("(").suppress()
RPAREN = L(")").suppress()

MARKER_EXPR = Forward()
MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN)
MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR)

MARKER = stringStart + MARKER_EXPR + stringEnd


def _coerce_parse_result(results):
    if isinstance(results, ParseResults):
        return [_coerce_parse_result(i) for i in results]
    else:
        return results


def _format_marker(marker, first=True):
    assert isinstance(marker, (list, tuple, string_types))

    # Sometimes we have a structure like [[...]] which is a single item list
    # where the single item is itself it's own list. In that case we want skip
    # the rest of this function so that we don't get extraneous () on the
    # outside.
    if (isinstance(marker, list) and len(marker) == 1 and
            isinstance(marker[0], (list, tuple))):
        return _format_marker(marker[0])

    if isinstance(marker, list):
        inner = (_format_marker(m, first=False) for m in marker)
        if first:
            return " ".join(inner)
        else:
            return "(" + " ".join(inner) + ")"
    elif isinstance(marker, tuple):
        return " ".join([m.serialize() for m in marker])
    else:
        return marker


_operators = {
    "in": lambda lhs, rhs: lhs in rhs,
    "not in": lambda lhs, rhs: lhs not in rhs,
    "<": operator.lt,
    "<=": operator.le,
    "==": operator.eq,
    "!=": operator.ne,
    ">=": operator.ge,
    ">": operator.gt,
}


def _eval_op(lhs, op, rhs):
    try:
        spec = Specifier("".join([op.serialize(), rhs]))
    except InvalidSpecifier:
        pass
    else:
        return spec.contains(lhs)

    oper = _operators.get(op.serialize())
    if oper is None:
        raise UndefinedComparison(
            "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs)
        )

    return oper(lhs, rhs)


_undefined = object()


def _get_env(environment, name):
    value = environment.get(name, _undefined)

    if value is _undefined:
        raise UndefinedEnvironmentName(
            "{0!r} does not exist in evaluation environment.".format(name)
        )

    return value


def _evaluate_markers(markers, environment):
    groups = [[]]

    for marker in markers:
        assert isinstance(marker, (list, tuple, string_types))

        if isinstance(marker, list):
            groups[-1].append(_evaluate_markers(marker, environment))
        elif isinstance(marker, tuple):
            lhs, op, rhs = marker

            if isinstance(lhs, Variable):
                lhs_value = _get_env(environment, lhs.value)
                rhs_value = rhs.value
            else:
                lhs_value = lhs.value
                rhs_value = _get_env(environment, rhs.value)

            groups[-1].append(_eval_op(lhs_value, op, rhs_value))
        else:
            assert marker in ["and", "or"]
            if marker == "or":
                groups.append([])

    return any(all(item) for item in groups)


def format_full_version(info):
    version = '{0.major}.{0.minor}.{0.micro}'.format(info)
    kind = info.releaselevel
    if kind != 'final':
        version += kind[0] + str(info.serial)
    return version


def default_environment():
    if hasattr(sys, 'implementation'):
        iver = format_full_version(sys.implementation.version)
        implementation_name = sys.implementation.name
    else:
        iver = '0'
        implementation_name = ''

    return {
        "implementation_name": implementation_name,
        "implementation_version": iver,
        "os_name": os.name,
        "platform_machine": platform.machine(),
        "platform_release": platform.release(),
        "platform_system": platform.system(),
        "platform_version": platform.version(),
        "python_full_version": platform.python_version(),
        "platform_python_implementation": platform.python_implementation(),
        "python_version": platform.python_version()[:3],
        "sys_platform": sys.platform,
    }


class Marker(object):

    def __init__(self, marker):
        try:
            self._markers = _coerce_parse_result(MARKER.parseString(marker))
        except ParseException as e:
            err_str = "Invalid marker: {0!r}, parse error at {1!r}".format(
                marker, marker[e.loc:e.loc + 8])
            raise InvalidMarker(err_str)

    def __str__(self):
        return _format_marker(self._markers)

    def __repr__(self):
        return "".format(str(self))

    def evaluate(self, environment=None):
        """Evaluate a marker.

        Return the boolean from evaluating the given marker against the
        environment. environment is an optional argument to override all or
        part of the determined environment.

        The environment is determined from the current Python process.
        """
        current_environment = default_environment()
        if environment is not None:
            current_environment.update(environment)

        return _evaluate_markers(self._markers, current_environment)
packaging/requirements.py000064400000010403147205126200011562 0ustar00# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

import string
import re

from pkg_resources.extern.pyparsing import stringStart, stringEnd, originalTextFor, ParseException
from pkg_resources.extern.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine
from pkg_resources.extern.pyparsing import Literal as L  # noqa
from pkg_resources.extern.six.moves.urllib import parse as urlparse

from .markers import MARKER_EXPR, Marker
from .specifiers import LegacySpecifier, Specifier, SpecifierSet


class InvalidRequirement(ValueError):
    """
    An invalid requirement was found, users should refer to PEP 508.
    """


ALPHANUM = Word(string.ascii_letters + string.digits)

LBRACKET = L("[").suppress()
RBRACKET = L("]").suppress()
LPAREN = L("(").suppress()
RPAREN = L(")").suppress()
COMMA = L(",").suppress()
SEMICOLON = L(";").suppress()
AT = L("@").suppress()

PUNCTUATION = Word("-_.")
IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM)
IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END))

NAME = IDENTIFIER("name")
EXTRA = IDENTIFIER

URI = Regex(r'[^ ]+')("url")
URL = (AT + URI)

EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA)
EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras")

VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE)
VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE)

VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY
VERSION_MANY = Combine(VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE),
                       joinString=",", adjacent=False)("_raw_spec")
_VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY))
_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or '')

VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier")
VERSION_SPEC.setParseAction(lambda s, l, t: t[1])

MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker")
MARKER_EXPR.setParseAction(
    lambda s, l, t: Marker(s[t._original_start:t._original_end])
)
MARKER_SEPERATOR = SEMICOLON
MARKER = MARKER_SEPERATOR + MARKER_EXPR

VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER)
URL_AND_MARKER = URL + Optional(MARKER)

NAMED_REQUIREMENT = \
    NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER)

REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd


class Requirement(object):
    """Parse a requirement.

    Parse a given requirement string into its parts, such as name, specifier,
    URL, and extras. Raises InvalidRequirement on a badly-formed requirement
    string.
    """

    # TODO: Can we test whether something is contained within a requirement?
    #       If so how do we do that? Do we need to test against the _name_ of
    #       the thing as well as the version? What about the markers?
    # TODO: Can we normalize the name and extra name?

    def __init__(self, requirement_string):
        try:
            req = REQUIREMENT.parseString(requirement_string)
        except ParseException as e:
            raise InvalidRequirement(
                "Invalid requirement, parse error at \"{0!r}\"".format(
                    requirement_string[e.loc:e.loc + 8]))

        self.name = req.name
        if req.url:
            parsed_url = urlparse.urlparse(req.url)
            if not (parsed_url.scheme and parsed_url.netloc) or (
                    not parsed_url.scheme and not parsed_url.netloc):
                raise InvalidRequirement("Invalid URL given")
            self.url = req.url
        else:
            self.url = None
        self.extras = set(req.extras.asList() if req.extras else [])
        self.specifier = SpecifierSet(req.specifier)
        self.marker = req.marker if req.marker else None

    def __str__(self):
        parts = [self.name]

        if self.extras:
            parts.append("[{0}]".format(",".join(sorted(self.extras))))

        if self.specifier:
            parts.append(str(self.specifier))

        if self.url:
            parts.append("@ {0}".format(self.url))

        if self.marker:
            parts.append("; {0}".format(self.marker))

        return "".join(parts)

    def __repr__(self):
        return "".format(str(self))
packaging/specifiers.py000064400000066571147205126200011214 0ustar00# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

import abc
import functools
import itertools
import re

from ._compat import string_types, with_metaclass
from .version import Version, LegacyVersion, parse


class InvalidSpecifier(ValueError):
    """
    An invalid specifier was found, users should refer to PEP 440.
    """


class BaseSpecifier(with_metaclass(abc.ABCMeta, object)):

    @abc.abstractmethod
    def __str__(self):
        """
        Returns the str representation of this Specifier like object. This
        should be representative of the Specifier itself.
        """

    @abc.abstractmethod
    def __hash__(self):
        """
        Returns a hash value for this Specifier like object.
        """

    @abc.abstractmethod
    def __eq__(self, other):
        """
        Returns a boolean representing whether or not the two Specifier like
        objects are equal.
        """

    @abc.abstractmethod
    def __ne__(self, other):
        """
        Returns a boolean representing whether or not the two Specifier like
        objects are not equal.
        """

    @abc.abstractproperty
    def prereleases(self):
        """
        Returns whether or not pre-releases as a whole are allowed by this
        specifier.
        """

    @prereleases.setter
    def prereleases(self, value):
        """
        Sets whether or not pre-releases as a whole are allowed by this
        specifier.
        """

    @abc.abstractmethod
    def contains(self, item, prereleases=None):
        """
        Determines if the given item is contained within this specifier.
        """

    @abc.abstractmethod
    def filter(self, iterable, prereleases=None):
        """
        Takes an iterable of items and filters them so that only items which
        are contained within this specifier are allowed in it.
        """


class _IndividualSpecifier(BaseSpecifier):

    _operators = {}

    def __init__(self, spec="", prereleases=None):
        match = self._regex.search(spec)
        if not match:
            raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec))

        self._spec = (
            match.group("operator").strip(),
            match.group("version").strip(),
        )

        # Store whether or not this Specifier should accept prereleases
        self._prereleases = prereleases

    def __repr__(self):
        pre = (
            ", prereleases={0!r}".format(self.prereleases)
            if self._prereleases is not None
            else ""
        )

        return "<{0}({1!r}{2})>".format(
            self.__class__.__name__,
            str(self),
            pre,
        )

    def __str__(self):
        return "{0}{1}".format(*self._spec)

    def __hash__(self):
        return hash(self._spec)

    def __eq__(self, other):
        if isinstance(other, string_types):
            try:
                other = self.__class__(other)
            except InvalidSpecifier:
                return NotImplemented
        elif not isinstance(other, self.__class__):
            return NotImplemented

        return self._spec == other._spec

    def __ne__(self, other):
        if isinstance(other, string_types):
            try:
                other = self.__class__(other)
            except InvalidSpecifier:
                return NotImplemented
        elif not isinstance(other, self.__class__):
            return NotImplemented

        return self._spec != other._spec

    def _get_operator(self, op):
        return getattr(self, "_compare_{0}".format(self._operators[op]))

    def _coerce_version(self, version):
        if not isinstance(version, (LegacyVersion, Version)):
            version = parse(version)
        return version

    @property
    def operator(self):
        return self._spec[0]

    @property
    def version(self):
        return self._spec[1]

    @property
    def prereleases(self):
        return self._prereleases

    @prereleases.setter
    def prereleases(self, value):
        self._prereleases = value

    def __contains__(self, item):
        return self.contains(item)

    def contains(self, item, prereleases=None):
        # Determine if prereleases are to be allowed or not.
        if prereleases is None:
            prereleases = self.prereleases

        # Normalize item to a Version or LegacyVersion, this allows us to have
        # a shortcut for ``"2.0" in Specifier(">=2")
        item = self._coerce_version(item)

        # Determine if we should be supporting prereleases in this specifier
        # or not, if we do not support prereleases than we can short circuit
        # logic if this version is a prereleases.
        if item.is_prerelease and not prereleases:
            return False

        # Actually do the comparison to determine if this item is contained
        # within this Specifier or not.
        return self._get_operator(self.operator)(item, self.version)

    def filter(self, iterable, prereleases=None):
        yielded = False
        found_prereleases = []

        kw = {"prereleases": prereleases if prereleases is not None else True}

        # Attempt to iterate over all the values in the iterable and if any of
        # them match, yield them.
        for version in iterable:
            parsed_version = self._coerce_version(version)

            if self.contains(parsed_version, **kw):
                # If our version is a prerelease, and we were not set to allow
                # prereleases, then we'll store it for later incase nothing
                # else matches this specifier.
                if (parsed_version.is_prerelease and not
                        (prereleases or self.prereleases)):
                    found_prereleases.append(version)
                # Either this is not a prerelease, or we should have been
                # accepting prereleases from the begining.
                else:
                    yielded = True
                    yield version

        # Now that we've iterated over everything, determine if we've yielded
        # any values, and if we have not and we have any prereleases stored up
        # then we will go ahead and yield the prereleases.
        if not yielded and found_prereleases:
            for version in found_prereleases:
                yield version


class LegacySpecifier(_IndividualSpecifier):

    _regex_str = (
        r"""
        (?P(==|!=|<=|>=|<|>))
        \s*
        (?P
            [^,;\s)]* # Since this is a "legacy" specifier, and the version
                      # string can be just about anything, we match everything
                      # except for whitespace, a semi-colon for marker support,
                      # a closing paren since versions can be enclosed in
                      # them, and a comma since it's a version separator.
        )
        """
    )

    _regex = re.compile(
        r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)

    _operators = {
        "==": "equal",
        "!=": "not_equal",
        "<=": "less_than_equal",
        ">=": "greater_than_equal",
        "<": "less_than",
        ">": "greater_than",
    }

    def _coerce_version(self, version):
        if not isinstance(version, LegacyVersion):
            version = LegacyVersion(str(version))
        return version

    def _compare_equal(self, prospective, spec):
        return prospective == self._coerce_version(spec)

    def _compare_not_equal(self, prospective, spec):
        return prospective != self._coerce_version(spec)

    def _compare_less_than_equal(self, prospective, spec):
        return prospective <= self._coerce_version(spec)

    def _compare_greater_than_equal(self, prospective, spec):
        return prospective >= self._coerce_version(spec)

    def _compare_less_than(self, prospective, spec):
        return prospective < self._coerce_version(spec)

    def _compare_greater_than(self, prospective, spec):
        return prospective > self._coerce_version(spec)


def _require_version_compare(fn):
    @functools.wraps(fn)
    def wrapped(self, prospective, spec):
        if not isinstance(prospective, Version):
            return False
        return fn(self, prospective, spec)
    return wrapped


class Specifier(_IndividualSpecifier):

    _regex_str = (
        r"""
        (?P(~=|==|!=|<=|>=|<|>|===))
        (?P
            (?:
                # The identity operators allow for an escape hatch that will
                # do an exact string match of the version you wish to install.
                # This will not be parsed by PEP 440 and we cannot determine
                # any semantic meaning from it. This operator is discouraged
                # but included entirely as an escape hatch.
                (?<====)  # Only match for the identity operator
                \s*
                [^\s]*    # We just match everything, except for whitespace
                          # since we are only testing for strict identity.
            )
            |
            (?:
                # The (non)equality operators allow for wild card and local
                # versions to be specified so we have to define these two
                # operators separately to enable that.
                (?<===|!=)            # Only match for equals and not equals

                \s*
                v?
                (?:[0-9]+!)?          # epoch
                [0-9]+(?:\.[0-9]+)*   # release
                (?:                   # pre release
                    [-_\.]?
                    (a|b|c|rc|alpha|beta|pre|preview)
                    [-_\.]?
                    [0-9]*
                )?
                (?:                   # post release
                    (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
                )?

                # You cannot use a wild card and a dev or local version
                # together so group them with a | and make them optional.
                (?:
                    (?:[-_\.]?dev[-_\.]?[0-9]*)?         # dev release
                    (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local
                    |
                    \.\*  # Wild card syntax of .*
                )?
            )
            |
            (?:
                # The compatible operator requires at least two digits in the
                # release segment.
                (?<=~=)               # Only match for the compatible operator

                \s*
                v?
                (?:[0-9]+!)?          # epoch
                [0-9]+(?:\.[0-9]+)+   # release  (We have a + instead of a *)
                (?:                   # pre release
                    [-_\.]?
                    (a|b|c|rc|alpha|beta|pre|preview)
                    [-_\.]?
                    [0-9]*
                )?
                (?:                                   # post release
                    (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
                )?
                (?:[-_\.]?dev[-_\.]?[0-9]*)?          # dev release
            )
            |
            (?:
                # All other operators only allow a sub set of what the
                # (non)equality operators do. Specifically they do not allow
                # local versions to be specified nor do they allow the prefix
                # matching wild cards.
                (?=": "greater_than_equal",
        "<": "less_than",
        ">": "greater_than",
        "===": "arbitrary",
    }

    @_require_version_compare
    def _compare_compatible(self, prospective, spec):
        # Compatible releases have an equivalent combination of >= and ==. That
        # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to
        # implement this in terms of the other specifiers instead of
        # implementing it ourselves. The only thing we need to do is construct
        # the other specifiers.

        # We want everything but the last item in the version, but we want to
        # ignore post and dev releases and we want to treat the pre-release as
        # it's own separate segment.
        prefix = ".".join(
            list(
                itertools.takewhile(
                    lambda x: (not x.startswith("post") and not
                               x.startswith("dev")),
                    _version_split(spec),
                )
            )[:-1]
        )

        # Add the prefix notation to the end of our string
        prefix += ".*"

        return (self._get_operator(">=")(prospective, spec) and
                self._get_operator("==")(prospective, prefix))

    @_require_version_compare
    def _compare_equal(self, prospective, spec):
        # We need special logic to handle prefix matching
        if spec.endswith(".*"):
            # In the case of prefix matching we want to ignore local segment.
            prospective = Version(prospective.public)
            # Split the spec out by dots, and pretend that there is an implicit
            # dot in between a release segment and a pre-release segment.
            spec = _version_split(spec[:-2])  # Remove the trailing .*

            # Split the prospective version out by dots, and pretend that there
            # is an implicit dot in between a release segment and a pre-release
            # segment.
            prospective = _version_split(str(prospective))

            # Shorten the prospective version to be the same length as the spec
            # so that we can determine if the specifier is a prefix of the
            # prospective version or not.
            prospective = prospective[:len(spec)]

            # Pad out our two sides with zeros so that they both equal the same
            # length.
            spec, prospective = _pad_version(spec, prospective)
        else:
            # Convert our spec string into a Version
            spec = Version(spec)

            # If the specifier does not have a local segment, then we want to
            # act as if the prospective version also does not have a local
            # segment.
            if not spec.local:
                prospective = Version(prospective.public)

        return prospective == spec

    @_require_version_compare
    def _compare_not_equal(self, prospective, spec):
        return not self._compare_equal(prospective, spec)

    @_require_version_compare
    def _compare_less_than_equal(self, prospective, spec):
        return prospective <= Version(spec)

    @_require_version_compare
    def _compare_greater_than_equal(self, prospective, spec):
        return prospective >= Version(spec)

    @_require_version_compare
    def _compare_less_than(self, prospective, spec):
        # Convert our spec to a Version instance, since we'll want to work with
        # it as a version.
        spec = Version(spec)

        # Check to see if the prospective version is less than the spec
        # version. If it's not we can short circuit and just return False now
        # instead of doing extra unneeded work.
        if not prospective < spec:
            return False

        # This special case is here so that, unless the specifier itself
        # includes is a pre-release version, that we do not accept pre-release
        # versions for the version mentioned in the specifier (e.g. <3.1 should
        # not match 3.1.dev0, but should match 3.0.dev0).
        if not spec.is_prerelease and prospective.is_prerelease:
            if Version(prospective.base_version) == Version(spec.base_version):
                return False

        # If we've gotten to here, it means that prospective version is both
        # less than the spec version *and* it's not a pre-release of the same
        # version in the spec.
        return True

    @_require_version_compare
    def _compare_greater_than(self, prospective, spec):
        # Convert our spec to a Version instance, since we'll want to work with
        # it as a version.
        spec = Version(spec)

        # Check to see if the prospective version is greater than the spec
        # version. If it's not we can short circuit and just return False now
        # instead of doing extra unneeded work.
        if not prospective > spec:
            return False

        # This special case is here so that, unless the specifier itself
        # includes is a post-release version, that we do not accept
        # post-release versions for the version mentioned in the specifier
        # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0).
        if not spec.is_postrelease and prospective.is_postrelease:
            if Version(prospective.base_version) == Version(spec.base_version):
                return False

        # Ensure that we do not allow a local version of the version mentioned
        # in the specifier, which is techincally greater than, to match.
        if prospective.local is not None:
            if Version(prospective.base_version) == Version(spec.base_version):
                return False

        # If we've gotten to here, it means that prospective version is both
        # greater than the spec version *and* it's not a pre-release of the
        # same version in the spec.
        return True

    def _compare_arbitrary(self, prospective, spec):
        return str(prospective).lower() == str(spec).lower()

    @property
    def prereleases(self):
        # If there is an explicit prereleases set for this, then we'll just
        # blindly use that.
        if self._prereleases is not None:
            return self._prereleases

        # Look at all of our specifiers and determine if they are inclusive
        # operators, and if they are if they are including an explicit
        # prerelease.
        operator, version = self._spec
        if operator in ["==", ">=", "<=", "~=", "==="]:
            # The == specifier can include a trailing .*, if it does we
            # want to remove before parsing.
            if operator == "==" and version.endswith(".*"):
                version = version[:-2]

            # Parse the version, and if it is a pre-release than this
            # specifier allows pre-releases.
            if parse(version).is_prerelease:
                return True

        return False

    @prereleases.setter
    def prereleases(self, value):
        self._prereleases = value


_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$")


def _version_split(version):
    result = []
    for item in version.split("."):
        match = _prefix_regex.search(item)
        if match:
            result.extend(match.groups())
        else:
            result.append(item)
    return result


def _pad_version(left, right):
    left_split, right_split = [], []

    # Get the release segment of our versions
    left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left)))
    right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right)))

    # Get the rest of our versions
    left_split.append(left[len(left_split[0]):])
    right_split.append(right[len(right_split[0]):])

    # Insert our padding
    left_split.insert(
        1,
        ["0"] * max(0, len(right_split[0]) - len(left_split[0])),
    )
    right_split.insert(
        1,
        ["0"] * max(0, len(left_split[0]) - len(right_split[0])),
    )

    return (
        list(itertools.chain(*left_split)),
        list(itertools.chain(*right_split)),
    )


class SpecifierSet(BaseSpecifier):

    def __init__(self, specifiers="", prereleases=None):
        # Split on , to break each indidivual specifier into it's own item, and
        # strip each item to remove leading/trailing whitespace.
        specifiers = [s.strip() for s in specifiers.split(",") if s.strip()]

        # Parsed each individual specifier, attempting first to make it a
        # Specifier and falling back to a LegacySpecifier.
        parsed = set()
        for specifier in specifiers:
            try:
                parsed.add(Specifier(specifier))
            except InvalidSpecifier:
                parsed.add(LegacySpecifier(specifier))

        # Turn our parsed specifiers into a frozen set and save them for later.
        self._specs = frozenset(parsed)

        # Store our prereleases value so we can use it later to determine if
        # we accept prereleases or not.
        self._prereleases = prereleases

    def __repr__(self):
        pre = (
            ", prereleases={0!r}".format(self.prereleases)
            if self._prereleases is not None
            else ""
        )

        return "".format(str(self), pre)

    def __str__(self):
        return ",".join(sorted(str(s) for s in self._specs))

    def __hash__(self):
        return hash(self._specs)

    def __and__(self, other):
        if isinstance(other, string_types):
            other = SpecifierSet(other)
        elif not isinstance(other, SpecifierSet):
            return NotImplemented

        specifier = SpecifierSet()
        specifier._specs = frozenset(self._specs | other._specs)

        if self._prereleases is None and other._prereleases is not None:
            specifier._prereleases = other._prereleases
        elif self._prereleases is not None and other._prereleases is None:
            specifier._prereleases = self._prereleases
        elif self._prereleases == other._prereleases:
            specifier._prereleases = self._prereleases
        else:
            raise ValueError(
                "Cannot combine SpecifierSets with True and False prerelease "
                "overrides."
            )

        return specifier

    def __eq__(self, other):
        if isinstance(other, string_types):
            other = SpecifierSet(other)
        elif isinstance(other, _IndividualSpecifier):
            other = SpecifierSet(str(other))
        elif not isinstance(other, SpecifierSet):
            return NotImplemented

        return self._specs == other._specs

    def __ne__(self, other):
        if isinstance(other, string_types):
            other = SpecifierSet(other)
        elif isinstance(other, _IndividualSpecifier):
            other = SpecifierSet(str(other))
        elif not isinstance(other, SpecifierSet):
            return NotImplemented

        return self._specs != other._specs

    def __len__(self):
        return len(self._specs)

    def __iter__(self):
        return iter(self._specs)

    @property
    def prereleases(self):
        # If we have been given an explicit prerelease modifier, then we'll
        # pass that through here.
        if self._prereleases is not None:
            return self._prereleases

        # If we don't have any specifiers, and we don't have a forced value,
        # then we'll just return None since we don't know if this should have
        # pre-releases or not.
        if not self._specs:
            return None

        # Otherwise we'll see if any of the given specifiers accept
        # prereleases, if any of them do we'll return True, otherwise False.
        return any(s.prereleases for s in self._specs)

    @prereleases.setter
    def prereleases(self, value):
        self._prereleases = value

    def __contains__(self, item):
        return self.contains(item)

    def contains(self, item, prereleases=None):
        # Ensure that our item is a Version or LegacyVersion instance.
        if not isinstance(item, (LegacyVersion, Version)):
            item = parse(item)

        # Determine if we're forcing a prerelease or not, if we're not forcing
        # one for this particular filter call, then we'll use whatever the
        # SpecifierSet thinks for whether or not we should support prereleases.
        if prereleases is None:
            prereleases = self.prereleases

        # We can determine if we're going to allow pre-releases by looking to
        # see if any of the underlying items supports them. If none of them do
        # and this item is a pre-release then we do not allow it and we can
        # short circuit that here.
        # Note: This means that 1.0.dev1 would not be contained in something
        #       like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0
        if not prereleases and item.is_prerelease:
            return False

        # We simply dispatch to the underlying specs here to make sure that the
        # given version is contained within all of them.
        # Note: This use of all() here means that an empty set of specifiers
        #       will always return True, this is an explicit design decision.
        return all(
            s.contains(item, prereleases=prereleases)
            for s in self._specs
        )

    def filter(self, iterable, prereleases=None):
        # Determine if we're forcing a prerelease or not, if we're not forcing
        # one for this particular filter call, then we'll use whatever the
        # SpecifierSet thinks for whether or not we should support prereleases.
        if prereleases is None:
            prereleases = self.prereleases

        # If we have any specifiers, then we want to wrap our iterable in the
        # filter method for each one, this will act as a logical AND amongst
        # each specifier.
        if self._specs:
            for spec in self._specs:
                iterable = spec.filter(iterable, prereleases=bool(prereleases))
            return iterable
        # If we do not have any specifiers, then we need to have a rough filter
        # which will filter out any pre-releases, unless there are no final
        # releases, and which will filter out LegacyVersion in general.
        else:
            filtered = []
            found_prereleases = []

            for item in iterable:
                # Ensure that we some kind of Version class for this item.
                if not isinstance(item, (LegacyVersion, Version)):
                    parsed_version = parse(item)
                else:
                    parsed_version = item

                # Filter out any item which is parsed as a LegacyVersion
                if isinstance(parsed_version, LegacyVersion):
                    continue

                # Store any item which is a pre-release for later unless we've
                # already found a final version or we are accepting prereleases
                if parsed_version.is_prerelease and not prereleases:
                    if not filtered:
                        found_prereleases.append(item)
                else:
                    filtered.append(item)

            # If we've found no items except for pre-releases, then we'll go
            # ahead and use the pre-releases
            if not filtered and found_prereleases and prereleases is None:
                return found_prereleases

            return filtered
packaging/utils.py000064400000000645147205126200010206 0ustar00# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

import re


_canonicalize_regex = re.compile(r"[-_.]+")


def canonicalize_name(name):
    # This is taken from PEP 503.
    return _canonicalize_regex.sub("-", name).lower()
packaging/version.py000064400000026444147205126200010540 0ustar00# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function

import collections
import itertools
import re

from ._structures import Infinity


__all__ = [
    "parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"
]


_Version = collections.namedtuple(
    "_Version",
    ["epoch", "release", "dev", "pre", "post", "local"],
)


def parse(version):
    """
    Parse the given version string and return either a :class:`Version` object
    or a :class:`LegacyVersion` object depending on if the given version is
    a valid PEP 440 version or a legacy version.
    """
    try:
        return Version(version)
    except InvalidVersion:
        return LegacyVersion(version)


class InvalidVersion(ValueError):
    """
    An invalid version was found, users should refer to PEP 440.
    """


class _BaseVersion(object):

    def __hash__(self):
        return hash(self._key)

    def __lt__(self, other):
        return self._compare(other, lambda s, o: s < o)

    def __le__(self, other):
        return self._compare(other, lambda s, o: s <= o)

    def __eq__(self, other):
        return self._compare(other, lambda s, o: s == o)

    def __ge__(self, other):
        return self._compare(other, lambda s, o: s >= o)

    def __gt__(self, other):
        return self._compare(other, lambda s, o: s > o)

    def __ne__(self, other):
        return self._compare(other, lambda s, o: s != o)

    def _compare(self, other, method):
        if not isinstance(other, _BaseVersion):
            return NotImplemented

        return method(self._key, other._key)


class LegacyVersion(_BaseVersion):

    def __init__(self, version):
        self._version = str(version)
        self._key = _legacy_cmpkey(self._version)

    def __str__(self):
        return self._version

    def __repr__(self):
        return "".format(repr(str(self)))

    @property
    def public(self):
        return self._version

    @property
    def base_version(self):
        return self._version

    @property
    def local(self):
        return None

    @property
    def is_prerelease(self):
        return False

    @property
    def is_postrelease(self):
        return False


_legacy_version_component_re = re.compile(
    r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE,
)

_legacy_version_replacement_map = {
    "pre": "c", "preview": "c", "-": "final-", "rc": "c", "dev": "@",
}


def _parse_version_parts(s):
    for part in _legacy_version_component_re.split(s):
        part = _legacy_version_replacement_map.get(part, part)

        if not part or part == ".":
            continue

        if part[:1] in "0123456789":
            # pad for numeric comparison
            yield part.zfill(8)
        else:
            yield "*" + part

    # ensure that alpha/beta/candidate are before final
    yield "*final"


def _legacy_cmpkey(version):
    # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch
    # greater than or equal to 0. This will effectively put the LegacyVersion,
    # which uses the defacto standard originally implemented by setuptools,
    # as before all PEP 440 versions.
    epoch = -1

    # This scheme is taken from pkg_resources.parse_version setuptools prior to
    # it's adoption of the packaging library.
    parts = []
    for part in _parse_version_parts(version.lower()):
        if part.startswith("*"):
            # remove "-" before a prerelease tag
            if part < "*final":
                while parts and parts[-1] == "*final-":
                    parts.pop()

            # remove trailing zeros from each series of numeric parts
            while parts and parts[-1] == "00000000":
                parts.pop()

        parts.append(part)
    parts = tuple(parts)

    return epoch, parts

# Deliberately not anchored to the start and end of the string, to make it
# easier for 3rd party code to reuse
VERSION_PATTERN = r"""
    v?
    (?:
        (?:(?P[0-9]+)!)?                           # epoch
        (?P[0-9]+(?:\.[0-9]+)*)                  # release segment
        (?P
                                          # pre-release
            [-_\.]?
            (?P(a|b|c|rc|alpha|beta|pre|preview))
            [-_\.]?
            (?P[0-9]+)?
        )?
        (?P                                         # post release
            (?:-(?P[0-9]+))
            |
            (?:
                [-_\.]?
                (?Ppost|rev|r)
                [-_\.]?
                (?P[0-9]+)?
            )
        )?
        (?P                                          # dev release
            [-_\.]?
            (?Pdev)
            [-_\.]?
            (?P[0-9]+)?
        )?
    )
    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
"""


class Version(_BaseVersion):

    _regex = re.compile(
        r"^\s*" + VERSION_PATTERN + r"\s*$",
        re.VERBOSE | re.IGNORECASE,
    )

    def __init__(self, version):
        # Validate the version and parse it into pieces
        match = self._regex.search(version)
        if not match:
            raise InvalidVersion("Invalid version: '{0}'".format(version))

        # Store the parsed out pieces of the version
        self._version = _Version(
            epoch=int(match.group("epoch")) if match.group("epoch") else 0,
            release=tuple(int(i) for i in match.group("release").split(".")),
            pre=_parse_letter_version(
                match.group("pre_l"),
                match.group("pre_n"),
            ),
            post=_parse_letter_version(
                match.group("post_l"),
                match.group("post_n1") or match.group("post_n2"),
            ),
            dev=_parse_letter_version(
                match.group("dev_l"),
                match.group("dev_n"),
            ),
            local=_parse_local_version(match.group("local")),
        )

        # Generate a key which will be used for sorting
        self._key = _cmpkey(
            self._version.epoch,
            self._version.release,
            self._version.pre,
            self._version.post,
            self._version.dev,
            self._version.local,
        )

    def __repr__(self):
        return "".format(repr(str(self)))

    def __str__(self):
        parts = []

        # Epoch
        if self._version.epoch != 0:
            parts.append("{0}!".format(self._version.epoch))

        # Release segment
        parts.append(".".join(str(x) for x in self._version.release))

        # Pre-release
        if self._version.pre is not None:
            parts.append("".join(str(x) for x in self._version.pre))

        # Post-release
        if self._version.post is not None:
            parts.append(".post{0}".format(self._version.post[1]))

        # Development release
        if self._version.dev is not None:
            parts.append(".dev{0}".format(self._version.dev[1]))

        # Local version segment
        if self._version.local is not None:
            parts.append(
                "+{0}".format(".".join(str(x) for x in self._version.local))
            )

        return "".join(parts)

    @property
    def public(self):
        return str(self).split("+", 1)[0]

    @property
    def base_version(self):
        parts = []

        # Epoch
        if self._version.epoch != 0:
            parts.append("{0}!".format(self._version.epoch))

        # Release segment
        parts.append(".".join(str(x) for x in self._version.release))

        return "".join(parts)

    @property
    def local(self):
        version_string = str(self)
        if "+" in version_string:
            return version_string.split("+", 1)[1]

    @property
    def is_prerelease(self):
        return bool(self._version.dev or self._version.pre)

    @property
    def is_postrelease(self):
        return bool(self._version.post)


def _parse_letter_version(letter, number):
    if letter:
        # We consider there to be an implicit 0 in a pre-release if there is
        # not a numeral associated with it.
        if number is None:
            number = 0

        # We normalize any letters to their lower case form
        letter = letter.lower()

        # We consider some words to be alternate spellings of other words and
        # in those cases we want to normalize the spellings to our preferred
        # spelling.
        if letter == "alpha":
            letter = "a"
        elif letter == "beta":
            letter = "b"
        elif letter in ["c", "pre", "preview"]:
            letter = "rc"
        elif letter in ["rev", "r"]:
            letter = "post"

        return letter, int(number)
    if not letter and number:
        # We assume if we are given a number, but we are not given a letter
        # then this is using the implicit post release syntax (e.g. 1.0-1)
        letter = "post"

        return letter, int(number)


_local_version_seperators = re.compile(r"[\._-]")


def _parse_local_version(local):
    """
    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
    """
    if local is not None:
        return tuple(
            part.lower() if not part.isdigit() else int(part)
            for part in _local_version_seperators.split(local)
        )


def _cmpkey(epoch, release, pre, post, dev, local):
    # When we compare a release version, we want to compare it with all of the
    # trailing zeros removed. So we'll use a reverse the list, drop all the now
    # leading zeros until we come to something non zero, then take the rest
    # re-reverse it back into the correct order and make it a tuple and use
    # that for our sorting key.
    release = tuple(
        reversed(list(
            itertools.dropwhile(
                lambda x: x == 0,
                reversed(release),
            )
        ))
    )

    # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
    # We'll do this by abusing the pre segment, but we _only_ want to do this
    # if there is not a pre or a post segment. If we have one of those then
    # the normal sorting rules will handle this case correctly.
    if pre is None and post is None and dev is not None:
        pre = -Infinity
    # Versions without a pre-release (except as noted above) should sort after
    # those with one.
    elif pre is None:
        pre = Infinity

    # Versions without a post segment should sort before those with one.
    if post is None:
        post = -Infinity

    # Versions without a development segment should sort after those with one.
    if dev is None:
        dev = Infinity

    if local is None:
        # Versions without a local segment should sort before those with one.
        local = -Infinity
    else:
        # Versions with a local segment need that segment parsed to implement
        # the sorting rules in PEP440.
        # - Alpha numeric segments sort before numeric segments
        # - Alpha numeric segments sort lexicographically
        # - Numeric segments sort numerically
        # - Shorter versions sort before longer versions when the prefixes
        #   match exactly
        local = tuple(
            (i, "") if isinstance(i, int) else (-Infinity, i)
            for i in local
        )

    return epoch, release, pre, post, dev, local
__init__.py000064400000000000147205126200006642 0ustar00appdirs.py000064400000053546147205126200006574 0ustar00#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2005-2010 ActiveState Software Inc.
# Copyright (c) 2013 Eddy Petrișor

"""Utilities for determining application-specific dirs.

See  for details and usage.
"""
# Dev Notes:
# - MSDN on where to store app data files:
#   http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120
# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html
# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html

__version_info__ = (1, 4, 0)
__version__ = '.'.join(map(str, __version_info__))


import sys
import os

PY3 = sys.version_info[0] == 3

if PY3:
    unicode = str

if sys.platform.startswith('java'):
    import platform
    os_name = platform.java_ver()[3][0]
    if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc.
        system = 'win32'
    elif os_name.startswith('Mac'): # "Mac OS X", etc.
        system = 'darwin'
    else: # "Linux", "SunOS", "FreeBSD", etc.
        # Setting this to "linux2" is not ideal, but only Windows or Mac
        # are actually checked for and the rest of the module expects
        # *sys.platform* style strings.
        system = 'linux2'
else:
    system = sys.platform



def user_data_dir(appname=None, appauthor=None, version=None, roaming=False):
    r"""Return full path to the user-specific data dir for this application.

        "appname" is the name of application.
            If None, just the system directory is returned.
        "appauthor" (only used on Windows) is the name of the
            appauthor or distributing body for this application. Typically
            it is the owning company name. This falls back to appname. You may
            pass False to disable it.
        "version" is an optional version path element to append to the
            path. You might want to use this if you want multiple versions
            of your app to be able to run independently. If used, this
            would typically be ".".
            Only applied when appname is present.
        "roaming" (boolean, default False) can be set True to use the Windows
            roaming appdata directory. That means that for users on a Windows
            network setup for roaming profiles, this user data will be
            sync'd on login. See
            
            for a discussion of issues.

    Typical user data directories are:
        Mac OS X:               ~/Library/Application Support/
        Unix:                   ~/.local/share/    # or in $XDG_DATA_HOME, if defined
        Win XP (not roaming):   C:\Documents and Settings\\Application Data\\
        Win XP (roaming):       C:\Documents and Settings\\Local Settings\Application Data\\
        Win 7  (not roaming):   C:\Users\\AppData\Local\\
        Win 7  (roaming):       C:\Users\\AppData\Roaming\\

    For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
    That means, by default "~/.local/share/".
    """
    if system == "win32":
        if appauthor is None:
            appauthor = appname
        const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA"
        path = os.path.normpath(_get_win_folder(const))
        if appname:
            if appauthor is not False:
                path = os.path.join(path, appauthor, appname)
            else:
                path = os.path.join(path, appname)
    elif system == 'darwin':
        path = os.path.expanduser('~/Library/Application Support/')
        if appname:
            path = os.path.join(path, appname)
    else:
        path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share"))
        if appname:
            path = os.path.join(path, appname)
    if appname and version:
        path = os.path.join(path, version)
    return path


def site_data_dir(appname=None, appauthor=None, version=None, multipath=False):
    """Return full path to the user-shared data dir for this application.

        "appname" is the name of application.
            If None, just the system directory is returned.
        "appauthor" (only used on Windows) is the name of the
            appauthor or distributing body for this application. Typically
            it is the owning company name. This falls back to appname. You may
            pass False to disable it.
        "version" is an optional version path element to append to the
            path. You might want to use this if you want multiple versions
            of your app to be able to run independently. If used, this
            would typically be ".".
            Only applied when appname is present.
        "multipath" is an optional parameter only applicable to *nix
            which indicates that the entire list of data dirs should be
            returned. By default, the first item from XDG_DATA_DIRS is
            returned, or '/usr/local/share/',
            if XDG_DATA_DIRS is not set

    Typical user data directories are:
        Mac OS X:   /Library/Application Support/
        Unix:       /usr/local/share/ or /usr/share/
        Win XP:     C:\Documents and Settings\All Users\Application Data\\
        Vista:      (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.)
        Win 7:      C:\ProgramData\\   # Hidden, but writeable on Win 7.

    For Unix, this is using the $XDG_DATA_DIRS[0] default.

    WARNING: Do not use this on Windows. See the Vista-Fail note above for why.
    """
    if system == "win32":
        if appauthor is None:
            appauthor = appname
        path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA"))
        if appname:
            if appauthor is not False:
                path = os.path.join(path, appauthor, appname)
            else:
                path = os.path.join(path, appname)
    elif system == 'darwin':
        path = os.path.expanduser('/Library/Application Support')
        if appname:
            path = os.path.join(path, appname)
    else:
        # XDG default for $XDG_DATA_DIRS
        # only first, if multipath is False
        path = os.getenv('XDG_DATA_DIRS',
                         os.pathsep.join(['/usr/local/share', '/usr/share']))
        pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)]
        if appname:
            if version:
                appname = os.path.join(appname, version)
            pathlist = [os.sep.join([x, appname]) for x in pathlist]

        if multipath:
            path = os.pathsep.join(pathlist)
        else:
            path = pathlist[0]
        return path

    if appname and version:
        path = os.path.join(path, version)
    return path


def user_config_dir(appname=None, appauthor=None, version=None, roaming=False):
    r"""Return full path to the user-specific config dir for this application.

        "appname" is the name of application.
            If None, just the system directory is returned.
        "appauthor" (only used on Windows) is the name of the
            appauthor or distributing body for this application. Typically
            it is the owning company name. This falls back to appname. You may
            pass False to disable it.
        "version" is an optional version path element to append to the
            path. You might want to use this if you want multiple versions
            of your app to be able to run independently. If used, this
            would typically be ".".
            Only applied when appname is present.
        "roaming" (boolean, default False) can be set True to use the Windows
            roaming appdata directory. That means that for users on a Windows
            network setup for roaming profiles, this user data will be
            sync'd on login. See
            
            for a discussion of issues.

    Typical user data directories are:
        Mac OS X:               same as user_data_dir
        Unix:                   ~/.config/     # or in $XDG_CONFIG_HOME, if defined
        Win *:                  same as user_data_dir

    For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME.
    That means, by deafult "~/.config/".
    """
    if system in ["win32", "darwin"]:
        path = user_data_dir(appname, appauthor, None, roaming)
    else:
        path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config"))
        if appname:
            path = os.path.join(path, appname)
    if appname and version:
        path = os.path.join(path, version)
    return path


def site_config_dir(appname=None, appauthor=None, version=None, multipath=False):
    """Return full path to the user-shared data dir for this application.

        "appname" is the name of application.
            If None, just the system directory is returned.
        "appauthor" (only used on Windows) is the name of the
            appauthor or distributing body for this application. Typically
            it is the owning company name. This falls back to appname. You may
            pass False to disable it.
        "version" is an optional version path element to append to the
            path. You might want to use this if you want multiple versions
            of your app to be able to run independently. If used, this
            would typically be ".".
            Only applied when appname is present.
        "multipath" is an optional parameter only applicable to *nix
            which indicates that the entire list of config dirs should be
            returned. By default, the first item from XDG_CONFIG_DIRS is
            returned, or '/etc/xdg/', if XDG_CONFIG_DIRS is not set

    Typical user data directories are:
        Mac OS X:   same as site_data_dir
        Unix:       /etc/xdg/ or $XDG_CONFIG_DIRS[i]/ for each value in
                    $XDG_CONFIG_DIRS
        Win *:      same as site_data_dir
        Vista:      (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.)

    For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False

    WARNING: Do not use this on Windows. See the Vista-Fail note above for why.
    """
    if system in ["win32", "darwin"]:
        path = site_data_dir(appname, appauthor)
        if appname and version:
            path = os.path.join(path, version)
    else:
        # XDG default for $XDG_CONFIG_DIRS
        # only first, if multipath is False
        path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg')
        pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)]
        if appname:
            if version:
                appname = os.path.join(appname, version)
            pathlist = [os.sep.join([x, appname]) for x in pathlist]

        if multipath:
            path = os.pathsep.join(pathlist)
        else:
            path = pathlist[0]
    return path


def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True):
    r"""Return full path to the user-specific cache dir for this application.

        "appname" is the name of application.
            If None, just the system directory is returned.
        "appauthor" (only used on Windows) is the name of the
            appauthor or distributing body for this application. Typically
            it is the owning company name. This falls back to appname. You may
            pass False to disable it.
        "version" is an optional version path element to append to the
            path. You might want to use this if you want multiple versions
            of your app to be able to run independently. If used, this
            would typically be ".".
            Only applied when appname is present.
        "opinion" (boolean) can be False to disable the appending of
            "Cache" to the base app data dir for Windows. See
            discussion below.

    Typical user cache directories are:
        Mac OS X:   ~/Library/Caches/
        Unix:       ~/.cache/ (XDG default)
        Win XP:     C:\Documents and Settings\\Local Settings\Application Data\\\Cache
        Vista:      C:\Users\\AppData\Local\\\Cache

    On Windows the only suggestion in the MSDN docs is that local settings go in
    the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming
    app data dir (the default returned by `user_data_dir` above). Apps typically
    put cache data somewhere *under* the given dir here. Some examples:
        ...\Mozilla\Firefox\Profiles\\Cache
        ...\Acme\SuperApp\Cache\1.0
    OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value.
    This can be disabled with the `opinion=False` option.
    """
    if system == "win32":
        if appauthor is None:
            appauthor = appname
        path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA"))
        if appname:
            if appauthor is not False:
                path = os.path.join(path, appauthor, appname)
            else:
                path = os.path.join(path, appname)
            if opinion:
                path = os.path.join(path, "Cache")
    elif system == 'darwin':
        path = os.path.expanduser('~/Library/Caches')
        if appname:
            path = os.path.join(path, appname)
    else:
        path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache'))
        if appname:
            path = os.path.join(path, appname)
    if appname and version:
        path = os.path.join(path, version)
    return path


def user_log_dir(appname=None, appauthor=None, version=None, opinion=True):
    r"""Return full path to the user-specific log dir for this application.

        "appname" is the name of application.
            If None, just the system directory is returned.
        "appauthor" (only used on Windows) is the name of the
            appauthor or distributing body for this application. Typically
            it is the owning company name. This falls back to appname. You may
            pass False to disable it.
        "version" is an optional version path element to append to the
            path. You might want to use this if you want multiple versions
            of your app to be able to run independently. If used, this
            would typically be ".".
            Only applied when appname is present.
        "opinion" (boolean) can be False to disable the appending of
            "Logs" to the base app data dir for Windows, and "log" to the
            base cache dir for Unix. See discussion below.

    Typical user cache directories are:
        Mac OS X:   ~/Library/Logs/
        Unix:       ~/.cache//log  # or under $XDG_CACHE_HOME if defined
        Win XP:     C:\Documents and Settings\\Local Settings\Application Data\\\Logs
        Vista:      C:\Users\\AppData\Local\\\Logs

    On Windows the only suggestion in the MSDN docs is that local settings
    go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in
    examples of what some windows apps use for a logs dir.)

    OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA`
    value for Windows and appends "log" to the user cache dir for Unix.
    This can be disabled with the `opinion=False` option.
    """
    if system == "darwin":
        path = os.path.join(
            os.path.expanduser('~/Library/Logs'),
            appname)
    elif system == "win32":
        path = user_data_dir(appname, appauthor, version)
        version = False
        if opinion:
            path = os.path.join(path, "Logs")
    else:
        path = user_cache_dir(appname, appauthor, version)
        version = False
        if opinion:
            path = os.path.join(path, "log")
    if appname and version:
        path = os.path.join(path, version)
    return path


class AppDirs(object):
    """Convenience wrapper for getting application dirs."""
    def __init__(self, appname, appauthor=None, version=None, roaming=False,
                 multipath=False):
        self.appname = appname
        self.appauthor = appauthor
        self.version = version
        self.roaming = roaming
        self.multipath = multipath

    @property
    def user_data_dir(self):
        return user_data_dir(self.appname, self.appauthor,
                             version=self.version, roaming=self.roaming)

    @property
    def site_data_dir(self):
        return site_data_dir(self.appname, self.appauthor,
                             version=self.version, multipath=self.multipath)

    @property
    def user_config_dir(self):
        return user_config_dir(self.appname, self.appauthor,
                               version=self.version, roaming=self.roaming)

    @property
    def site_config_dir(self):
        return site_config_dir(self.appname, self.appauthor,
                             version=self.version, multipath=self.multipath)

    @property
    def user_cache_dir(self):
        return user_cache_dir(self.appname, self.appauthor,
                              version=self.version)

    @property
    def user_log_dir(self):
        return user_log_dir(self.appname, self.appauthor,
                            version=self.version)


#---- internal support stuff

def _get_win_folder_from_registry(csidl_name):
    """This is a fallback technique at best. I'm not sure if using the
    registry for this guarantees us the correct answer for all CSIDL_*
    names.
    """
    import _winreg

    shell_folder_name = {
        "CSIDL_APPDATA": "AppData",
        "CSIDL_COMMON_APPDATA": "Common AppData",
        "CSIDL_LOCAL_APPDATA": "Local AppData",
    }[csidl_name]

    key = _winreg.OpenKey(
        _winreg.HKEY_CURRENT_USER,
        r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
    )
    dir, type = _winreg.QueryValueEx(key, shell_folder_name)
    return dir


def _get_win_folder_with_pywin32(csidl_name):
    from win32com.shell import shellcon, shell
    dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0)
    # Try to make this a unicode path because SHGetFolderPath does
    # not return unicode strings when there is unicode data in the
    # path.
    try:
        dir = unicode(dir)

        # Downgrade to short path name if have highbit chars. See
        # .
        has_high_char = False
        for c in dir:
            if ord(c) > 255:
                has_high_char = True
                break
        if has_high_char:
            try:
                import win32api
                dir = win32api.GetShortPathName(dir)
            except ImportError:
                pass
    except UnicodeError:
        pass
    return dir


def _get_win_folder_with_ctypes(csidl_name):
    import ctypes

    csidl_const = {
        "CSIDL_APPDATA": 26,
        "CSIDL_COMMON_APPDATA": 35,
        "CSIDL_LOCAL_APPDATA": 28,
    }[csidl_name]

    buf = ctypes.create_unicode_buffer(1024)
    ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)

    # Downgrade to short path name if have highbit chars. See
    # .
    has_high_char = False
    for c in buf:
        if ord(c) > 255:
            has_high_char = True
            break
    if has_high_char:
        buf2 = ctypes.create_unicode_buffer(1024)
        if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
            buf = buf2

    return buf.value

def _get_win_folder_with_jna(csidl_name):
    import array
    from com.sun import jna
    from com.sun.jna.platform import win32

    buf_size = win32.WinDef.MAX_PATH * 2
    buf = array.zeros('c', buf_size)
    shell = win32.Shell32.INSTANCE
    shell.SHGetFolderPath(None, getattr(win32.ShlObj, csidl_name), None, win32.ShlObj.SHGFP_TYPE_CURRENT, buf)
    dir = jna.Native.toString(buf.tostring()).rstrip("\0")

    # Downgrade to short path name if have highbit chars. See
    # .
    has_high_char = False
    for c in dir:
        if ord(c) > 255:
            has_high_char = True
            break
    if has_high_char:
        buf = array.zeros('c', buf_size)
        kernel = win32.Kernel32.INSTANCE
        if kernal.GetShortPathName(dir, buf, buf_size):
            dir = jna.Native.toString(buf.tostring()).rstrip("\0")

    return dir

if system == "win32":
    try:
        import win32com.shell
        _get_win_folder = _get_win_folder_with_pywin32
    except ImportError:
        try:
            from ctypes import windll
            _get_win_folder = _get_win_folder_with_ctypes
        except ImportError:
            try:
                import com.sun.jna
                _get_win_folder = _get_win_folder_with_jna
            except ImportError:
                _get_win_folder = _get_win_folder_from_registry


#---- self test code

if __name__ == "__main__":
    appname = "MyApp"
    appauthor = "MyCompany"

    props = ("user_data_dir", "site_data_dir",
             "user_config_dir", "site_config_dir",
             "user_cache_dir", "user_log_dir")

    print("-- app dirs (with optional 'version')")
    dirs = AppDirs(appname, appauthor, version="1.0")
    for prop in props:
        print("%s: %s" % (prop, getattr(dirs, prop)))

    print("\n-- app dirs (without optional 'version')")
    dirs = AppDirs(appname, appauthor)
    for prop in props:
        print("%s: %s" % (prop, getattr(dirs, prop)))

    print("\n-- app dirs (without optional 'appauthor')")
    dirs = AppDirs(appname)
    for prop in props:
        print("%s: %s" % (prop, getattr(dirs, prop)))

    print("\n-- app dirs (with disabled 'appauthor')")
    dirs = AppDirs(appname, appauthor=False)
    for prop in props:
        print("%s: %s" % (prop, getattr(dirs, prop)))
pyparsing.py000064400000700753147205126200007145 0ustar00# module pyparsing.py
#
# Copyright (c) 2003-2016  Paul T. McGuire
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

__doc__ = \
"""
pyparsing module - Classes and methods to define and execute parsing grammars

The pyparsing module is an alternative approach to creating and executing simple grammars,
vs. the traditional lex/yacc approach, or the use of regular expressions.  With pyparsing, you
don't need to learn a new syntax for defining grammars or matching expressions - the parsing module
provides a library of classes that you use to construct the grammar directly in Python.

Here is a program to parse "Hello, World!" (or any greeting of the form 
C{", !"}), built up using L{Word}, L{Literal}, and L{And} elements 
(L{'+'} operator gives L{And} expressions, strings are auto-converted to
L{Literal} expressions)::

    from pyparsing import Word, alphas

    # define grammar of a greeting
    greet = Word(alphas) + "," + Word(alphas) + "!"

    hello = "Hello, World!"
    print (hello, "->", greet.parseString(hello))

The program outputs the following::

    Hello, World! -> ['Hello', ',', 'World', '!']

The Python representation of the grammar is quite readable, owing to the self-explanatory
class names, and the use of '+', '|' and '^' operators.

The L{ParseResults} object returned from L{ParserElement.parseString} can be accessed as a nested list, a dictionary, or an
object with named attributes.

The pyparsing module handles some of the problems that are typically vexing when writing text parsers:
 - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello  ,  World  !", etc.)
 - quoted strings
 - embedded comments
"""

__version__ = "2.1.10"
__versionTime__ = "07 Oct 2016 01:31 UTC"
__author__ = "Paul McGuire "

import string
from weakref import ref as wkref
import copy
import sys
import warnings
import re
import sre_constants
import collections
import pprint
import traceback
import types
from datetime import datetime

try:
    from _thread import RLock
except ImportError:
    from threading import RLock

try:
    from collections import OrderedDict as _OrderedDict
except ImportError:
    try:
        from ordereddict import OrderedDict as _OrderedDict
    except ImportError:
        _OrderedDict = None

#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) )

__all__ = [
'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty',
'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal',
'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or',
'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException',
'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException',
'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', 
'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore',
'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col',
'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString',
'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums',
'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno',
'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral',
'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables',
'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', 
'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd',
'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute',
'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass',
'CloseMatch', 'tokenMap', 'pyparsing_common',
]

system_version = tuple(sys.version_info)[:3]
PY_3 = system_version[0] == 3
if PY_3:
    _MAX_INT = sys.maxsize
    basestring = str
    unichr = chr
    _ustr = str

    # build list of single arg builtins, that can be used as parse actions
    singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max]

else:
    _MAX_INT = sys.maxint
    range = xrange

    def _ustr(obj):
        """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries
           str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It
           then < returns the unicode object | encodes it with the default encoding | ... >.
        """
        if isinstance(obj,unicode):
            return obj

        try:
            # If this works, then _ustr(obj) has the same behaviour as str(obj), so
            # it won't break any existing code.
            return str(obj)

        except UnicodeEncodeError:
            # Else encode it
            ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace')
            xmlcharref = Regex('&#\d+;')
            xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:])
            return xmlcharref.transformString(ret)

    # build list of single arg builtins, tolerant of Python version, that can be used as parse actions
    singleArgBuiltins = []
    import __builtin__
    for fname in "sum len sorted reversed list tuple set any all min max".split():
        try:
            singleArgBuiltins.append(getattr(__builtin__,fname))
        except AttributeError:
            continue
            
_generatorType = type((y for y in range(1)))
 
def _xml_escape(data):
    """Escape &, <, >, ", ', etc. in a string of data."""

    # ampersand must be replaced first
    from_symbols = '&><"\''
    to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split())
    for from_,to_ in zip(from_symbols, to_symbols):
        data = data.replace(from_, to_)
    return data

class _Constants(object):
    pass

alphas     = string.ascii_uppercase + string.ascii_lowercase
nums       = "0123456789"
hexnums    = nums + "ABCDEFabcdef"
alphanums  = alphas + nums
_bslash    = chr(92)
printables = "".join(c for c in string.printable if c not in string.whitespace)

class ParseBaseException(Exception):
    """base exception class for all parsing runtime exceptions"""
    # Performance tuning: we construct a *lot* of these, so keep this
    # constructor as small and fast as possible
    def __init__( self, pstr, loc=0, msg=None, elem=None ):
        self.loc = loc
        if msg is None:
            self.msg = pstr
            self.pstr = ""
        else:
            self.msg = msg
            self.pstr = pstr
        self.parserElement = elem
        self.args = (pstr, loc, msg)

    @classmethod
    def _from_exception(cls, pe):
        """
        internal factory method to simplify creating one type of ParseException 
        from another - avoids having __init__ signature conflicts among subclasses
        """
        return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement)

    def __getattr__( self, aname ):
        """supported attributes by name are:
            - lineno - returns the line number of the exception text
            - col - returns the column number of the exception text
            - line - returns the line containing the exception text
        """
        if( aname == "lineno" ):
            return lineno( self.loc, self.pstr )
        elif( aname in ("col", "column") ):
            return col( self.loc, self.pstr )
        elif( aname == "line" ):
            return line( self.loc, self.pstr )
        else:
            raise AttributeError(aname)

    def __str__( self ):
        return "%s (at char %d), (line:%d, col:%d)" % \
                ( self.msg, self.loc, self.lineno, self.column )
    def __repr__( self ):
        return _ustr(self)
    def markInputline( self, markerString = ">!<" ):
        """Extracts the exception line from the input string, and marks
           the location of the exception with a special symbol.
        """
        line_str = self.line
        line_column = self.column - 1
        if markerString:
            line_str = "".join((line_str[:line_column],
                                markerString, line_str[line_column:]))
        return line_str.strip()
    def __dir__(self):
        return "lineno col line".split() + dir(type(self))

class ParseException(ParseBaseException):
    """
    Exception thrown when parse expressions don't match class;
    supported attributes by name are:
     - lineno - returns the line number of the exception text
     - col - returns the column number of the exception text
     - line - returns the line containing the exception text
        
    Example::
        try:
            Word(nums).setName("integer").parseString("ABC")
        except ParseException as pe:
            print(pe)
            print("column: {}".format(pe.col))
            
    prints::
       Expected integer (at char 0), (line:1, col:1)
        column: 1
    """
    pass

class ParseFatalException(ParseBaseException):
    """user-throwable exception thrown when inconsistent parse content
       is found; stops all parsing immediately"""
    pass

class ParseSyntaxException(ParseFatalException):
    """just like L{ParseFatalException}, but thrown internally when an
       L{ErrorStop} ('-' operator) indicates that parsing is to stop 
       immediately because an unbacktrackable syntax error has been found"""
    pass

#~ class ReparseException(ParseBaseException):
    #~ """Experimental class - parse actions can raise this exception to cause
       #~ pyparsing to reparse the input string:
        #~ - with a modified input string, and/or
        #~ - with a modified start location
       #~ Set the values of the ReparseException in the constructor, and raise the
       #~ exception in a parse action to cause pyparsing to use the new string/location.
       #~ Setting the values as None causes no change to be made.
       #~ """
    #~ def __init_( self, newstring, restartLoc ):
        #~ self.newParseText = newstring
        #~ self.reparseLoc = restartLoc

class RecursiveGrammarException(Exception):
    """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive"""
    def __init__( self, parseElementList ):
        self.parseElementTrace = parseElementList

    def __str__( self ):
        return "RecursiveGrammarException: %s" % self.parseElementTrace

class _ParseResultsWithOffset(object):
    def __init__(self,p1,p2):
        self.tup = (p1,p2)
    def __getitem__(self,i):
        return self.tup[i]
    def __repr__(self):
        return repr(self.tup[0])
    def setOffset(self,i):
        self.tup = (self.tup[0],i)

class ParseResults(object):
    """
    Structured parse results, to provide multiple means of access to the parsed data:
       - as a list (C{len(results)})
       - by list index (C{results[0], results[1]}, etc.)
       - by attribute (C{results.} - see L{ParserElement.setResultsName})

    Example::
        integer = Word(nums)
        date_str = (integer.setResultsName("year") + '/' 
                        + integer.setResultsName("month") + '/' 
                        + integer.setResultsName("day"))
        # equivalent form:
        # date_str = integer("year") + '/' + integer("month") + '/' + integer("day")

        # parseString returns a ParseResults object
        result = date_str.parseString("1999/12/31")

        def test(s, fn=repr):
            print("%s -> %s" % (s, fn(eval(s))))
        test("list(result)")
        test("result[0]")
        test("result['month']")
        test("result.day")
        test("'month' in result")
        test("'minutes' in result")
        test("result.dump()", str)
    prints::
        list(result) -> ['1999', '/', '12', '/', '31']
        result[0] -> '1999'
        result['month'] -> '12'
        result.day -> '31'
        'month' in result -> True
        'minutes' in result -> False
        result.dump() -> ['1999', '/', '12', '/', '31']
        - day: 31
        - month: 12
        - year: 1999
    """
    def __new__(cls, toklist=None, name=None, asList=True, modal=True ):
        if isinstance(toklist, cls):
            return toklist
        retobj = object.__new__(cls)
        retobj.__doinit = True
        return retobj

    # Performance tuning: we construct a *lot* of these, so keep this
    # constructor as small and fast as possible
    def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ):
        if self.__doinit:
            self.__doinit = False
            self.__name = None
            self.__parent = None
            self.__accumNames = {}
            self.__asList = asList
            self.__modal = modal
            if toklist is None:
                toklist = []
            if isinstance(toklist, list):
                self.__toklist = toklist[:]
            elif isinstance(toklist, _generatorType):
                self.__toklist = list(toklist)
            else:
                self.__toklist = [toklist]
            self.__tokdict = dict()

        if name is not None and name:
            if not modal:
                self.__accumNames[name] = 0
            if isinstance(name,int):
                name = _ustr(name) # will always return a str, but use _ustr for consistency
            self.__name = name
            if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])):
                if isinstance(toklist,basestring):
                    toklist = [ toklist ]
                if asList:
                    if isinstance(toklist,ParseResults):
                        self[name] = _ParseResultsWithOffset(toklist.copy(),0)
                    else:
                        self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0)
                    self[name].__name = name
                else:
                    try:
                        self[name] = toklist[0]
                    except (KeyError,TypeError,IndexError):
                        self[name] = toklist

    def __getitem__( self, i ):
        if isinstance( i, (int,slice) ):
            return self.__toklist[i]
        else:
            if i not in self.__accumNames:
                return self.__tokdict[i][-1][0]
            else:
                return ParseResults([ v[0] for v in self.__tokdict[i] ])

    def __setitem__( self, k, v, isinstance=isinstance ):
        if isinstance(v,_ParseResultsWithOffset):
            self.__tokdict[k] = self.__tokdict.get(k,list()) + [v]
            sub = v[0]
        elif isinstance(k,(int,slice)):
            self.__toklist[k] = v
            sub = v
        else:
            self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)]
            sub = v
        if isinstance(sub,ParseResults):
            sub.__parent = wkref(self)

    def __delitem__( self, i ):
        if isinstance(i,(int,slice)):
            mylen = len( self.__toklist )
            del self.__toklist[i]

            # convert int to slice
            if isinstance(i, int):
                if i < 0:
                    i += mylen
                i = slice(i, i+1)
            # get removed indices
            removed = list(range(*i.indices(mylen)))
            removed.reverse()
            # fixup indices in token dictionary
            for name,occurrences in self.__tokdict.items():
                for j in removed:
                    for k, (value, position) in enumerate(occurrences):
                        occurrences[k] = _ParseResultsWithOffset(value, position - (position > j))
        else:
            del self.__tokdict[i]

    def __contains__( self, k ):
        return k in self.__tokdict

    def __len__( self ): return len( self.__toklist )
    def __bool__(self): return ( not not self.__toklist )
    __nonzero__ = __bool__
    def __iter__( self ): return iter( self.__toklist )
    def __reversed__( self ): return iter( self.__toklist[::-1] )
    def _iterkeys( self ):
        if hasattr(self.__tokdict, "iterkeys"):
            return self.__tokdict.iterkeys()
        else:
            return iter(self.__tokdict)

    def _itervalues( self ):
        return (self[k] for k in self._iterkeys())
            
    def _iteritems( self ):
        return ((k, self[k]) for k in self._iterkeys())

    if PY_3:
        keys = _iterkeys       
        """Returns an iterator of all named result keys (Python 3.x only)."""

        values = _itervalues
        """Returns an iterator of all named result values (Python 3.x only)."""

        items = _iteritems
        """Returns an iterator of all named result key-value tuples (Python 3.x only)."""

    else:
        iterkeys = _iterkeys
        """Returns an iterator of all named result keys (Python 2.x only)."""

        itervalues = _itervalues
        """Returns an iterator of all named result values (Python 2.x only)."""

        iteritems = _iteritems
        """Returns an iterator of all named result key-value tuples (Python 2.x only)."""

        def keys( self ):
            """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x)."""
            return list(self.iterkeys())

        def values( self ):
            """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x)."""
            return list(self.itervalues())
                
        def items( self ):
            """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x)."""
            return list(self.iteritems())

    def haskeys( self ):
        """Since keys() returns an iterator, this method is helpful in bypassing
           code that looks for the existence of any defined results names."""
        return bool(self.__tokdict)
        
    def pop( self, *args, **kwargs):
        """
        Removes and returns item at specified index (default=C{last}).
        Supports both C{list} and C{dict} semantics for C{pop()}. If passed no
        argument or an integer argument, it will use C{list} semantics
        and pop tokens from the list of parsed tokens. If passed a 
        non-integer argument (most likely a string), it will use C{dict}
        semantics and pop the corresponding value from any defined 
        results names. A second default return value argument is 
        supported, just as in C{dict.pop()}.

        Example::
            def remove_first(tokens):
                tokens.pop(0)
            print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321']
            print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321']

            label = Word(alphas)
            patt = label("LABEL") + OneOrMore(Word(nums))
            print(patt.parseString("AAB 123 321").dump())

            # Use pop() in a parse action to remove named result (note that corresponding value is not
            # removed from list form of results)
            def remove_LABEL(tokens):
                tokens.pop("LABEL")
                return tokens
            patt.addParseAction(remove_LABEL)
            print(patt.parseString("AAB 123 321").dump())
        prints::
            ['AAB', '123', '321']
            - LABEL: AAB

            ['AAB', '123', '321']
        """
        if not args:
            args = [-1]
        for k,v in kwargs.items():
            if k == 'default':
                args = (args[0], v)
            else:
                raise TypeError("pop() got an unexpected keyword argument '%s'" % k)
        if (isinstance(args[0], int) or 
                        len(args) == 1 or 
                        args[0] in self):
            index = args[0]
            ret = self[index]
            del self[index]
            return ret
        else:
            defaultvalue = args[1]
            return defaultvalue

    def get(self, key, defaultValue=None):
        """
        Returns named result matching the given key, or if there is no
        such name, then returns the given C{defaultValue} or C{None} if no
        C{defaultValue} is specified.

        Similar to C{dict.get()}.
        
        Example::
            integer = Word(nums)
            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")           

            result = date_str.parseString("1999/12/31")
            print(result.get("year")) # -> '1999'
            print(result.get("hour", "not specified")) # -> 'not specified'
            print(result.get("hour")) # -> None
        """
        if key in self:
            return self[key]
        else:
            return defaultValue

    def insert( self, index, insStr ):
        """
        Inserts new element at location index in the list of parsed tokens.
        
        Similar to C{list.insert()}.

        Example::
            print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321']

            # use a parse action to insert the parse location in the front of the parsed results
            def insert_locn(locn, tokens):
                tokens.insert(0, locn)
            print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321']
        """
        self.__toklist.insert(index, insStr)
        # fixup indices in token dictionary
        for name,occurrences in self.__tokdict.items():
            for k, (value, position) in enumerate(occurrences):
                occurrences[k] = _ParseResultsWithOffset(value, position + (position > index))

    def append( self, item ):
        """
        Add single element to end of ParseResults list of elements.

        Example::
            print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321']
            
            # use a parse action to compute the sum of the parsed integers, and add it to the end
            def append_sum(tokens):
                tokens.append(sum(map(int, tokens)))
            print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444]
        """
        self.__toklist.append(item)

    def extend( self, itemseq ):
        """
        Add sequence of elements to end of ParseResults list of elements.

        Example::
            patt = OneOrMore(Word(alphas))
            
            # use a parse action to append the reverse of the matched strings, to make a palindrome
            def make_palindrome(tokens):
                tokens.extend(reversed([t[::-1] for t in tokens]))
                return ''.join(tokens)
            print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl'
        """
        if isinstance(itemseq, ParseResults):
            self += itemseq
        else:
            self.__toklist.extend(itemseq)

    def clear( self ):
        """
        Clear all elements and results names.
        """
        del self.__toklist[:]
        self.__tokdict.clear()

    def __getattr__( self, name ):
        try:
            return self[name]
        except KeyError:
            return ""
            
        if name in self.__tokdict:
            if name not in self.__accumNames:
                return self.__tokdict[name][-1][0]
            else:
                return ParseResults([ v[0] for v in self.__tokdict[name] ])
        else:
            return ""

    def __add__( self, other ):
        ret = self.copy()
        ret += other
        return ret

    def __iadd__( self, other ):
        if other.__tokdict:
            offset = len(self.__toklist)
            addoffset = lambda a: offset if a<0 else a+offset
            otheritems = other.__tokdict.items()
            otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) )
                                for (k,vlist) in otheritems for v in vlist]
            for k,v in otherdictitems:
                self[k] = v
                if isinstance(v[0],ParseResults):
                    v[0].__parent = wkref(self)
            
        self.__toklist += other.__toklist
        self.__accumNames.update( other.__accumNames )
        return self

    def __radd__(self, other):
        if isinstance(other,int) and other == 0:
            # useful for merging many ParseResults using sum() builtin
            return self.copy()
        else:
            # this may raise a TypeError - so be it
            return other + self
        
    def __repr__( self ):
        return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) )

    def __str__( self ):
        return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']'

    def _asStringList( self, sep='' ):
        out = []
        for item in self.__toklist:
            if out and sep:
                out.append(sep)
            if isinstance( item, ParseResults ):
                out += item._asStringList()
            else:
                out.append( _ustr(item) )
        return out

    def asList( self ):
        """
        Returns the parse results as a nested list of matching tokens, all converted to strings.

        Example::
            patt = OneOrMore(Word(alphas))
            result = patt.parseString("sldkj lsdkj sldkj")
            # even though the result prints in string-like form, it is actually a pyparsing ParseResults
            print(type(result), result) # ->  ['sldkj', 'lsdkj', 'sldkj']
            
            # Use asList() to create an actual list
            result_list = result.asList()
            print(type(result_list), result_list) # ->  ['sldkj', 'lsdkj', 'sldkj']
        """
        return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist]

    def asDict( self ):
        """
        Returns the named parse results as a nested dictionary.

        Example::
            integer = Word(nums)
            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
            
            result = date_str.parseString('12/31/1999')
            print(type(result), repr(result)) # ->  (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]})
            
            result_dict = result.asDict()
            print(type(result_dict), repr(result_dict)) # ->  {'day': '1999', 'year': '12', 'month': '31'}

            # even though a ParseResults supports dict-like access, sometime you just need to have a dict
            import json
            print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable
            print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"}
        """
        if PY_3:
            item_fn = self.items
        else:
            item_fn = self.iteritems
            
        def toItem(obj):
            if isinstance(obj, ParseResults):
                if obj.haskeys():
                    return obj.asDict()
                else:
                    return [toItem(v) for v in obj]
            else:
                return obj
                
        return dict((k,toItem(v)) for k,v in item_fn())

    def copy( self ):
        """
        Returns a new copy of a C{ParseResults} object.
        """
        ret = ParseResults( self.__toklist )
        ret.__tokdict = self.__tokdict.copy()
        ret.__parent = self.__parent
        ret.__accumNames.update( self.__accumNames )
        ret.__name = self.__name
        return ret

    def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ):
        """
        (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names.
        """
        nl = "\n"
        out = []
        namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items()
                                                            for v in vlist)
        nextLevelIndent = indent + "  "

        # collapse out indents if formatting is not desired
        if not formatted:
            indent = ""
            nextLevelIndent = ""
            nl = ""

        selfTag = None
        if doctag is not None:
            selfTag = doctag
        else:
            if self.__name:
                selfTag = self.__name

        if not selfTag:
            if namedItemsOnly:
                return ""
            else:
                selfTag = "ITEM"

        out += [ nl, indent, "<", selfTag, ">" ]

        for i,res in enumerate(self.__toklist):
            if isinstance(res,ParseResults):
                if i in namedItems:
                    out += [ res.asXML(namedItems[i],
                                        namedItemsOnly and doctag is None,
                                        nextLevelIndent,
                                        formatted)]
                else:
                    out += [ res.asXML(None,
                                        namedItemsOnly and doctag is None,
                                        nextLevelIndent,
                                        formatted)]
            else:
                # individual token, see if there is a name for it
                resTag = None
                if i in namedItems:
                    resTag = namedItems[i]
                if not resTag:
                    if namedItemsOnly:
                        continue
                    else:
                        resTag = "ITEM"
                xmlBodyText = _xml_escape(_ustr(res))
                out += [ nl, nextLevelIndent, "<", resTag, ">",
                                                xmlBodyText,
                                                "" ]

        out += [ nl, indent, "" ]
        return "".join(out)

    def __lookup(self,sub):
        for k,vlist in self.__tokdict.items():
            for v,loc in vlist:
                if sub is v:
                    return k
        return None

    def getName(self):
        """
        Returns the results name for this token expression. Useful when several 
        different expressions might match at a particular location.

        Example::
            integer = Word(nums)
            ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d")
            house_number_expr = Suppress('#') + Word(nums, alphanums)
            user_data = (Group(house_number_expr)("house_number") 
                        | Group(ssn_expr)("ssn")
                        | Group(integer)("age"))
            user_info = OneOrMore(user_data)
            
            result = user_info.parseString("22 111-22-3333 #221B")
            for item in result:
                print(item.getName(), ':', item[0])
        prints::
            age : 22
            ssn : 111-22-3333
            house_number : 221B
        """
        if self.__name:
            return self.__name
        elif self.__parent:
            par = self.__parent()
            if par:
                return par.__lookup(self)
            else:
                return None
        elif (len(self) == 1 and
               len(self.__tokdict) == 1 and
               next(iter(self.__tokdict.values()))[0][1] in (0,-1)):
            return next(iter(self.__tokdict.keys()))
        else:
            return None

    def dump(self, indent='', depth=0, full=True):
        """
        Diagnostic method for listing out the contents of a C{ParseResults}.
        Accepts an optional C{indent} argument so that this string can be embedded
        in a nested display of other data.

        Example::
            integer = Word(nums)
            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
            
            result = date_str.parseString('12/31/1999')
            print(result.dump())
        prints::
            ['12', '/', '31', '/', '1999']
            - day: 1999
            - month: 31
            - year: 12
        """
        out = []
        NL = '\n'
        out.append( indent+_ustr(self.asList()) )
        if full:
            if self.haskeys():
                items = sorted((str(k), v) for k,v in self.items())
                for k,v in items:
                    if out:
                        out.append(NL)
                    out.append( "%s%s- %s: " % (indent,('  '*depth), k) )
                    if isinstance(v,ParseResults):
                        if v:
                            out.append( v.dump(indent,depth+1) )
                        else:
                            out.append(_ustr(v))
                    else:
                        out.append(repr(v))
            elif any(isinstance(vv,ParseResults) for vv in self):
                v = self
                for i,vv in enumerate(v):
                    if isinstance(vv,ParseResults):
                        out.append("\n%s%s[%d]:\n%s%s%s" % (indent,('  '*(depth)),i,indent,('  '*(depth+1)),vv.dump(indent,depth+1) ))
                    else:
                        out.append("\n%s%s[%d]:\n%s%s%s" % (indent,('  '*(depth)),i,indent,('  '*(depth+1)),_ustr(vv)))
            
        return "".join(out)

    def pprint(self, *args, **kwargs):
        """
        Pretty-printer for parsed results as a list, using the C{pprint} module.
        Accepts additional positional or keyword args as defined for the 
        C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint})

        Example::
            ident = Word(alphas, alphanums)
            num = Word(nums)
            func = Forward()
            term = ident | num | Group('(' + func + ')')
            func <<= ident + Group(Optional(delimitedList(term)))
            result = func.parseString("fna a,b,(fnb c,d,200),100")
            result.pprint(width=40)
        prints::
            ['fna',
             ['a',
              'b',
              ['(', 'fnb', ['c', 'd', '200'], ')'],
              '100']]
        """
        pprint.pprint(self.asList(), *args, **kwargs)

    # add support for pickle protocol
    def __getstate__(self):
        return ( self.__toklist,
                 ( self.__tokdict.copy(),
                   self.__parent is not None and self.__parent() or None,
                   self.__accumNames,
                   self.__name ) )

    def __setstate__(self,state):
        self.__toklist = state[0]
        (self.__tokdict,
         par,
         inAccumNames,
         self.__name) = state[1]
        self.__accumNames = {}
        self.__accumNames.update(inAccumNames)
        if par is not None:
            self.__parent = wkref(par)
        else:
            self.__parent = None

    def __getnewargs__(self):
        return self.__toklist, self.__name, self.__asList, self.__modal

    def __dir__(self):
        return (dir(type(self)) + list(self.keys()))

collections.MutableMapping.register(ParseResults)

def col (loc,strg):
    """Returns current column within a string, counting newlines as line separators.
   The first column is number 1.

   Note: the default parsing behavior is to expand tabs in the input string
   before starting the parsing process.  See L{I{ParserElement.parseString}} for more information
   on parsing strings containing C{}s, and suggested methods to maintain a
   consistent view of the parsed string, the parse location, and line and column
   positions within the parsed string.
   """
    s = strg
    return 1 if 0} for more information
   on parsing strings containing C{}s, and suggested methods to maintain a
   consistent view of the parsed string, the parse location, and line and column
   positions within the parsed string.
   """
    return strg.count("\n",0,loc) + 1

def line( loc, strg ):
    """Returns the line of text containing loc within a string, counting newlines as line separators.
       """
    lastCR = strg.rfind("\n", 0, loc)
    nextCR = strg.find("\n", loc)
    if nextCR >= 0:
        return strg[lastCR+1:nextCR]
    else:
        return strg[lastCR+1:]

def _defaultStartDebugAction( instring, loc, expr ):
    print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )))

def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ):
    print ("Matched " + _ustr(expr) + " -> " + str(toks.asList()))

def _defaultExceptionDebugAction( instring, loc, expr, exc ):
    print ("Exception raised:" + _ustr(exc))

def nullDebugAction(*args):
    """'Do-nothing' debug action, to suppress debugging output during parsing."""
    pass

# Only works on Python 3.x - nonlocal is toxic to Python 2 installs
#~ 'decorator to trim function calls to match the arity of the target'
#~ def _trim_arity(func, maxargs=3):
    #~ if func in singleArgBuiltins:
        #~ return lambda s,l,t: func(t)
    #~ limit = 0
    #~ foundArity = False
    #~ def wrapper(*args):
        #~ nonlocal limit,foundArity
        #~ while 1:
            #~ try:
                #~ ret = func(*args[limit:])
                #~ foundArity = True
                #~ return ret
            #~ except TypeError:
                #~ if limit == maxargs or foundArity:
                    #~ raise
                #~ limit += 1
                #~ continue
    #~ return wrapper

# this version is Python 2.x-3.x cross-compatible
'decorator to trim function calls to match the arity of the target'
def _trim_arity(func, maxargs=2):
    if func in singleArgBuiltins:
        return lambda s,l,t: func(t)
    limit = [0]
    foundArity = [False]
    
    # traceback return data structure changed in Py3.5 - normalize back to plain tuples
    if system_version[:2] >= (3,5):
        def extract_stack(limit=0):
            # special handling for Python 3.5.0 - extra deep call stack by 1
            offset = -3 if system_version == (3,5,0) else -2
            frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset]
            return [(frame_summary.filename, frame_summary.lineno)]
        def extract_tb(tb, limit=0):
            frames = traceback.extract_tb(tb, limit=limit)
            frame_summary = frames[-1]
            return [(frame_summary.filename, frame_summary.lineno)]
    else:
        extract_stack = traceback.extract_stack
        extract_tb = traceback.extract_tb
    
    # synthesize what would be returned by traceback.extract_stack at the call to 
    # user's parse action 'func', so that we don't incur call penalty at parse time
    
    LINE_DIFF = 6
    # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND 
    # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!!
    this_line = extract_stack(limit=2)[-1]
    pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF)

    def wrapper(*args):
        while 1:
            try:
                ret = func(*args[limit[0]:])
                foundArity[0] = True
                return ret
            except TypeError:
                # re-raise TypeErrors if they did not come from our arity testing
                if foundArity[0]:
                    raise
                else:
                    try:
                        tb = sys.exc_info()[-1]
                        if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth:
                            raise
                    finally:
                        del tb

                if limit[0] <= maxargs:
                    limit[0] += 1
                    continue
                raise

    # copy func name to wrapper for sensible debug output
    func_name = ""
    try:
        func_name = getattr(func, '__name__', 
                            getattr(func, '__class__').__name__)
    except Exception:
        func_name = str(func)
    wrapper.__name__ = func_name

    return wrapper

class ParserElement(object):
    """Abstract base level parser element class."""
    DEFAULT_WHITE_CHARS = " \n\t\r"
    verbose_stacktrace = False

    @staticmethod
    def setDefaultWhitespaceChars( chars ):
        r"""
        Overrides the default whitespace chars

        Example::
            # default whitespace chars are space,  and newline
            OneOrMore(Word(alphas)).parseString("abc def\nghi jkl")  # -> ['abc', 'def', 'ghi', 'jkl']
            
            # change to just treat newline as significant
            ParserElement.setDefaultWhitespaceChars(" \t")
            OneOrMore(Word(alphas)).parseString("abc def\nghi jkl")  # -> ['abc', 'def']
        """
        ParserElement.DEFAULT_WHITE_CHARS = chars

    @staticmethod
    def inlineLiteralsUsing(cls):
        """
        Set class to be used for inclusion of string literals into a parser.
        
        Example::
            # default literal class used is Literal
            integer = Word(nums)
            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")           

            date_str.parseString("1999/12/31")  # -> ['1999', '/', '12', '/', '31']


            # change to Suppress
            ParserElement.inlineLiteralsUsing(Suppress)
            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")           

            date_str.parseString("1999/12/31")  # -> ['1999', '12', '31']
        """
        ParserElement._literalStringClass = cls

    def __init__( self, savelist=False ):
        self.parseAction = list()
        self.failAction = None
        #~ self.name = ""  # don't define self.name, let subclasses try/except upcall
        self.strRepr = None
        self.resultsName = None
        self.saveAsList = savelist
        self.skipWhitespace = True
        self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
        self.copyDefaultWhiteChars = True
        self.mayReturnEmpty = False # used when checking for left-recursion
        self.keepTabs = False
        self.ignoreExprs = list()
        self.debug = False
        self.streamlined = False
        self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index
        self.errmsg = ""
        self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all)
        self.debugActions = ( None, None, None ) #custom debug actions
        self.re = None
        self.callPreparse = True # used to avoid redundant calls to preParse
        self.callDuringTry = False

    def copy( self ):
        """
        Make a copy of this C{ParserElement}.  Useful for defining different parse actions
        for the same parsing pattern, using copies of the original parse element.
        
        Example::
            integer = Word(nums).setParseAction(lambda toks: int(toks[0]))
            integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K")
            integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M")
            
            print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M"))
        prints::
            [5120, 100, 655360, 268435456]
        Equivalent form of C{expr.copy()} is just C{expr()}::
            integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M")
        """
        cpy = copy.copy( self )
        cpy.parseAction = self.parseAction[:]
        cpy.ignoreExprs = self.ignoreExprs[:]
        if self.copyDefaultWhiteChars:
            cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
        return cpy

    def setName( self, name ):
        """
        Define name for this expression, makes debugging and exception messages clearer.
        
        Example::
            Word(nums).parseString("ABC")  # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1)
            Word(nums).setName("integer").parseString("ABC")  # -> Exception: Expected integer (at char 0), (line:1, col:1)
        """
        self.name = name
        self.errmsg = "Expected " + self.name
        if hasattr(self,"exception"):
            self.exception.msg = self.errmsg
        return self

    def setResultsName( self, name, listAllMatches=False ):
        """
        Define name for referencing matching tokens as a nested attribute
        of the returned parse results.
        NOTE: this returns a *copy* of the original C{ParserElement} object;
        this is so that the client can define a basic element, such as an
        integer, and reference it in multiple places with different names.

        You can also set results names using the abbreviated syntax,
        C{expr("name")} in place of C{expr.setResultsName("name")} - 
        see L{I{__call__}<__call__>}.

        Example::
            date_str = (integer.setResultsName("year") + '/' 
                        + integer.setResultsName("month") + '/' 
                        + integer.setResultsName("day"))

            # equivalent form:
            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
        """
        newself = self.copy()
        if name.endswith("*"):
            name = name[:-1]
            listAllMatches=True
        newself.resultsName = name
        newself.modalResults = not listAllMatches
        return newself

    def setBreak(self,breakFlag = True):
        """Method to invoke the Python pdb debugger when this element is
           about to be parsed. Set C{breakFlag} to True to enable, False to
           disable.
        """
        if breakFlag:
            _parseMethod = self._parse
            def breaker(instring, loc, doActions=True, callPreParse=True):
                import pdb
                pdb.set_trace()
                return _parseMethod( instring, loc, doActions, callPreParse )
            breaker._originalParseMethod = _parseMethod
            self._parse = breaker
        else:
            if hasattr(self._parse,"_originalParseMethod"):
                self._parse = self._parse._originalParseMethod
        return self

    def setParseAction( self, *fns, **kwargs ):
        """
        Define action to perform when successfully matching parse element definition.
        Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)},
        C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where:
         - s   = the original string being parsed (see note below)
         - loc = the location of the matching substring
         - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object
        If the functions in fns modify the tokens, they can return them as the return
        value from fn, and the modified list of tokens will replace the original.
        Otherwise, fn does not need to return any value.

        Optional keyword arguments:
         - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing

        Note: the default parsing behavior is to expand tabs in the input string
        before starting the parsing process.  See L{I{parseString}} for more information
        on parsing strings containing C{}s, and suggested methods to maintain a
        consistent view of the parsed string, the parse location, and line and column
        positions within the parsed string.
        
        Example::
            integer = Word(nums)
            date_str = integer + '/' + integer + '/' + integer

            date_str.parseString("1999/12/31")  # -> ['1999', '/', '12', '/', '31']

            # use parse action to convert to ints at parse time
            integer = Word(nums).setParseAction(lambda toks: int(toks[0]))
            date_str = integer + '/' + integer + '/' + integer

            # note that integer fields are now ints, not strings
            date_str.parseString("1999/12/31")  # -> [1999, '/', 12, '/', 31]
        """
        self.parseAction = list(map(_trim_arity, list(fns)))
        self.callDuringTry = kwargs.get("callDuringTry", False)
        return self

    def addParseAction( self, *fns, **kwargs ):
        """
        Add parse action to expression's list of parse actions. See L{I{setParseAction}}.
        
        See examples in L{I{copy}}.
        """
        self.parseAction += list(map(_trim_arity, list(fns)))
        self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False)
        return self

    def addCondition(self, *fns, **kwargs):
        """Add a boolean predicate function to expression's list of parse actions. See 
        L{I{setParseAction}} for function call signatures. Unlike C{setParseAction}, 
        functions passed to C{addCondition} need to return boolean success/fail of the condition.

        Optional keyword arguments:
         - message = define a custom message to be used in the raised exception
         - fatal   = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException
         
        Example::
            integer = Word(nums).setParseAction(lambda toks: int(toks[0]))
            year_int = integer.copy()
            year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later")
            date_str = year_int + '/' + integer + '/' + integer

            result = date_str.parseString("1999/12/31")  # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1)
        """
        msg = kwargs.get("message", "failed user-defined condition")
        exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException
        for fn in fns:
            def pa(s,l,t):
                if not bool(_trim_arity(fn)(s,l,t)):
                    raise exc_type(s,l,msg)
            self.parseAction.append(pa)
        self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False)
        return self

    def setFailAction( self, fn ):
        """Define action to perform if parsing fails at this expression.
           Fail acton fn is a callable function that takes the arguments
           C{fn(s,loc,expr,err)} where:
            - s = string being parsed
            - loc = location where expression match was attempted and failed
            - expr = the parse expression that failed
            - err = the exception thrown
           The function returns no value.  It may throw C{L{ParseFatalException}}
           if it is desired to stop parsing immediately."""
        self.failAction = fn
        return self

    def _skipIgnorables( self, instring, loc ):
        exprsFound = True
        while exprsFound:
            exprsFound = False
            for e in self.ignoreExprs:
                try:
                    while 1:
                        loc,dummy = e._parse( instring, loc )
                        exprsFound = True
                except ParseException:
                    pass
        return loc

    def preParse( self, instring, loc ):
        if self.ignoreExprs:
            loc = self._skipIgnorables( instring, loc )

        if self.skipWhitespace:
            wt = self.whiteChars
            instrlen = len(instring)
            while loc < instrlen and instring[loc] in wt:
                loc += 1

        return loc

    def parseImpl( self, instring, loc, doActions=True ):
        return loc, []

    def postParse( self, instring, loc, tokenlist ):
        return tokenlist

    #~ @profile
    def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ):
        debugging = ( self.debug ) #and doActions )

        if debugging or self.failAction:
            #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))
            if (self.debugActions[0] ):
                self.debugActions[0]( instring, loc, self )
            if callPreParse and self.callPreparse:
                preloc = self.preParse( instring, loc )
            else:
                preloc = loc
            tokensStart = preloc
            try:
                try:
                    loc,tokens = self.parseImpl( instring, preloc, doActions )
                except IndexError:
                    raise ParseException( instring, len(instring), self.errmsg, self )
            except ParseBaseException as err:
                #~ print ("Exception raised:", err)
                if self.debugActions[2]:
                    self.debugActions[2]( instring, tokensStart, self, err )
                if self.failAction:
                    self.failAction( instring, tokensStart, self, err )
                raise
        else:
            if callPreParse and self.callPreparse:
                preloc = self.preParse( instring, loc )
            else:
                preloc = loc
            tokensStart = preloc
            if self.mayIndexError or loc >= len(instring):
                try:
                    loc,tokens = self.parseImpl( instring, preloc, doActions )
                except IndexError:
                    raise ParseException( instring, len(instring), self.errmsg, self )
            else:
                loc,tokens = self.parseImpl( instring, preloc, doActions )

        tokens = self.postParse( instring, loc, tokens )

        retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults )
        if self.parseAction and (doActions or self.callDuringTry):
            if debugging:
                try:
                    for fn in self.parseAction:
                        tokens = fn( instring, tokensStart, retTokens )
                        if tokens is not None:
                            retTokens = ParseResults( tokens,
                                                      self.resultsName,
                                                      asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
                                                      modal=self.modalResults )
                except ParseBaseException as err:
                    #~ print "Exception raised in user parse action:", err
                    if (self.debugActions[2] ):
                        self.debugActions[2]( instring, tokensStart, self, err )
                    raise
            else:
                for fn in self.parseAction:
                    tokens = fn( instring, tokensStart, retTokens )
                    if tokens is not None:
                        retTokens = ParseResults( tokens,
                                                  self.resultsName,
                                                  asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
                                                  modal=self.modalResults )

        if debugging:
            #~ print ("Matched",self,"->",retTokens.asList())
            if (self.debugActions[1] ):
                self.debugActions[1]( instring, tokensStart, loc, self, retTokens )

        return loc, retTokens

    def tryParse( self, instring, loc ):
        try:
            return self._parse( instring, loc, doActions=False )[0]
        except ParseFatalException:
            raise ParseException( instring, loc, self.errmsg, self)
    
    def canParseNext(self, instring, loc):
        try:
            self.tryParse(instring, loc)
        except (ParseException, IndexError):
            return False
        else:
            return True

    class _UnboundedCache(object):
        def __init__(self):
            cache = {}
            self.not_in_cache = not_in_cache = object()

            def get(self, key):
                return cache.get(key, not_in_cache)

            def set(self, key, value):
                cache[key] = value

            def clear(self):
                cache.clear()

            self.get = types.MethodType(get, self)
            self.set = types.MethodType(set, self)
            self.clear = types.MethodType(clear, self)

    if _OrderedDict is not None:
        class _FifoCache(object):
            def __init__(self, size):
                self.not_in_cache = not_in_cache = object()

                cache = _OrderedDict()

                def get(self, key):
                    return cache.get(key, not_in_cache)

                def set(self, key, value):
                    cache[key] = value
                    if len(cache) > size:
                        cache.popitem(False)

                def clear(self):
                    cache.clear()

                self.get = types.MethodType(get, self)
                self.set = types.MethodType(set, self)
                self.clear = types.MethodType(clear, self)

    else:
        class _FifoCache(object):
            def __init__(self, size):
                self.not_in_cache = not_in_cache = object()

                cache = {}
                key_fifo = collections.deque([], size)

                def get(self, key):
                    return cache.get(key, not_in_cache)

                def set(self, key, value):
                    cache[key] = value
                    if len(cache) > size:
                        cache.pop(key_fifo.popleft(), None)
                    key_fifo.append(key)

                def clear(self):
                    cache.clear()
                    key_fifo.clear()

                self.get = types.MethodType(get, self)
                self.set = types.MethodType(set, self)
                self.clear = types.MethodType(clear, self)

    # argument cache for optimizing repeated calls when backtracking through recursive expressions
    packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail
    packrat_cache_lock = RLock()
    packrat_cache_stats = [0, 0]

    # this method gets repeatedly called during backtracking with the same arguments -
    # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression
    def _parseCache( self, instring, loc, doActions=True, callPreParse=True ):
        HIT, MISS = 0, 1
        lookup = (self, instring, loc, callPreParse, doActions)
        with ParserElement.packrat_cache_lock:
            cache = ParserElement.packrat_cache
            value = cache.get(lookup)
            if value is cache.not_in_cache:
                ParserElement.packrat_cache_stats[MISS] += 1
                try:
                    value = self._parseNoCache(instring, loc, doActions, callPreParse)
                except ParseBaseException as pe:
                    # cache a copy of the exception, without the traceback
                    cache.set(lookup, pe.__class__(*pe.args))
                    raise
                else:
                    cache.set(lookup, (value[0], value[1].copy()))
                    return value
            else:
                ParserElement.packrat_cache_stats[HIT] += 1
                if isinstance(value, Exception):
                    raise value
                return (value[0], value[1].copy())

    _parse = _parseNoCache

    @staticmethod
    def resetCache():
        ParserElement.packrat_cache.clear()
        ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats)

    _packratEnabled = False
    @staticmethod
    def enablePackrat(cache_size_limit=128):
        """Enables "packrat" parsing, which adds memoizing to the parsing logic.
           Repeated parse attempts at the same string location (which happens
           often in many complex grammars) can immediately return a cached value,
           instead of re-executing parsing/validating code.  Memoizing is done of
           both valid results and parsing exceptions.
           
           Parameters:
            - cache_size_limit - (default=C{128}) - if an integer value is provided
              will limit the size of the packrat cache; if None is passed, then
              the cache size will be unbounded; if 0 is passed, the cache will
              be effectively disabled.
            
           This speedup may break existing programs that use parse actions that
           have side-effects.  For this reason, packrat parsing is disabled when
           you first import pyparsing.  To activate the packrat feature, your
           program must call the class method C{ParserElement.enablePackrat()}.  If
           your program uses C{psyco} to "compile as you go", you must call
           C{enablePackrat} before calling C{psyco.full()}.  If you do not do this,
           Python will crash.  For best results, call C{enablePackrat()} immediately
           after importing pyparsing.
           
           Example::
               import pyparsing
               pyparsing.ParserElement.enablePackrat()
        """
        if not ParserElement._packratEnabled:
            ParserElement._packratEnabled = True
            if cache_size_limit is None:
                ParserElement.packrat_cache = ParserElement._UnboundedCache()
            else:
                ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit)
            ParserElement._parse = ParserElement._parseCache

    def parseString( self, instring, parseAll=False ):
        """
        Execute the parse expression with the given string.
        This is the main interface to the client code, once the complete
        expression has been built.

        If you want the grammar to require that the entire input string be
        successfully parsed, then set C{parseAll} to True (equivalent to ending
        the grammar with C{L{StringEnd()}}).

        Note: C{parseString} implicitly calls C{expandtabs()} on the input string,
        in order to report proper column numbers in parse actions.
        If the input string contains tabs and
        the grammar uses parse actions that use the C{loc} argument to index into the
        string being parsed, you can ensure you have a consistent view of the input
        string by:
         - calling C{parseWithTabs} on your grammar before calling C{parseString}
           (see L{I{parseWithTabs}})
         - define your parse action using the full C{(s,loc,toks)} signature, and
           reference the input string using the parse action's C{s} argument
         - explictly expand the tabs in your input string before calling
           C{parseString}
        
        Example::
            Word('a').parseString('aaaaabaaa')  # -> ['aaaaa']
            Word('a').parseString('aaaaabaaa', parseAll=True)  # -> Exception: Expected end of text
        """
        ParserElement.resetCache()
        if not self.streamlined:
            self.streamline()
            #~ self.saveAsList = True
        for e in self.ignoreExprs:
            e.streamline()
        if not self.keepTabs:
            instring = instring.expandtabs()
        try:
            loc, tokens = self._parse( instring, 0 )
            if parseAll:
                loc = self.preParse( instring, loc )
                se = Empty() + StringEnd()
                se._parse( instring, loc )
        except ParseBaseException as exc:
            if ParserElement.verbose_stacktrace:
                raise
            else:
                # catch and re-raise exception from here, clears out pyparsing internal stack trace
                raise exc
        else:
            return tokens

    def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ):
        """
        Scan the input string for expression matches.  Each match will return the
        matching tokens, start location, and end location.  May be called with optional
        C{maxMatches} argument, to clip scanning after 'n' matches are found.  If
        C{overlap} is specified, then overlapping matches will be reported.

        Note that the start and end locations are reported relative to the string
        being parsed.  See L{I{parseString}} for more information on parsing
        strings with embedded tabs.

        Example::
            source = "sldjf123lsdjjkf345sldkjf879lkjsfd987"
            print(source)
            for tokens,start,end in Word(alphas).scanString(source):
                print(' '*start + '^'*(end-start))
                print(' '*start + tokens[0])
        
        prints::
        
            sldjf123lsdjjkf345sldkjf879lkjsfd987
            ^^^^^
            sldjf
                    ^^^^^^^
                    lsdjjkf
                              ^^^^^^
                              sldkjf
                                       ^^^^^^
                                       lkjsfd
        """
        if not self.streamlined:
            self.streamline()
        for e in self.ignoreExprs:
            e.streamline()

        if not self.keepTabs:
            instring = _ustr(instring).expandtabs()
        instrlen = len(instring)
        loc = 0
        preparseFn = self.preParse
        parseFn = self._parse
        ParserElement.resetCache()
        matches = 0
        try:
            while loc <= instrlen and matches < maxMatches:
                try:
                    preloc = preparseFn( instring, loc )
                    nextLoc,tokens = parseFn( instring, preloc, callPreParse=False )
                except ParseException:
                    loc = preloc+1
                else:
                    if nextLoc > loc:
                        matches += 1
                        yield tokens, preloc, nextLoc
                        if overlap:
                            nextloc = preparseFn( instring, loc )
                            if nextloc > loc:
                                loc = nextLoc
                            else:
                                loc += 1
                        else:
                            loc = nextLoc
                    else:
                        loc = preloc+1
        except ParseBaseException as exc:
            if ParserElement.verbose_stacktrace:
                raise
            else:
                # catch and re-raise exception from here, clears out pyparsing internal stack trace
                raise exc

    def transformString( self, instring ):
        """
        Extension to C{L{scanString}}, to modify matching text with modified tokens that may
        be returned from a parse action.  To use C{transformString}, define a grammar and
        attach a parse action to it that modifies the returned token list.
        Invoking C{transformString()} on a target string will then scan for matches,
        and replace the matched text patterns according to the logic in the parse
        action.  C{transformString()} returns the resulting transformed string.
        
        Example::
            wd = Word(alphas)
            wd.setParseAction(lambda toks: toks[0].title())
            
            print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york."))
        Prints::
            Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York.
        """
        out = []
        lastE = 0
        # force preservation of s, to minimize unwanted transformation of string, and to
        # keep string locs straight between transformString and scanString
        self.keepTabs = True
        try:
            for t,s,e in self.scanString( instring ):
                out.append( instring[lastE:s] )
                if t:
                    if isinstance(t,ParseResults):
                        out += t.asList()
                    elif isinstance(t,list):
                        out += t
                    else:
                        out.append(t)
                lastE = e
            out.append(instring[lastE:])
            out = [o for o in out if o]
            return "".join(map(_ustr,_flatten(out)))
        except ParseBaseException as exc:
            if ParserElement.verbose_stacktrace:
                raise
            else:
                # catch and re-raise exception from here, clears out pyparsing internal stack trace
                raise exc

    def searchString( self, instring, maxMatches=_MAX_INT ):
        """
        Another extension to C{L{scanString}}, simplifying the access to the tokens found
        to match the given parse expression.  May be called with optional
        C{maxMatches} argument, to clip searching after 'n' matches are found.
        
        Example::
            # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters
            cap_word = Word(alphas.upper(), alphas.lower())
            
            print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))
        prints::
            ['More', 'Iron', 'Lead', 'Gold', 'I']
        """
        try:
            return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ])
        except ParseBaseException as exc:
            if ParserElement.verbose_stacktrace:
                raise
            else:
                # catch and re-raise exception from here, clears out pyparsing internal stack trace
                raise exc

    def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False):
        """
        Generator method to split a string using the given expression as a separator.
        May be called with optional C{maxsplit} argument, to limit the number of splits;
        and the optional C{includeSeparators} argument (default=C{False}), if the separating
        matching text should be included in the split results.
        
        Example::        
            punc = oneOf(list(".,;:/-!?"))
            print(list(punc.split("This, this?, this sentence, is badly punctuated!")))
        prints::
            ['This', ' this', '', ' this sentence', ' is badly punctuated', '']
        """
        splits = 0
        last = 0
        for t,s,e in self.scanString(instring, maxMatches=maxsplit):
            yield instring[last:s]
            if includeSeparators:
                yield t[0]
            last = e
        yield instring[last:]

    def __add__(self, other ):
        """
        Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement
        converts them to L{Literal}s by default.
        
        Example::
            greet = Word(alphas) + "," + Word(alphas) + "!"
            hello = "Hello, World!"
            print (hello, "->", greet.parseString(hello))
        Prints::
            Hello, World! -> ['Hello', ',', 'World', '!']
        """
        if isinstance( other, basestring ):
            other = ParserElement._literalStringClass( other )
        if not isinstance( other, ParserElement ):
            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
                    SyntaxWarning, stacklevel=2)
            return None
        return And( [ self, other ] )

    def __radd__(self, other ):
        """
        Implementation of + operator when left operand is not a C{L{ParserElement}}
        """
        if isinstance( other, basestring ):
            other = ParserElement._literalStringClass( other )
        if not isinstance( other, ParserElement ):
            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
                    SyntaxWarning, stacklevel=2)
            return None
        return other + self

    def __sub__(self, other):
        """
        Implementation of - operator, returns C{L{And}} with error stop
        """
        if isinstance( other, basestring ):
            other = ParserElement._literalStringClass( other )
        if not isinstance( other, ParserElement ):
            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
                    SyntaxWarning, stacklevel=2)
            return None
        return And( [ self, And._ErrorStop(), other ] )

    def __rsub__(self, other ):
        """
        Implementation of - operator when left operand is not a C{L{ParserElement}}
        """
        if isinstance( other, basestring ):
            other = ParserElement._literalStringClass( other )
        if not isinstance( other, ParserElement ):
            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
                    SyntaxWarning, stacklevel=2)
            return None
        return other - self

    def __mul__(self,other):
        """
        Implementation of * operator, allows use of C{expr * 3} in place of
        C{expr + expr + expr}.  Expressions may also me multiplied by a 2-integer
        tuple, similar to C{{min,max}} multipliers in regular expressions.  Tuples
        may also include C{None} as in:
         - C{expr*(n,None)} or C{expr*(n,)} is equivalent
              to C{expr*n + L{ZeroOrMore}(expr)}
              (read as "at least n instances of C{expr}")
         - C{expr*(None,n)} is equivalent to C{expr*(0,n)}
              (read as "0 to n instances of C{expr}")
         - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)}
         - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)}

        Note that C{expr*(None,n)} does not raise an exception if
        more than n exprs exist in the input stream; that is,
        C{expr*(None,n)} does not enforce a maximum number of expr
        occurrences.  If this behavior is desired, then write
        C{expr*(None,n) + ~expr}
        """
        if isinstance(other,int):
            minElements, optElements = other,0
        elif isinstance(other,tuple):
            other = (other + (None, None))[:2]
            if other[0] is None:
                other = (0, other[1])
            if isinstance(other[0],int) and other[1] is None:
                if other[0] == 0:
                    return ZeroOrMore(self)
                if other[0] == 1:
                    return OneOrMore(self)
                else:
                    return self*other[0] + ZeroOrMore(self)
            elif isinstance(other[0],int) and isinstance(other[1],int):
                minElements, optElements = other
                optElements -= minElements
            else:
                raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1]))
        else:
            raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other))

        if minElements < 0:
            raise ValueError("cannot multiply ParserElement by negative value")
        if optElements < 0:
            raise ValueError("second tuple value must be greater or equal to first tuple value")
        if minElements == optElements == 0:
            raise ValueError("cannot multiply ParserElement by 0 or (0,0)")

        if (optElements):
            def makeOptionalList(n):
                if n>1:
                    return Optional(self + makeOptionalList(n-1))
                else:
                    return Optional(self)
            if minElements:
                if minElements == 1:
                    ret = self + makeOptionalList(optElements)
                else:
                    ret = And([self]*minElements) + makeOptionalList(optElements)
            else:
                ret = makeOptionalList(optElements)
        else:
            if minElements == 1:
                ret = self
            else:
                ret = And([self]*minElements)
        return ret

    def __rmul__(self, other):
        return self.__mul__(other)

    def __or__(self, other ):
        """
        Implementation of | operator - returns C{L{MatchFirst}}
        """
        if isinstance( other, basestring ):
            other = ParserElement._literalStringClass( other )
        if not isinstance( other, ParserElement ):
            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
                    SyntaxWarning, stacklevel=2)
            return None
        return MatchFirst( [ self, other ] )

    def __ror__(self, other ):
        """
        Implementation of | operator when left operand is not a C{L{ParserElement}}
        """
        if isinstance( other, basestring ):
            other = ParserElement._literalStringClass( other )
        if not isinstance( other, ParserElement ):
            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
                    SyntaxWarning, stacklevel=2)
            return None
        return other | self

    def __xor__(self, other ):
        """
        Implementation of ^ operator - returns C{L{Or}}
        """
        if isinstance( other, basestring ):
            other = ParserElement._literalStringClass( other )
        if not isinstance( other, ParserElement ):
            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
                    SyntaxWarning, stacklevel=2)
            return None
        return Or( [ self, other ] )

    def __rxor__(self, other ):
        """
        Implementation of ^ operator when left operand is not a C{L{ParserElement}}
        """
        if isinstance( other, basestring ):
            other = ParserElement._literalStringClass( other )
        if not isinstance( other, ParserElement ):
            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
                    SyntaxWarning, stacklevel=2)
            return None
        return other ^ self

    def __and__(self, other ):
        """
        Implementation of & operator - returns C{L{Each}}
        """
        if isinstance( other, basestring ):
            other = ParserElement._literalStringClass( other )
        if not isinstance( other, ParserElement ):
            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
                    SyntaxWarning, stacklevel=2)
            return None
        return Each( [ self, other ] )

    def __rand__(self, other ):
        """
        Implementation of & operator when left operand is not a C{L{ParserElement}}
        """
        if isinstance( other, basestring ):
            other = ParserElement._literalStringClass( other )
        if not isinstance( other, ParserElement ):
            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
                    SyntaxWarning, stacklevel=2)
            return None
        return other & self

    def __invert__( self ):
        """
        Implementation of ~ operator - returns C{L{NotAny}}
        """
        return NotAny( self )

    def __call__(self, name=None):
        """
        Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}.
        
        If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be
        passed as C{True}.
           
        If C{name} is omitted, same as calling C{L{copy}}.

        Example::
            # these are equivalent
            userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno")
            userdata = Word(alphas)("name") + Word(nums+"-")("socsecno")             
        """
        if name is not None:
            return self.setResultsName(name)
        else:
            return self.copy()

    def suppress( self ):
        """
        Suppresses the output of this C{ParserElement}; useful to keep punctuation from
        cluttering up returned output.
        """
        return Suppress( self )

    def leaveWhitespace( self ):
        """
        Disables the skipping of whitespace before matching the characters in the
        C{ParserElement}'s defined pattern.  This is normally only used internally by
        the pyparsing module, but may be needed in some whitespace-sensitive grammars.
        """
        self.skipWhitespace = False
        return self

    def setWhitespaceChars( self, chars ):
        """
        Overrides the default whitespace chars
        """
        self.skipWhitespace = True
        self.whiteChars = chars
        self.copyDefaultWhiteChars = False
        return self

    def parseWithTabs( self ):
        """
        Overrides default behavior to expand C{}s to spaces before parsing the input string.
        Must be called before C{parseString} when the input grammar contains elements that
        match C{} characters.
        """
        self.keepTabs = True
        return self

    def ignore( self, other ):
        """
        Define expression to be ignored (e.g., comments) while doing pattern
        matching; may be called repeatedly, to define multiple comment or other
        ignorable patterns.
        
        Example::
            patt = OneOrMore(Word(alphas))
            patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj']
            
            patt.ignore(cStyleComment)
            patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd']
        """
        if isinstance(other, basestring):
            other = Suppress(other)

        if isinstance( other, Suppress ):
            if other not in self.ignoreExprs:
                self.ignoreExprs.append(other)
        else:
            self.ignoreExprs.append( Suppress( other.copy() ) )
        return self

    def setDebugActions( self, startAction, successAction, exceptionAction ):
        """
        Enable display of debugging messages while doing pattern matching.
        """
        self.debugActions = (startAction or _defaultStartDebugAction,
                             successAction or _defaultSuccessDebugAction,
                             exceptionAction or _defaultExceptionDebugAction)
        self.debug = True
        return self

    def setDebug( self, flag=True ):
        """
        Enable display of debugging messages while doing pattern matching.
        Set C{flag} to True to enable, False to disable.

        Example::
            wd = Word(alphas).setName("alphaword")
            integer = Word(nums).setName("numword")
            term = wd | integer
            
            # turn on debugging for wd
            wd.setDebug()

            OneOrMore(term).parseString("abc 123 xyz 890")
        
        prints::
            Match alphaword at loc 0(1,1)
            Matched alphaword -> ['abc']
            Match alphaword at loc 3(1,4)
            Exception raised:Expected alphaword (at char 4), (line:1, col:5)
            Match alphaword at loc 7(1,8)
            Matched alphaword -> ['xyz']
            Match alphaword at loc 11(1,12)
            Exception raised:Expected alphaword (at char 12), (line:1, col:13)
            Match alphaword at loc 15(1,16)
            Exception raised:Expected alphaword (at char 15), (line:1, col:16)

        The output shown is that produced by the default debug actions - custom debug actions can be
        specified using L{setDebugActions}. Prior to attempting
        to match the C{wd} expression, the debugging message C{"Match  at loc (,)"}
        is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"}
        message is shown. Also note the use of L{setName} to assign a human-readable name to the expression,
        which makes debugging and exception messages easier to understand - for instance, the default
        name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}.
        """
        if flag:
            self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction )
        else:
            self.debug = False
        return self

    def __str__( self ):
        return self.name

    def __repr__( self ):
        return _ustr(self)

    def streamline( self ):
        self.streamlined = True
        self.strRepr = None
        return self

    def checkRecursion( self, parseElementList ):
        pass

    def validate( self, validateTrace=[] ):
        """
        Check defined expressions for valid structure, check for infinite recursive definitions.
        """
        self.checkRecursion( [] )

    def parseFile( self, file_or_filename, parseAll=False ):
        """
        Execute the parse expression on the given file or filename.
        If a filename is specified (instead of a file object),
        the entire file is opened, read, and closed before parsing.
        """
        try:
            file_contents = file_or_filename.read()
        except AttributeError:
            with open(file_or_filename, "r") as f:
                file_contents = f.read()
        try:
            return self.parseString(file_contents, parseAll)
        except ParseBaseException as exc:
            if ParserElement.verbose_stacktrace:
                raise
            else:
                # catch and re-raise exception from here, clears out pyparsing internal stack trace
                raise exc

    def __eq__(self,other):
        if isinstance(other, ParserElement):
            return self is other or vars(self) == vars(other)
        elif isinstance(other, basestring):
            return self.matches(other)
        else:
            return super(ParserElement,self)==other

    def __ne__(self,other):
        return not (self == other)

    def __hash__(self):
        return hash(id(self))

    def __req__(self,other):
        return self == other

    def __rne__(self,other):
        return not (self == other)

    def matches(self, testString, parseAll=True):
        """
        Method for quick testing of a parser against a test string. Good for simple 
        inline microtests of sub expressions while building up larger parser.
           
        Parameters:
         - testString - to test against this expression for a match
         - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests
            
        Example::
            expr = Word(nums)
            assert expr.matches("100")
        """
        try:
            self.parseString(_ustr(testString), parseAll=parseAll)
            return True
        except ParseBaseException:
            return False
                
    def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False):
        """
        Execute the parse expression on a series of test strings, showing each
        test, the parsed results or where the parse failed. Quick and easy way to
        run a parse expression against a list of sample strings.
           
        Parameters:
         - tests - a list of separate test strings, or a multiline string of test strings
         - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests           
         - comment - (default=C{'#'}) - expression for indicating embedded comments in the test 
              string; pass None to disable comment filtering
         - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline;
              if False, only dump nested list
         - printResults - (default=C{True}) prints test output to stdout
         - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing

        Returns: a (success, results) tuple, where success indicates that all tests succeeded
        (or failed if C{failureTests} is True), and the results contain a list of lines of each 
        test's output
        
        Example::
            number_expr = pyparsing_common.number.copy()

            result = number_expr.runTests('''
                # unsigned integer
                100
                # negative integer
                -100
                # float with scientific notation
                6.02e23
                # integer with scientific notation
                1e-12
                ''')
            print("Success" if result[0] else "Failed!")

            result = number_expr.runTests('''
                # stray character
                100Z
                # missing leading digit before '.'
                -.100
                # too many '.'
                3.14.159
                ''', failureTests=True)
            print("Success" if result[0] else "Failed!")
        prints::
            # unsigned integer
            100
            [100]

            # negative integer
            -100
            [-100]

            # float with scientific notation
            6.02e23
            [6.02e+23]

            # integer with scientific notation
            1e-12
            [1e-12]

            Success
            
            # stray character
            100Z
               ^
            FAIL: Expected end of text (at char 3), (line:1, col:4)

            # missing leading digit before '.'
            -.100
            ^
            FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1)

            # too many '.'
            3.14.159
                ^
            FAIL: Expected end of text (at char 4), (line:1, col:5)

            Success

        Each test string must be on a single line. If you want to test a string that spans multiple
        lines, create a test like this::

            expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines")
        
        (Note that this is a raw string literal, you must include the leading 'r'.)
        """
        if isinstance(tests, basestring):
            tests = list(map(str.strip, tests.rstrip().splitlines()))
        if isinstance(comment, basestring):
            comment = Literal(comment)
        allResults = []
        comments = []
        success = True
        for t in tests:
            if comment is not None and comment.matches(t, False) or comments and not t:
                comments.append(t)
                continue
            if not t:
                continue
            out = ['\n'.join(comments), t]
            comments = []
            try:
                t = t.replace(r'\n','\n')
                result = self.parseString(t, parseAll=parseAll)
                out.append(result.dump(full=fullDump))
                success = success and not failureTests
            except ParseBaseException as pe:
                fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else ""
                if '\n' in t:
                    out.append(line(pe.loc, t))
                    out.append(' '*(col(pe.loc,t)-1) + '^' + fatal)
                else:
                    out.append(' '*pe.loc + '^' + fatal)
                out.append("FAIL: " + str(pe))
                success = success and failureTests
                result = pe
            except Exception as exc:
                out.append("FAIL-EXCEPTION: " + str(exc))
                success = success and failureTests
                result = exc

            if printResults:
                if fullDump:
                    out.append('')
                print('\n'.join(out))

            allResults.append((t, result))
        
        return success, allResults

        
class Token(ParserElement):
    """
    Abstract C{ParserElement} subclass, for defining atomic matching patterns.
    """
    def __init__( self ):
        super(Token,self).__init__( savelist=False )


class Empty(Token):
    """
    An empty token, will always match.
    """
    def __init__( self ):
        super(Empty,self).__init__()
        self.name = "Empty"
        self.mayReturnEmpty = True
        self.mayIndexError = False


class NoMatch(Token):
    """
    A token that will never match.
    """
    def __init__( self ):
        super(NoMatch,self).__init__()
        self.name = "NoMatch"
        self.mayReturnEmpty = True
        self.mayIndexError = False
        self.errmsg = "Unmatchable token"

    def parseImpl( self, instring, loc, doActions=True ):
        raise ParseException(instring, loc, self.errmsg, self)


class Literal(Token):
    """
    Token to exactly match a specified string.
    
    Example::
        Literal('blah').parseString('blah')  # -> ['blah']
        Literal('blah').parseString('blahfooblah')  # -> ['blah']
        Literal('blah').parseString('bla')  # -> Exception: Expected "blah"
    
    For case-insensitive matching, use L{CaselessLiteral}.
    
    For keyword matching (force word break before and after the matched string),
    use L{Keyword} or L{CaselessKeyword}.
    """
    def __init__( self, matchString ):
        super(Literal,self).__init__()
        self.match = matchString
        self.matchLen = len(matchString)
        try:
            self.firstMatchChar = matchString[0]
        except IndexError:
            warnings.warn("null string passed to Literal; use Empty() instead",
                            SyntaxWarning, stacklevel=2)
            self.__class__ = Empty
        self.name = '"%s"' % _ustr(self.match)
        self.errmsg = "Expected " + self.name
        self.mayReturnEmpty = False
        self.mayIndexError = False

    # Performance tuning: this routine gets called a *lot*
    # if this is a single character match string  and the first character matches,
    # short-circuit as quickly as possible, and avoid calling startswith
    #~ @profile
    def parseImpl( self, instring, loc, doActions=True ):
        if (instring[loc] == self.firstMatchChar and
            (self.matchLen==1 or instring.startswith(self.match,loc)) ):
            return loc+self.matchLen, self.match
        raise ParseException(instring, loc, self.errmsg, self)
_L = Literal
ParserElement._literalStringClass = Literal

class Keyword(Token):
    """
    Token to exactly match a specified string as a keyword, that is, it must be
    immediately followed by a non-keyword character.  Compare with C{L{Literal}}:
     - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}.
     - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'}
    Accepts two optional constructor arguments in addition to the keyword string:
     - C{identChars} is a string of characters that would be valid identifier characters,
          defaulting to all alphanumerics + "_" and "$"
     - C{caseless} allows case-insensitive matching, default is C{False}.
       
    Example::
        Keyword("start").parseString("start")  # -> ['start']
        Keyword("start").parseString("starting")  # -> Exception

    For case-insensitive matching, use L{CaselessKeyword}.
    """
    DEFAULT_KEYWORD_CHARS = alphanums+"_$"

    def __init__( self, matchString, identChars=None, caseless=False ):
        super(Keyword,self).__init__()
        if identChars is None:
            identChars = Keyword.DEFAULT_KEYWORD_CHARS
        self.match = matchString
        self.matchLen = len(matchString)
        try:
            self.firstMatchChar = matchString[0]
        except IndexError:
            warnings.warn("null string passed to Keyword; use Empty() instead",
                            SyntaxWarning, stacklevel=2)
        self.name = '"%s"' % self.match
        self.errmsg = "Expected " + self.name
        self.mayReturnEmpty = False
        self.mayIndexError = False
        self.caseless = caseless
        if caseless:
            self.caselessmatch = matchString.upper()
            identChars = identChars.upper()
        self.identChars = set(identChars)

    def parseImpl( self, instring, loc, doActions=True ):
        if self.caseless:
            if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
                 (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and
                 (loc == 0 or instring[loc-1].upper() not in self.identChars) ):
                return loc+self.matchLen, self.match
        else:
            if (instring[loc] == self.firstMatchChar and
                (self.matchLen==1 or instring.startswith(self.match,loc)) and
                (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and
                (loc == 0 or instring[loc-1] not in self.identChars) ):
                return loc+self.matchLen, self.match
        raise ParseException(instring, loc, self.errmsg, self)

    def copy(self):
        c = super(Keyword,self).copy()
        c.identChars = Keyword.DEFAULT_KEYWORD_CHARS
        return c

    @staticmethod
    def setDefaultKeywordChars( chars ):
        """Overrides the default Keyword chars
        """
        Keyword.DEFAULT_KEYWORD_CHARS = chars

class CaselessLiteral(Literal):
    """
    Token to match a specified string, ignoring case of letters.
    Note: the matched results will always be in the case of the given
    match string, NOT the case of the input text.

    Example::
        OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD']
        
    (Contrast with example for L{CaselessKeyword}.)
    """
    def __init__( self, matchString ):
        super(CaselessLiteral,self).__init__( matchString.upper() )
        # Preserve the defining literal.
        self.returnString = matchString
        self.name = "'%s'" % self.returnString
        self.errmsg = "Expected " + self.name

    def parseImpl( self, instring, loc, doActions=True ):
        if instring[ loc:loc+self.matchLen ].upper() == self.match:
            return loc+self.matchLen, self.returnString
        raise ParseException(instring, loc, self.errmsg, self)

class CaselessKeyword(Keyword):
    """
    Caseless version of L{Keyword}.

    Example::
        OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD']
        
    (Contrast with example for L{CaselessLiteral}.)
    """
    def __init__( self, matchString, identChars=None ):
        super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True )

    def parseImpl( self, instring, loc, doActions=True ):
        if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
             (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ):
            return loc+self.matchLen, self.match
        raise ParseException(instring, loc, self.errmsg, self)

class CloseMatch(Token):
    """
    A variation on L{Literal} which matches "close" matches, that is, 
    strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters:
     - C{match_string} - string to be matched
     - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match
    
    The results from a successful parse will contain the matched text from the input string and the following named results:
     - C{mismatches} - a list of the positions within the match_string where mismatches were found
     - C{original} - the original match_string used to compare against the input string
    
    If C{mismatches} is an empty list, then the match was an exact match.
    
    Example::
        patt = CloseMatch("ATCATCGAATGGA")
        patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']})
        patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1)

        # exact match
        patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']})

        # close match allowing up to 2 mismatches
        patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2)
        patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']})
    """
    def __init__(self, match_string, maxMismatches=1):
        super(CloseMatch,self).__init__()
        self.name = match_string
        self.match_string = match_string
        self.maxMismatches = maxMismatches
        self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches)
        self.mayIndexError = False
        self.mayReturnEmpty = False

    def parseImpl( self, instring, loc, doActions=True ):
        start = loc
        instrlen = len(instring)
        maxloc = start + len(self.match_string)

        if maxloc <= instrlen:
            match_string = self.match_string
            match_stringloc = 0
            mismatches = []
            maxMismatches = self.maxMismatches

            for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)):
                src,mat = s_m
                if src != mat:
                    mismatches.append(match_stringloc)
                    if len(mismatches) > maxMismatches:
                        break
            else:
                loc = match_stringloc + 1
                results = ParseResults([instring[start:loc]])
                results['original'] = self.match_string
                results['mismatches'] = mismatches
                return loc, results

        raise ParseException(instring, loc, self.errmsg, self)


class Word(Token):
    """
    Token for matching words composed of allowed character sets.
    Defined with string containing all allowed initial characters,
    an optional string containing allowed body characters (if omitted,
    defaults to the initial character set), and an optional minimum,
    maximum, and/or exact length.  The default value for C{min} is 1 (a
    minimum value < 1 is not valid); the default values for C{max} and C{exact}
    are 0, meaning no maximum or exact length restriction. An optional
    C{excludeChars} parameter can list characters that might be found in 
    the input C{bodyChars} string; useful to define a word of all printables
    except for one or two characters, for instance.
    
    L{srange} is useful for defining custom character set strings for defining 
    C{Word} expressions, using range notation from regular expression character sets.
    
    A common mistake is to use C{Word} to match a specific literal string, as in 
    C{Word("Address")}. Remember that C{Word} uses the string argument to define
    I{sets} of matchable characters. This expression would match "Add", "AAA",
    "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'.
    To match an exact literal string, use L{Literal} or L{Keyword}.

    pyparsing includes helper strings for building Words:
     - L{alphas}
     - L{nums}
     - L{alphanums}
     - L{hexnums}
     - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.)
     - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.)
     - L{printables} (any non-whitespace character)

    Example::
        # a word composed of digits
        integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9"))
        
        # a word with a leading capital, and zero or more lowercase
        capital_word = Word(alphas.upper(), alphas.lower())

        # hostnames are alphanumeric, with leading alpha, and '-'
        hostname = Word(alphas, alphanums+'-')
        
        # roman numeral (not a strict parser, accepts invalid mix of characters)
        roman = Word("IVXLCDM")
        
        # any string of non-whitespace characters, except for ','
        csv_value = Word(printables, excludeChars=",")
    """
    def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ):
        super(Word,self).__init__()
        if excludeChars:
            initChars = ''.join(c for c in initChars if c not in excludeChars)
            if bodyChars:
                bodyChars = ''.join(c for c in bodyChars if c not in excludeChars)
        self.initCharsOrig = initChars
        self.initChars = set(initChars)
        if bodyChars :
            self.bodyCharsOrig = bodyChars
            self.bodyChars = set(bodyChars)
        else:
            self.bodyCharsOrig = initChars
            self.bodyChars = set(initChars)

        self.maxSpecified = max > 0

        if min < 1:
            raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted")

        self.minLen = min

        if max > 0:
            self.maxLen = max
        else:
            self.maxLen = _MAX_INT

        if exact > 0:
            self.maxLen = exact
            self.minLen = exact

        self.name = _ustr(self)
        self.errmsg = "Expected " + self.name
        self.mayIndexError = False
        self.asKeyword = asKeyword

        if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0):
            if self.bodyCharsOrig == self.initCharsOrig:
                self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig)
            elif len(self.initCharsOrig) == 1:
                self.reString = "%s[%s]*" % \
                                      (re.escape(self.initCharsOrig),
                                      _escapeRegexRangeChars(self.bodyCharsOrig),)
            else:
                self.reString = "[%s][%s]*" % \
                                      (_escapeRegexRangeChars(self.initCharsOrig),
                                      _escapeRegexRangeChars(self.bodyCharsOrig),)
            if self.asKeyword:
                self.reString = r"\b"+self.reString+r"\b"
            try:
                self.re = re.compile( self.reString )
            except Exception:
                self.re = None

    def parseImpl( self, instring, loc, doActions=True ):
        if self.re:
            result = self.re.match(instring,loc)
            if not result:
                raise ParseException(instring, loc, self.errmsg, self)

            loc = result.end()
            return loc, result.group()

        if not(instring[ loc ] in self.initChars):
            raise ParseException(instring, loc, self.errmsg, self)

        start = loc
        loc += 1
        instrlen = len(instring)
        bodychars = self.bodyChars
        maxloc = start + self.maxLen
        maxloc = min( maxloc, instrlen )
        while loc < maxloc and instring[loc] in bodychars:
            loc += 1

        throwException = False
        if loc - start < self.minLen:
            throwException = True
        if self.maxSpecified and loc < instrlen and instring[loc] in bodychars:
            throwException = True
        if self.asKeyword:
            if (start>0 and instring[start-1] in bodychars) or (loc4:
                    return s[:4]+"..."
                else:
                    return s

            if ( self.initCharsOrig != self.bodyCharsOrig ):
                self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) )
            else:
                self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig)

        return self.strRepr


class Regex(Token):
    """
    Token for matching strings that match a given regular expression.
    Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module.
    If the given regex contains named groups (defined using C{(?P...)}), these will be preserved as 
    named parse results.

    Example::
        realnum = Regex(r"[+-]?\d+\.\d*")
        date = Regex(r'(?P\d{4})-(?P\d\d?)-(?P\d\d?)')
        # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression
        roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})")
    """
    compiledREtype = type(re.compile("[A-Z]"))
    def __init__( self, pattern, flags=0):
        """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags."""
        super(Regex,self).__init__()

        if isinstance(pattern, basestring):
            if not pattern:
                warnings.warn("null string passed to Regex; use Empty() instead",
                        SyntaxWarning, stacklevel=2)

            self.pattern = pattern
            self.flags = flags

            try:
                self.re = re.compile(self.pattern, self.flags)
                self.reString = self.pattern
            except sre_constants.error:
                warnings.warn("invalid pattern (%s) passed to Regex" % pattern,
                    SyntaxWarning, stacklevel=2)
                raise

        elif isinstance(pattern, Regex.compiledREtype):
            self.re = pattern
            self.pattern = \
            self.reString = str(pattern)
            self.flags = flags
            
        else:
            raise ValueError("Regex may only be constructed with a string or a compiled RE object")

        self.name = _ustr(self)
        self.errmsg = "Expected " + self.name
        self.mayIndexError = False
        self.mayReturnEmpty = True

    def parseImpl( self, instring, loc, doActions=True ):
        result = self.re.match(instring,loc)
        if not result:
            raise ParseException(instring, loc, self.errmsg, self)

        loc = result.end()
        d = result.groupdict()
        ret = ParseResults(result.group())
        if d:
            for k in d:
                ret[k] = d[k]
        return loc,ret

    def __str__( self ):
        try:
            return super(Regex,self).__str__()
        except Exception:
            pass

        if self.strRepr is None:
            self.strRepr = "Re:(%s)" % repr(self.pattern)

        return self.strRepr


class QuotedString(Token):
    r"""
    Token for matching strings that are delimited by quoting characters.
    
    Defined with the following parameters:
        - quoteChar - string of one or more characters defining the quote delimiting string
        - escChar - character to escape quotes, typically backslash (default=C{None})
        - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None})
        - multiline - boolean indicating whether quotes can span multiple lines (default=C{False})
        - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True})
        - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar)
        - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True})

    Example::
        qs = QuotedString('"')
        print(qs.searchString('lsjdf "This is the quote" sldjf'))
        complex_qs = QuotedString('{{', endQuoteChar='}}')
        print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf'))
        sql_qs = QuotedString('"', escQuote='""')
        print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf'))
    prints::
        [['This is the quote']]
        [['This is the "quote"']]
        [['This is the quote with "embedded" quotes']]
    """
    def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True):
        super(QuotedString,self).__init__()

        # remove white space from quote chars - wont work anyway
        quoteChar = quoteChar.strip()
        if not quoteChar:
            warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
            raise SyntaxError()

        if endQuoteChar is None:
            endQuoteChar = quoteChar
        else:
            endQuoteChar = endQuoteChar.strip()
            if not endQuoteChar:
                warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
                raise SyntaxError()

        self.quoteChar = quoteChar
        self.quoteCharLen = len(quoteChar)
        self.firstQuoteChar = quoteChar[0]
        self.endQuoteChar = endQuoteChar
        self.endQuoteCharLen = len(endQuoteChar)
        self.escChar = escChar
        self.escQuote = escQuote
        self.unquoteResults = unquoteResults
        self.convertWhitespaceEscapes = convertWhitespaceEscapes

        if multiline:
            self.flags = re.MULTILINE | re.DOTALL
            self.pattern = r'%s(?:[^%s%s]' % \
                ( re.escape(self.quoteChar),
                  _escapeRegexRangeChars(self.endQuoteChar[0]),
                  (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
        else:
            self.flags = 0
            self.pattern = r'%s(?:[^%s\n\r%s]' % \
                ( re.escape(self.quoteChar),
                  _escapeRegexRangeChars(self.endQuoteChar[0]),
                  (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
        if len(self.endQuoteChar) > 1:
            self.pattern += (
                '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]),
                                               _escapeRegexRangeChars(self.endQuoteChar[i]))
                                    for i in range(len(self.endQuoteChar)-1,0,-1)) + ')'
                )
        if escQuote:
            self.pattern += (r'|(?:%s)' % re.escape(escQuote))
        if escChar:
            self.pattern += (r'|(?:%s.)' % re.escape(escChar))
            self.escCharReplacePattern = re.escape(self.escChar)+"(.)"
        self.pattern += (r')*%s' % re.escape(self.endQuoteChar))

        try:
            self.re = re.compile(self.pattern, self.flags)
            self.reString = self.pattern
        except sre_constants.error:
            warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern,
                SyntaxWarning, stacklevel=2)
            raise

        self.name = _ustr(self)
        self.errmsg = "Expected " + self.name
        self.mayIndexError = False
        self.mayReturnEmpty = True

    def parseImpl( self, instring, loc, doActions=True ):
        result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None
        if not result:
            raise ParseException(instring, loc, self.errmsg, self)

        loc = result.end()
        ret = result.group()

        if self.unquoteResults:

            # strip off quotes
            ret = ret[self.quoteCharLen:-self.endQuoteCharLen]

            if isinstance(ret,basestring):
                # replace escaped whitespace
                if '\\' in ret and self.convertWhitespaceEscapes:
                    ws_map = {
                        r'\t' : '\t',
                        r'\n' : '\n',
                        r'\f' : '\f',
                        r'\r' : '\r',
                    }
                    for wslit,wschar in ws_map.items():
                        ret = ret.replace(wslit, wschar)

                # replace escaped characters
                if self.escChar:
                    ret = re.sub(self.escCharReplacePattern,"\g<1>",ret)

                # replace escaped quotes
                if self.escQuote:
                    ret = ret.replace(self.escQuote, self.endQuoteChar)

        return loc, ret

    def __str__( self ):
        try:
            return super(QuotedString,self).__str__()
        except Exception:
            pass

        if self.strRepr is None:
            self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar)

        return self.strRepr


class CharsNotIn(Token):
    """
    Token for matching words composed of characters I{not} in a given set (will
    include whitespace in matched characters if not listed in the provided exclusion set - see example).
    Defined with string containing all disallowed characters, and an optional
    minimum, maximum, and/or exact length.  The default value for C{min} is 1 (a
    minimum value < 1 is not valid); the default values for C{max} and C{exact}
    are 0, meaning no maximum or exact length restriction.

    Example::
        # define a comma-separated-value as anything that is not a ','
        csv_value = CharsNotIn(',')
        print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213"))
    prints::
        ['dkls', 'lsdkjf', 's12 34', '@!#', '213']
    """
    def __init__( self, notChars, min=1, max=0, exact=0 ):
        super(CharsNotIn,self).__init__()
        self.skipWhitespace = False
        self.notChars = notChars

        if min < 1:
            raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted")

        self.minLen = min

        if max > 0:
            self.maxLen = max
        else:
            self.maxLen = _MAX_INT

        if exact > 0:
            self.maxLen = exact
            self.minLen = exact

        self.name = _ustr(self)
        self.errmsg = "Expected " + self.name
        self.mayReturnEmpty = ( self.minLen == 0 )
        self.mayIndexError = False

    def parseImpl( self, instring, loc, doActions=True ):
        if instring[loc] in self.notChars:
            raise ParseException(instring, loc, self.errmsg, self)

        start = loc
        loc += 1
        notchars = self.notChars
        maxlen = min( start+self.maxLen, len(instring) )
        while loc < maxlen and \
              (instring[loc] not in notchars):
            loc += 1

        if loc - start < self.minLen:
            raise ParseException(instring, loc, self.errmsg, self)

        return loc, instring[start:loc]

    def __str__( self ):
        try:
            return super(CharsNotIn, self).__str__()
        except Exception:
            pass

        if self.strRepr is None:
            if len(self.notChars) > 4:
                self.strRepr = "!W:(%s...)" % self.notChars[:4]
            else:
                self.strRepr = "!W:(%s)" % self.notChars

        return self.strRepr

class White(Token):
    """
    Special matching class for matching whitespace.  Normally, whitespace is ignored
    by pyparsing grammars.  This class is included when some whitespace structures
    are significant.  Define with a string containing the whitespace characters to be
    matched; default is C{" \\t\\r\\n"}.  Also takes optional C{min}, C{max}, and C{exact} arguments,
    as defined for the C{L{Word}} class.
    """
    whiteStrs = {
        " " : "",
        "\t": "",
        "\n": "",
        "\r": "",
        "\f": "",
        }
    def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0):
        super(White,self).__init__()
        self.matchWhite = ws
        self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) )
        #~ self.leaveWhitespace()
        self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite))
        self.mayReturnEmpty = True
        self.errmsg = "Expected " + self.name

        self.minLen = min

        if max > 0:
            self.maxLen = max
        else:
            self.maxLen = _MAX_INT

        if exact > 0:
            self.maxLen = exact
            self.minLen = exact

    def parseImpl( self, instring, loc, doActions=True ):
        if not(instring[ loc ] in self.matchWhite):
            raise ParseException(instring, loc, self.errmsg, self)
        start = loc
        loc += 1
        maxloc = start + self.maxLen
        maxloc = min( maxloc, len(instring) )
        while loc < maxloc and instring[loc] in self.matchWhite:
            loc += 1

        if loc - start < self.minLen:
            raise ParseException(instring, loc, self.errmsg, self)

        return loc, instring[start:loc]


class _PositionToken(Token):
    def __init__( self ):
        super(_PositionToken,self).__init__()
        self.name=self.__class__.__name__
        self.mayReturnEmpty = True
        self.mayIndexError = False

class GoToColumn(_PositionToken):
    """
    Token to advance to a specific column of input text; useful for tabular report scraping.
    """
    def __init__( self, colno ):
        super(GoToColumn,self).__init__()
        self.col = colno

    def preParse( self, instring, loc ):
        if col(loc,instring) != self.col:
            instrlen = len(instring)
            if self.ignoreExprs:
                loc = self._skipIgnorables( instring, loc )
            while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col :
                loc += 1
        return loc

    def parseImpl( self, instring, loc, doActions=True ):
        thiscol = col( loc, instring )
        if thiscol > self.col:
            raise ParseException( instring, loc, "Text not in expected column", self )
        newloc = loc + self.col - thiscol
        ret = instring[ loc: newloc ]
        return newloc, ret


class LineStart(_PositionToken):
    """
    Matches if current position is at the beginning of a line within the parse string
    
    Example::
    
        test = '''\
        AAA this line
        AAA and this line
          AAA but not this one
        B AAA and definitely not this one
        '''

        for t in (LineStart() + 'AAA' + restOfLine).searchString(test):
            print(t)
    
    Prints::
        ['AAA', ' this line']
        ['AAA', ' and this line']    

    """
    def __init__( self ):
        super(LineStart,self).__init__()
        self.errmsg = "Expected start of line"

    def parseImpl( self, instring, loc, doActions=True ):
        if col(loc, instring) == 1:
            return loc, []
        raise ParseException(instring, loc, self.errmsg, self)

class LineEnd(_PositionToken):
    """
    Matches if current position is at the end of a line within the parse string
    """
    def __init__( self ):
        super(LineEnd,self).__init__()
        self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") )
        self.errmsg = "Expected end of line"

    def parseImpl( self, instring, loc, doActions=True ):
        if loc len(instring):
            return loc, []
        else:
            raise ParseException(instring, loc, self.errmsg, self)

class WordStart(_PositionToken):
    """
    Matches if the current position is at the beginning of a Word, and
    is not preceded by any character in a given set of C{wordChars}
    (default=C{printables}). To emulate the C{\b} behavior of regular expressions,
    use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of
    the string being parsed, or at the beginning of a line.
    """
    def __init__(self, wordChars = printables):
        super(WordStart,self).__init__()
        self.wordChars = set(wordChars)
        self.errmsg = "Not at the start of a word"

    def parseImpl(self, instring, loc, doActions=True ):
        if loc != 0:
            if (instring[loc-1] in self.wordChars or
                instring[loc] not in self.wordChars):
                raise ParseException(instring, loc, self.errmsg, self)
        return loc, []

class WordEnd(_PositionToken):
    """
    Matches if the current position is at the end of a Word, and
    is not followed by any character in a given set of C{wordChars}
    (default=C{printables}). To emulate the C{\b} behavior of regular expressions,
    use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of
    the string being parsed, or at the end of a line.
    """
    def __init__(self, wordChars = printables):
        super(WordEnd,self).__init__()
        self.wordChars = set(wordChars)
        self.skipWhitespace = False
        self.errmsg = "Not at the end of a word"

    def parseImpl(self, instring, loc, doActions=True ):
        instrlen = len(instring)
        if instrlen>0 and loc maxExcLoc:
                    maxException = err
                    maxExcLoc = err.loc
            except IndexError:
                if len(instring) > maxExcLoc:
                    maxException = ParseException(instring,len(instring),e.errmsg,self)
                    maxExcLoc = len(instring)
            else:
                # save match among all matches, to retry longest to shortest
                matches.append((loc2, e))

        if matches:
            matches.sort(key=lambda x: -x[0])
            for _,e in matches:
                try:
                    return e._parse( instring, loc, doActions )
                except ParseException as err:
                    err.__traceback__ = None
                    if err.loc > maxExcLoc:
                        maxException = err
                        maxExcLoc = err.loc

        if maxException is not None:
            maxException.msg = self.errmsg
            raise maxException
        else:
            raise ParseException(instring, loc, "no defined alternatives to match", self)


    def __ixor__(self, other ):
        if isinstance( other, basestring ):
            other = ParserElement._literalStringClass( other )
        return self.append( other ) #Or( [ self, other ] )

    def __str__( self ):
        if hasattr(self,"name"):
            return self.name

        if self.strRepr is None:
            self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}"

        return self.strRepr

    def checkRecursion( self, parseElementList ):
        subRecCheckList = parseElementList[:] + [ self ]
        for e in self.exprs:
            e.checkRecursion( subRecCheckList )


class MatchFirst(ParseExpression):
    """
    Requires that at least one C{ParseExpression} is found.
    If two expressions match, the first one listed is the one that will match.
    May be constructed using the C{'|'} operator.

    Example::
        # construct MatchFirst using '|' operator
        
        # watch the order of expressions to match
        number = Word(nums) | Combine(Word(nums) + '.' + Word(nums))
        print(number.searchString("123 3.1416 789")) #  Fail! -> [['123'], ['3'], ['1416'], ['789']]

        # put more selective expression first
        number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums)
        print(number.searchString("123 3.1416 789")) #  Better -> [['123'], ['3.1416'], ['789']]
    """
    def __init__( self, exprs, savelist = False ):
        super(MatchFirst,self).__init__(exprs, savelist)
        if self.exprs:
            self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs)
        else:
            self.mayReturnEmpty = True

    def parseImpl( self, instring, loc, doActions=True ):
        maxExcLoc = -1
        maxException = None
        for e in self.exprs:
            try:
                ret = e._parse( instring, loc, doActions )
                return ret
            except ParseException as err:
                if err.loc > maxExcLoc:
                    maxException = err
                    maxExcLoc = err.loc
            except IndexError:
                if len(instring) > maxExcLoc:
                    maxException = ParseException(instring,len(instring),e.errmsg,self)
                    maxExcLoc = len(instring)

        # only got here if no expression matched, raise exception for match that made it the furthest
        else:
            if maxException is not None:
                maxException.msg = self.errmsg
                raise maxException
            else:
                raise ParseException(instring, loc, "no defined alternatives to match", self)

    def __ior__(self, other ):
        if isinstance( other, basestring ):
            other = ParserElement._literalStringClass( other )
        return self.append( other ) #MatchFirst( [ self, other ] )

    def __str__( self ):
        if hasattr(self,"name"):
            return self.name

        if self.strRepr is None:
            self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}"

        return self.strRepr

    def checkRecursion( self, parseElementList ):
        subRecCheckList = parseElementList[:] + [ self ]
        for e in self.exprs:
            e.checkRecursion( subRecCheckList )


class Each(ParseExpression):
    """
    Requires all given C{ParseExpression}s to be found, but in any order.
    Expressions may be separated by whitespace.
    May be constructed using the C{'&'} operator.

    Example::
        color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN")
        shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON")
        integer = Word(nums)
        shape_attr = "shape:" + shape_type("shape")
        posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn")
        color_attr = "color:" + color("color")
        size_attr = "size:" + integer("size")

        # use Each (using operator '&') to accept attributes in any order 
        # (shape and posn are required, color and size are optional)
        shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr)

        shape_spec.runTests('''
            shape: SQUARE color: BLACK posn: 100, 120
            shape: CIRCLE size: 50 color: BLUE posn: 50,80
            color:GREEN size:20 shape:TRIANGLE posn:20,40
            '''
            )
    prints::
        shape: SQUARE color: BLACK posn: 100, 120
        ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']]
        - color: BLACK
        - posn: ['100', ',', '120']
          - x: 100
          - y: 120
        - shape: SQUARE


        shape: CIRCLE size: 50 color: BLUE posn: 50,80
        ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']]
        - color: BLUE
        - posn: ['50', ',', '80']
          - x: 50
          - y: 80
        - shape: CIRCLE
        - size: 50


        color: GREEN size: 20 shape: TRIANGLE posn: 20,40
        ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']]
        - color: GREEN
        - posn: ['20', ',', '40']
          - x: 20
          - y: 40
        - shape: TRIANGLE
        - size: 20
    """
    def __init__( self, exprs, savelist = True ):
        super(Each,self).__init__(exprs, savelist)
        self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs)
        self.skipWhitespace = True
        self.initExprGroups = True

    def parseImpl( self, instring, loc, doActions=True ):
        if self.initExprGroups:
            self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional))
            opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ]
            opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)]
            self.optionals = opt1 + opt2
            self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ]
            self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ]
            self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ]
            self.required += self.multirequired
            self.initExprGroups = False
        tmpLoc = loc
        tmpReqd = self.required[:]
        tmpOpt  = self.optionals[:]
        matchOrder = []

        keepMatching = True
        while keepMatching:
            tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired
            failed = []
            for e in tmpExprs:
                try:
                    tmpLoc = e.tryParse( instring, tmpLoc )
                except ParseException:
                    failed.append(e)
                else:
                    matchOrder.append(self.opt1map.get(id(e),e))
                    if e in tmpReqd:
                        tmpReqd.remove(e)
                    elif e in tmpOpt:
                        tmpOpt.remove(e)
            if len(failed) == len(tmpExprs):
                keepMatching = False

        if tmpReqd:
            missing = ", ".join(_ustr(e) for e in tmpReqd)
            raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing )

        # add any unmatched Optionals, in case they have default values defined
        matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt]

        resultlist = []
        for e in matchOrder:
            loc,results = e._parse(instring,loc,doActions)
            resultlist.append(results)

        finalResults = sum(resultlist, ParseResults([]))
        return loc, finalResults

    def __str__( self ):
        if hasattr(self,"name"):
            return self.name

        if self.strRepr is None:
            self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}"

        return self.strRepr

    def checkRecursion( self, parseElementList ):
        subRecCheckList = parseElementList[:] + [ self ]
        for e in self.exprs:
            e.checkRecursion( subRecCheckList )


class ParseElementEnhance(ParserElement):
    """
    Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens.
    """
    def __init__( self, expr, savelist=False ):
        super(ParseElementEnhance,self).__init__(savelist)
        if isinstance( expr, basestring ):
            if issubclass(ParserElement._literalStringClass, Token):
                expr = ParserElement._literalStringClass(expr)
            else:
                expr = ParserElement._literalStringClass(Literal(expr))
        self.expr = expr
        self.strRepr = None
        if expr is not None:
            self.mayIndexError = expr.mayIndexError
            self.mayReturnEmpty = expr.mayReturnEmpty
            self.setWhitespaceChars( expr.whiteChars )
            self.skipWhitespace = expr.skipWhitespace
            self.saveAsList = expr.saveAsList
            self.callPreparse = expr.callPreparse
            self.ignoreExprs.extend(expr.ignoreExprs)

    def parseImpl( self, instring, loc, doActions=True ):
        if self.expr is not None:
            return self.expr._parse( instring, loc, doActions, callPreParse=False )
        else:
            raise ParseException("",loc,self.errmsg,self)

    def leaveWhitespace( self ):
        self.skipWhitespace = False
        self.expr = self.expr.copy()
        if self.expr is not None:
            self.expr.leaveWhitespace()
        return self

    def ignore( self, other ):
        if isinstance( other, Suppress ):
            if other not in self.ignoreExprs:
                super( ParseElementEnhance, self).ignore( other )
                if self.expr is not None:
                    self.expr.ignore( self.ignoreExprs[-1] )
        else:
            super( ParseElementEnhance, self).ignore( other )
            if self.expr is not None:
                self.expr.ignore( self.ignoreExprs[-1] )
        return self

    def streamline( self ):
        super(ParseElementEnhance,self).streamline()
        if self.expr is not None:
            self.expr.streamline()
        return self

    def checkRecursion( self, parseElementList ):
        if self in parseElementList:
            raise RecursiveGrammarException( parseElementList+[self] )
        subRecCheckList = parseElementList[:] + [ self ]
        if self.expr is not None:
            self.expr.checkRecursion( subRecCheckList )

    def validate( self, validateTrace=[] ):
        tmp = validateTrace[:]+[self]
        if self.expr is not None:
            self.expr.validate(tmp)
        self.checkRecursion( [] )

    def __str__( self ):
        try:
            return super(ParseElementEnhance,self).__str__()
        except Exception:
            pass

        if self.strRepr is None and self.expr is not None:
            self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) )
        return self.strRepr


class FollowedBy(ParseElementEnhance):
    """
    Lookahead matching of the given parse expression.  C{FollowedBy}
    does I{not} advance the parsing position within the input string, it only
    verifies that the specified parse expression matches at the current
    position.  C{FollowedBy} always returns a null token list.

    Example::
        # use FollowedBy to match a label only if it is followed by a ':'
        data_word = Word(alphas)
        label = data_word + FollowedBy(':')
        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
        
        OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint()
    prints::
        [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']]
    """
    def __init__( self, expr ):
        super(FollowedBy,self).__init__(expr)
        self.mayReturnEmpty = True

    def parseImpl( self, instring, loc, doActions=True ):
        self.expr.tryParse( instring, loc )
        return loc, []


class NotAny(ParseElementEnhance):
    """
    Lookahead to disallow matching with the given parse expression.  C{NotAny}
    does I{not} advance the parsing position within the input string, it only
    verifies that the specified parse expression does I{not} match at the current
    position.  Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny}
    always returns a null token list.  May be constructed using the '~' operator.

    Example::
        
    """
    def __init__( self, expr ):
        super(NotAny,self).__init__(expr)
        #~ self.leaveWhitespace()
        self.skipWhitespace = False  # do NOT use self.leaveWhitespace(), don't want to propagate to exprs
        self.mayReturnEmpty = True
        self.errmsg = "Found unwanted token, "+_ustr(self.expr)

    def parseImpl( self, instring, loc, doActions=True ):
        if self.expr.canParseNext(instring, loc):
            raise ParseException(instring, loc, self.errmsg, self)
        return loc, []

    def __str__( self ):
        if hasattr(self,"name"):
            return self.name

        if self.strRepr is None:
            self.strRepr = "~{" + _ustr(self.expr) + "}"

        return self.strRepr

class _MultipleMatch(ParseElementEnhance):
    def __init__( self, expr, stopOn=None):
        super(_MultipleMatch, self).__init__(expr)
        self.saveAsList = True
        ender = stopOn
        if isinstance(ender, basestring):
            ender = ParserElement._literalStringClass(ender)
        self.not_ender = ~ender if ender is not None else None

    def parseImpl( self, instring, loc, doActions=True ):
        self_expr_parse = self.expr._parse
        self_skip_ignorables = self._skipIgnorables
        check_ender = self.not_ender is not None
        if check_ender:
            try_not_ender = self.not_ender.tryParse
        
        # must be at least one (but first see if we are the stopOn sentinel;
        # if so, fail)
        if check_ender:
            try_not_ender(instring, loc)
        loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False )
        try:
            hasIgnoreExprs = (not not self.ignoreExprs)
            while 1:
                if check_ender:
                    try_not_ender(instring, loc)
                if hasIgnoreExprs:
                    preloc = self_skip_ignorables( instring, loc )
                else:
                    preloc = loc
                loc, tmptokens = self_expr_parse( instring, preloc, doActions )
                if tmptokens or tmptokens.haskeys():
                    tokens += tmptokens
        except (ParseException,IndexError):
            pass

        return loc, tokens
        
class OneOrMore(_MultipleMatch):
    """
    Repetition of one or more of the given expression.
    
    Parameters:
     - expr - expression that must match one or more times
     - stopOn - (default=C{None}) - expression for a terminating sentinel
          (only required if the sentinel would ordinarily match the repetition 
          expression)          

    Example::
        data_word = Word(alphas)
        label = data_word + FollowedBy(':')
        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join))

        text = "shape: SQUARE posn: upper left color: BLACK"
        OneOrMore(attr_expr).parseString(text).pprint()  # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']]

        # use stopOn attribute for OneOrMore to avoid reading label string as part of the data
        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
        OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']]
        
        # could also be written as
        (attr_expr * (1,)).parseString(text).pprint()
    """

    def __str__( self ):
        if hasattr(self,"name"):
            return self.name

        if self.strRepr is None:
            self.strRepr = "{" + _ustr(self.expr) + "}..."

        return self.strRepr

class ZeroOrMore(_MultipleMatch):
    """
    Optional repetition of zero or more of the given expression.
    
    Parameters:
     - expr - expression that must match zero or more times
     - stopOn - (default=C{None}) - expression for a terminating sentinel
          (only required if the sentinel would ordinarily match the repetition 
          expression)          

    Example: similar to L{OneOrMore}
    """
    def __init__( self, expr, stopOn=None):
        super(ZeroOrMore,self).__init__(expr, stopOn=stopOn)
        self.mayReturnEmpty = True
        
    def parseImpl( self, instring, loc, doActions=True ):
        try:
            return super(ZeroOrMore, self).parseImpl(instring, loc, doActions)
        except (ParseException,IndexError):
            return loc, []

    def __str__( self ):
        if hasattr(self,"name"):
            return self.name

        if self.strRepr is None:
            self.strRepr = "[" + _ustr(self.expr) + "]..."

        return self.strRepr

class _NullToken(object):
    def __bool__(self):
        return False
    __nonzero__ = __bool__
    def __str__(self):
        return ""

_optionalNotMatched = _NullToken()
class Optional(ParseElementEnhance):
    """
    Optional matching of the given expression.

    Parameters:
     - expr - expression that must match zero or more times
     - default (optional) - value to be returned if the optional expression is not found.

    Example::
        # US postal code can be a 5-digit zip, plus optional 4-digit qualifier
        zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4)))
        zip.runTests('''
            # traditional ZIP code
            12345
            
            # ZIP+4 form
            12101-0001
            
            # invalid ZIP
            98765-
            ''')
    prints::
        # traditional ZIP code
        12345
        ['12345']

        # ZIP+4 form
        12101-0001
        ['12101-0001']

        # invalid ZIP
        98765-
             ^
        FAIL: Expected end of text (at char 5), (line:1, col:6)
    """
    def __init__( self, expr, default=_optionalNotMatched ):
        super(Optional,self).__init__( expr, savelist=False )
        self.saveAsList = self.expr.saveAsList
        self.defaultValue = default
        self.mayReturnEmpty = True

    def parseImpl( self, instring, loc, doActions=True ):
        try:
            loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False )
        except (ParseException,IndexError):
            if self.defaultValue is not _optionalNotMatched:
                if self.expr.resultsName:
                    tokens = ParseResults([ self.defaultValue ])
                    tokens[self.expr.resultsName] = self.defaultValue
                else:
                    tokens = [ self.defaultValue ]
            else:
                tokens = []
        return loc, tokens

    def __str__( self ):
        if hasattr(self,"name"):
            return self.name

        if self.strRepr is None:
            self.strRepr = "[" + _ustr(self.expr) + "]"

        return self.strRepr

class SkipTo(ParseElementEnhance):
    """
    Token for skipping over all undefined text until the matched expression is found.

    Parameters:
     - expr - target expression marking the end of the data to be skipped
     - include - (default=C{False}) if True, the target expression is also parsed 
          (the skipped text and target expression are returned as a 2-element list).
     - ignore - (default=C{None}) used to define grammars (typically quoted strings and 
          comments) that might contain false matches to the target expression
     - failOn - (default=C{None}) define expressions that are not allowed to be 
          included in the skipped test; if found before the target expression is found, 
          the SkipTo is not a match

    Example::
        report = '''
            Outstanding Issues Report - 1 Jan 2000

               # | Severity | Description                               |  Days Open
            -----+----------+-------------------------------------------+-----------
             101 | Critical | Intermittent system crash                 |          6
              94 | Cosmetic | Spelling error on Login ('log|n')         |         14
              79 | Minor    | System slow when running too many reports |         47
            '''
        integer = Word(nums)
        SEP = Suppress('|')
        # use SkipTo to simply match everything up until the next SEP
        # - ignore quoted strings, so that a '|' character inside a quoted string does not match
        # - parse action will call token.strip() for each matched token, i.e., the description body
        string_data = SkipTo(SEP, ignore=quotedString)
        string_data.setParseAction(tokenMap(str.strip))
        ticket_expr = (integer("issue_num") + SEP 
                      + string_data("sev") + SEP 
                      + string_data("desc") + SEP 
                      + integer("days_open"))
        
        for tkt in ticket_expr.searchString(report):
            print tkt.dump()
    prints::
        ['101', 'Critical', 'Intermittent system crash', '6']
        - days_open: 6
        - desc: Intermittent system crash
        - issue_num: 101
        - sev: Critical
        ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14']
        - days_open: 14
        - desc: Spelling error on Login ('log|n')
        - issue_num: 94
        - sev: Cosmetic
        ['79', 'Minor', 'System slow when running too many reports', '47']
        - days_open: 47
        - desc: System slow when running too many reports
        - issue_num: 79
        - sev: Minor
    """
    def __init__( self, other, include=False, ignore=None, failOn=None ):
        super( SkipTo, self ).__init__( other )
        self.ignoreExpr = ignore
        self.mayReturnEmpty = True
        self.mayIndexError = False
        self.includeMatch = include
        self.asList = False
        if isinstance(failOn, basestring):
            self.failOn = ParserElement._literalStringClass(failOn)
        else:
            self.failOn = failOn
        self.errmsg = "No match found for "+_ustr(self.expr)

    def parseImpl( self, instring, loc, doActions=True ):
        startloc = loc
        instrlen = len(instring)
        expr = self.expr
        expr_parse = self.expr._parse
        self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None
        self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None
        
        tmploc = loc
        while tmploc <= instrlen:
            if self_failOn_canParseNext is not None:
                # break if failOn expression matches
                if self_failOn_canParseNext(instring, tmploc):
                    break
                    
            if self_ignoreExpr_tryParse is not None:
                # advance past ignore expressions
                while 1:
                    try:
                        tmploc = self_ignoreExpr_tryParse(instring, tmploc)
                    except ParseBaseException:
                        break
            
            try:
                expr_parse(instring, tmploc, doActions=False, callPreParse=False)
            except (ParseException, IndexError):
                # no match, advance loc in string
                tmploc += 1
            else:
                # matched skipto expr, done
                break

        else:
            # ran off the end of the input string without matching skipto expr, fail
            raise ParseException(instring, loc, self.errmsg, self)

        # build up return values
        loc = tmploc
        skiptext = instring[startloc:loc]
        skipresult = ParseResults(skiptext)
        
        if self.includeMatch:
            loc, mat = expr_parse(instring,loc,doActions,callPreParse=False)
            skipresult += mat

        return loc, skipresult

class Forward(ParseElementEnhance):
    """
    Forward declaration of an expression to be defined later -
    used for recursive grammars, such as algebraic infix notation.
    When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator.

    Note: take care when assigning to C{Forward} not to overlook precedence of operators.
    Specifically, '|' has a lower precedence than '<<', so that::
        fwdExpr << a | b | c
    will actually be evaluated as::
        (fwdExpr << a) | b | c
    thereby leaving b and c out as parseable alternatives.  It is recommended that you
    explicitly group the values inserted into the C{Forward}::
        fwdExpr << (a | b | c)
    Converting to use the '<<=' operator instead will avoid this problem.

    See L{ParseResults.pprint} for an example of a recursive parser created using
    C{Forward}.
    """
    def __init__( self, other=None ):
        super(Forward,self).__init__( other, savelist=False )

    def __lshift__( self, other ):
        if isinstance( other, basestring ):
            other = ParserElement._literalStringClass(other)
        self.expr = other
        self.strRepr = None
        self.mayIndexError = self.expr.mayIndexError
        self.mayReturnEmpty = self.expr.mayReturnEmpty
        self.setWhitespaceChars( self.expr.whiteChars )
        self.skipWhitespace = self.expr.skipWhitespace
        self.saveAsList = self.expr.saveAsList
        self.ignoreExprs.extend(self.expr.ignoreExprs)
        return self
        
    def __ilshift__(self, other):
        return self << other
    
    def leaveWhitespace( self ):
        self.skipWhitespace = False
        return self

    def streamline( self ):
        if not self.streamlined:
            self.streamlined = True
            if self.expr is not None:
                self.expr.streamline()
        return self

    def validate( self, validateTrace=[] ):
        if self not in validateTrace:
            tmp = validateTrace[:]+[self]
            if self.expr is not None:
                self.expr.validate(tmp)
        self.checkRecursion([])

    def __str__( self ):
        if hasattr(self,"name"):
            return self.name
        return self.__class__.__name__ + ": ..."

        # stubbed out for now - creates awful memory and perf issues
        self._revertClass = self.__class__
        self.__class__ = _ForwardNoRecurse
        try:
            if self.expr is not None:
                retString = _ustr(self.expr)
            else:
                retString = "None"
        finally:
            self.__class__ = self._revertClass
        return self.__class__.__name__ + ": " + retString

    def copy(self):
        if self.expr is not None:
            return super(Forward,self).copy()
        else:
            ret = Forward()
            ret <<= self
            return ret

class _ForwardNoRecurse(Forward):
    def __str__( self ):
        return "..."

class TokenConverter(ParseElementEnhance):
    """
    Abstract subclass of C{ParseExpression}, for converting parsed results.
    """
    def __init__( self, expr, savelist=False ):
        super(TokenConverter,self).__init__( expr )#, savelist )
        self.saveAsList = False

class Combine(TokenConverter):
    """
    Converter to concatenate all matching tokens to a single string.
    By default, the matching patterns must also be contiguous in the input string;
    this can be disabled by specifying C{'adjacent=False'} in the constructor.

    Example::
        real = Word(nums) + '.' + Word(nums)
        print(real.parseString('3.1416')) # -> ['3', '.', '1416']
        # will also erroneously match the following
        print(real.parseString('3. 1416')) # -> ['3', '.', '1416']

        real = Combine(Word(nums) + '.' + Word(nums))
        print(real.parseString('3.1416')) # -> ['3.1416']
        # no match when there are internal spaces
        print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...)
    """
    def __init__( self, expr, joinString="", adjacent=True ):
        super(Combine,self).__init__( expr )
        # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself
        if adjacent:
            self.leaveWhitespace()
        self.adjacent = adjacent
        self.skipWhitespace = True
        self.joinString = joinString
        self.callPreparse = True

    def ignore( self, other ):
        if self.adjacent:
            ParserElement.ignore(self, other)
        else:
            super( Combine, self).ignore( other )
        return self

    def postParse( self, instring, loc, tokenlist ):
        retToks = tokenlist.copy()
        del retToks[:]
        retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults)

        if self.resultsName and retToks.haskeys():
            return [ retToks ]
        else:
            return retToks

class Group(TokenConverter):
    """
    Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions.

    Example::
        ident = Word(alphas)
        num = Word(nums)
        term = ident | num
        func = ident + Optional(delimitedList(term))
        print(func.parseString("fn a,b,100"))  # -> ['fn', 'a', 'b', '100']

        func = ident + Group(Optional(delimitedList(term)))
        print(func.parseString("fn a,b,100"))  # -> ['fn', ['a', 'b', '100']]
    """
    def __init__( self, expr ):
        super(Group,self).__init__( expr )
        self.saveAsList = True

    def postParse( self, instring, loc, tokenlist ):
        return [ tokenlist ]

class Dict(TokenConverter):
    """
    Converter to return a repetitive expression as a list, but also as a dictionary.
    Each element can also be referenced using the first token in the expression as its key.
    Useful for tabular report scraping when the first column can be used as a item key.

    Example::
        data_word = Word(alphas)
        label = data_word + FollowedBy(':')
        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join))

        text = "shape: SQUARE posn: upper left color: light blue texture: burlap"
        attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
        
        # print attributes as plain groups
        print(OneOrMore(attr_expr).parseString(text).dump())
        
        # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names
        result = Dict(OneOrMore(Group(attr_expr))).parseString(text)
        print(result.dump())
        
        # access named fields as dict entries, or output as dict
        print(result['shape'])        
        print(result.asDict())
    prints::
        ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap']

        [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
        - color: light blue
        - posn: upper left
        - shape: SQUARE
        - texture: burlap
        SQUARE
        {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'}
    See more examples at L{ParseResults} of accessing fields by results name.
    """
    def __init__( self, expr ):
        super(Dict,self).__init__( expr )
        self.saveAsList = True

    def postParse( self, instring, loc, tokenlist ):
        for i,tok in enumerate(tokenlist):
            if len(tok) == 0:
                continue
            ikey = tok[0]
            if isinstance(ikey,int):
                ikey = _ustr(tok[0]).strip()
            if len(tok)==1:
                tokenlist[ikey] = _ParseResultsWithOffset("",i)
            elif len(tok)==2 and not isinstance(tok[1],ParseResults):
                tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i)
            else:
                dictvalue = tok.copy() #ParseResults(i)
                del dictvalue[0]
                if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()):
                    tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i)
                else:
                    tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i)

        if self.resultsName:
            return [ tokenlist ]
        else:
            return tokenlist


class Suppress(TokenConverter):
    """
    Converter for ignoring the results of a parsed expression.

    Example::
        source = "a, b, c,d"
        wd = Word(alphas)
        wd_list1 = wd + ZeroOrMore(',' + wd)
        print(wd_list1.parseString(source))

        # often, delimiters that are useful during parsing are just in the
        # way afterward - use Suppress to keep them out of the parsed output
        wd_list2 = wd + ZeroOrMore(Suppress(',') + wd)
        print(wd_list2.parseString(source))
    prints::
        ['a', ',', 'b', ',', 'c', ',', 'd']
        ['a', 'b', 'c', 'd']
    (See also L{delimitedList}.)
    """
    def postParse( self, instring, loc, tokenlist ):
        return []

    def suppress( self ):
        return self


class OnlyOnce(object):
    """
    Wrapper for parse actions, to ensure they are only called once.
    """
    def __init__(self, methodCall):
        self.callable = _trim_arity(methodCall)
        self.called = False
    def __call__(self,s,l,t):
        if not self.called:
            results = self.callable(s,l,t)
            self.called = True
            return results
        raise ParseException(s,l,"")
    def reset(self):
        self.called = False

def traceParseAction(f):
    """
    Decorator for debugging parse actions. 
    
    When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".}
    When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised.

    Example::
        wd = Word(alphas)

        @traceParseAction
        def remove_duplicate_chars(tokens):
            return ''.join(sorted(set(''.join(tokens)))

        wds = OneOrMore(wd).setParseAction(remove_duplicate_chars)
        print(wds.parseString("slkdjs sld sldd sdlf sdljf"))
    prints::
        >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {}))
        <3:
            thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc
        sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) )
        try:
            ret = f(*paArgs)
        except Exception as exc:
            sys.stderr.write( "< ['aa', 'bb', 'cc']
        delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE']
    """
    dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..."
    if combine:
        return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName)
    else:
        return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName)

def countedArray( expr, intExpr=None ):
    """
    Helper to define a counted list of expressions.
    This helper defines a pattern of the form::
        integer expr expr expr...
    where the leading integer tells how many expr expressions follow.
    The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed.
    
    If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value.

    Example::
        countedArray(Word(alphas)).parseString('2 ab cd ef')  # -> ['ab', 'cd']

        # in this parser, the leading integer value is given in binary,
        # '10' indicating that 2 values are in the array
        binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2))
        countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef')  # -> ['ab', 'cd']
    """
    arrayExpr = Forward()
    def countFieldParseAction(s,l,t):
        n = t[0]
        arrayExpr << (n and Group(And([expr]*n)) or Group(empty))
        return []
    if intExpr is None:
        intExpr = Word(nums).setParseAction(lambda t:int(t[0]))
    else:
        intExpr = intExpr.copy()
    intExpr.setName("arrayLen")
    intExpr.addParseAction(countFieldParseAction, callDuringTry=True)
    return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...')

def _flatten(L):
    ret = []
    for i in L:
        if isinstance(i,list):
            ret.extend(_flatten(i))
        else:
            ret.append(i)
    return ret

def matchPreviousLiteral(expr):
    """
    Helper to define an expression that is indirectly defined from
    the tokens matched in a previous expression, that is, it looks
    for a 'repeat' of a previous expression.  For example::
        first = Word(nums)
        second = matchPreviousLiteral(first)
        matchExpr = first + ":" + second
    will match C{"1:1"}, but not C{"1:2"}.  Because this matches a
    previous literal, will also match the leading C{"1:1"} in C{"1:10"}.
    If this is not desired, use C{matchPreviousExpr}.
    Do I{not} use with packrat parsing enabled.
    """
    rep = Forward()
    def copyTokenToRepeater(s,l,t):
        if t:
            if len(t) == 1:
                rep << t[0]
            else:
                # flatten t tokens
                tflat = _flatten(t.asList())
                rep << And(Literal(tt) for tt in tflat)
        else:
            rep << Empty()
    expr.addParseAction(copyTokenToRepeater, callDuringTry=True)
    rep.setName('(prev) ' + _ustr(expr))
    return rep

def matchPreviousExpr(expr):
    """
    Helper to define an expression that is indirectly defined from
    the tokens matched in a previous expression, that is, it looks
    for a 'repeat' of a previous expression.  For example::
        first = Word(nums)
        second = matchPreviousExpr(first)
        matchExpr = first + ":" + second
    will match C{"1:1"}, but not C{"1:2"}.  Because this matches by
    expressions, will I{not} match the leading C{"1:1"} in C{"1:10"};
    the expressions are evaluated first, and then compared, so
    C{"1"} is compared with C{"10"}.
    Do I{not} use with packrat parsing enabled.
    """
    rep = Forward()
    e2 = expr.copy()
    rep <<= e2
    def copyTokenToRepeater(s,l,t):
        matchTokens = _flatten(t.asList())
        def mustMatchTheseTokens(s,l,t):
            theseTokens = _flatten(t.asList())
            if  theseTokens != matchTokens:
                raise ParseException("",0,"")
        rep.setParseAction( mustMatchTheseTokens, callDuringTry=True )
    expr.addParseAction(copyTokenToRepeater, callDuringTry=True)
    rep.setName('(prev) ' + _ustr(expr))
    return rep

def _escapeRegexRangeChars(s):
    #~  escape these chars: ^-]
    for c in r"\^-]":
        s = s.replace(c,_bslash+c)
    s = s.replace("\n",r"\n")
    s = s.replace("\t",r"\t")
    return _ustr(s)

def oneOf( strs, caseless=False, useRegex=True ):
    """
    Helper to quickly define a set of alternative Literals, and makes sure to do
    longest-first testing when there is a conflict, regardless of the input order,
    but returns a C{L{MatchFirst}} for best performance.

    Parameters:
     - strs - a string of space-delimited literals, or a collection of string literals
     - caseless - (default=C{False}) - treat all literals as caseless
     - useRegex - (default=C{True}) - as an optimization, will generate a Regex
          object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or
          if creating a C{Regex} raises an exception)

    Example::
        comp_oper = oneOf("< = > <= >= !=")
        var = Word(alphas)
        number = Word(nums)
        term = var | number
        comparison_expr = term + comp_oper + term
        print(comparison_expr.searchString("B = 12  AA=23 B<=AA AA>12"))
    prints::
        [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']]
    """
    if caseless:
        isequal = ( lambda a,b: a.upper() == b.upper() )
        masks = ( lambda a,b: b.upper().startswith(a.upper()) )
        parseElementClass = CaselessLiteral
    else:
        isequal = ( lambda a,b: a == b )
        masks = ( lambda a,b: b.startswith(a) )
        parseElementClass = Literal

    symbols = []
    if isinstance(strs,basestring):
        symbols = strs.split()
    elif isinstance(strs, collections.Iterable):
        symbols = list(strs)
    else:
        warnings.warn("Invalid argument to oneOf, expected string or iterable",
                SyntaxWarning, stacklevel=2)
    if not symbols:
        return NoMatch()

    i = 0
    while i < len(symbols)-1:
        cur = symbols[i]
        for j,other in enumerate(symbols[i+1:]):
            if ( isequal(other, cur) ):
                del symbols[i+j+1]
                break
            elif ( masks(cur, other) ):
                del symbols[i+j+1]
                symbols.insert(i,other)
                cur = other
                break
        else:
            i += 1

    if not caseless and useRegex:
        #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] ))
        try:
            if len(symbols)==len("".join(symbols)):
                return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols))
            else:
                return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols))
        except Exception:
            warnings.warn("Exception creating Regex for oneOf, building MatchFirst",
                    SyntaxWarning, stacklevel=2)


    # last resort, just use MatchFirst
    return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols))

def dictOf( key, value ):
    """
    Helper to easily and clearly define a dictionary by specifying the respective patterns
    for the key and value.  Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens
    in the proper order.  The key pattern can include delimiting markers or punctuation,
    as long as they are suppressed, thereby leaving the significant key text.  The value
    pattern can include named results, so that the C{Dict} results can include named token
    fields.

    Example::
        text = "shape: SQUARE posn: upper left color: light blue texture: burlap"
        attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
        print(OneOrMore(attr_expr).parseString(text).dump())
        
        attr_label = label
        attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)

        # similar to Dict, but simpler call format
        result = dictOf(attr_label, attr_value).parseString(text)
        print(result.dump())
        print(result['shape'])
        print(result.shape)  # object attribute access works too
        print(result.asDict())
    prints::
        [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
        - color: light blue
        - posn: upper left
        - shape: SQUARE
        - texture: burlap
        SQUARE
        SQUARE
        {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'}
    """
    return Dict( ZeroOrMore( Group ( key + value ) ) )

def originalTextFor(expr, asString=True):
    """
    Helper to return the original, untokenized text for a given expression.  Useful to
    restore the parsed fields of an HTML start tag into the raw tag text itself, or to
    revert separate tokens with intervening whitespace back to the original matching
    input text. By default, returns astring containing the original parsed text.  
       
    If the optional C{asString} argument is passed as C{False}, then the return value is a 
    C{L{ParseResults}} containing any results names that were originally matched, and a 
    single token containing the original matched text from the input string.  So if 
    the expression passed to C{L{originalTextFor}} contains expressions with defined
    results names, you must set C{asString} to C{False} if you want to preserve those
    results name values.

    Example::
        src = "this is test  bold text  normal text "
        for tag in ("b","i"):
            opener,closer = makeHTMLTags(tag)
            patt = originalTextFor(opener + SkipTo(closer) + closer)
            print(patt.searchString(src)[0])
    prints::
        [' bold text ']
        ['text']
    """
    locMarker = Empty().setParseAction(lambda s,loc,t: loc)
    endlocMarker = locMarker.copy()
    endlocMarker.callPreparse = False
    matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end")
    if asString:
        extractText = lambda s,l,t: s[t._original_start:t._original_end]
    else:
        def extractText(s,l,t):
            t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]]
    matchExpr.setParseAction(extractText)
    matchExpr.ignoreExprs = expr.ignoreExprs
    return matchExpr

def ungroup(expr): 
    """
    Helper to undo pyparsing's default grouping of And expressions, even
    if all but one are non-empty.
    """
    return TokenConverter(expr).setParseAction(lambda t:t[0])

def locatedExpr(expr):
    """
    Helper to decorate a returned token with its starting and ending locations in the input string.
    This helper adds the following results names:
     - locn_start = location where matched expression begins
     - locn_end = location where matched expression ends
     - value = the actual parsed results

    Be careful if the input text contains C{} characters, you may want to call
    C{L{ParserElement.parseWithTabs}}

    Example::
        wd = Word(alphas)
        for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"):
            print(match)
    prints::
        [[0, 'ljsdf', 5]]
        [[8, 'lksdjjf', 15]]
        [[18, 'lkkjj', 23]]
    """
    locator = Empty().setParseAction(lambda s,l,t: l)
    return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end"))


# convenience constants for positional expressions
empty       = Empty().setName("empty")
lineStart   = LineStart().setName("lineStart")
lineEnd     = LineEnd().setName("lineEnd")
stringStart = StringStart().setName("stringStart")
stringEnd   = StringEnd().setName("stringEnd")

_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1])
_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16)))
_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8)))
_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | Word(printables, excludeChars=r'\]', exact=1) | Regex(r"\w", re.UNICODE)
_charRange = Group(_singleChar + Suppress("-") + _singleChar)
_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]"

def srange(s):
    r"""
    Helper to easily define string ranges for use in Word construction.  Borrows
    syntax from regexp '[]' string range definitions::
        srange("[0-9]")   -> "0123456789"
        srange("[a-z]")   -> "abcdefghijklmnopqrstuvwxyz"
        srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_"
    The input string must be enclosed in []'s, and the returned string is the expanded
    character set joined into a single string.
    The values enclosed in the []'s may be:
     - a single character
     - an escaped character with a leading backslash (such as C{\-} or C{\]})
     - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) 
         (C{\0x##} is also supported for backwards compatibility) 
     - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character)
     - a range of any of the above, separated by a dash (C{'a-z'}, etc.)
     - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.)
    """
    _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1))
    try:
        return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body)
    except Exception:
        return ""

def matchOnlyAtCol(n):
    """
    Helper method for defining parse actions that require matching at a specific
    column in the input text.
    """
    def verifyCol(strg,locn,toks):
        if col(locn,strg) != n:
            raise ParseException(strg,locn,"matched token not at column %d" % n)
    return verifyCol

def replaceWith(replStr):
    """
    Helper method for common parse actions that simply return a literal value.  Especially
    useful when used with C{L{transformString}()}.

    Example::
        num = Word(nums).setParseAction(lambda toks: int(toks[0]))
        na = oneOf("N/A NA").setParseAction(replaceWith(math.nan))
        term = na | num
        
        OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234]
    """
    return lambda s,l,t: [replStr]

def removeQuotes(s,l,t):
    """
    Helper parse action for removing quotation marks from parsed quoted strings.

    Example::
        # by default, quotation marks are included in parsed results
        quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"]

        # use removeQuotes to strip quotation marks from parsed results
        quotedString.setParseAction(removeQuotes)
        quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"]
    """
    return t[0][1:-1]

def tokenMap(func, *args):
    """
    Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional 
    args are passed, they are forwarded to the given function as additional arguments after
    the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the
    parsed data to an integer using base 16.

    Example (compare the last to example in L{ParserElement.transformString}::
        hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16))
        hex_ints.runTests('''
            00 11 22 aa FF 0a 0d 1a
            ''')
        
        upperword = Word(alphas).setParseAction(tokenMap(str.upper))
        OneOrMore(upperword).runTests('''
            my kingdom for a horse
            ''')

        wd = Word(alphas).setParseAction(tokenMap(str.title))
        OneOrMore(wd).setParseAction(' '.join).runTests('''
            now is the winter of our discontent made glorious summer by this sun of york
            ''')
    prints::
        00 11 22 aa FF 0a 0d 1a
        [0, 17, 34, 170, 255, 10, 13, 26]

        my kingdom for a horse
        ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE']

        now is the winter of our discontent made glorious summer by this sun of york
        ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York']
    """
    def pa(s,l,t):
        return [func(tokn, *args) for tokn in t]

    try:
        func_name = getattr(func, '__name__', 
                            getattr(func, '__class__').__name__)
    except Exception:
        func_name = str(func)
    pa.__name__ = func_name

    return pa

upcaseTokens = tokenMap(lambda t: _ustr(t).upper())
"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}"""

downcaseTokens = tokenMap(lambda t: _ustr(t).lower())
"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}"""
    
def _makeTags(tagStr, xml):
    """Internal helper to construct opening and closing tag expressions, given a tag name"""
    if isinstance(tagStr,basestring):
        resname = tagStr
        tagStr = Keyword(tagStr, caseless=not xml)
    else:
        resname = tagStr.name

    tagAttrName = Word(alphas,alphanums+"_-:")
    if (xml):
        tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes )
        openTag = Suppress("<") + tagStr("tag") + \
                Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \
                Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
    else:
        printablesLessRAbrack = "".join(c for c in printables if c not in ">")
        tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack)
        openTag = Suppress("<") + tagStr("tag") + \
                Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \
                Optional( Suppress("=") + tagAttrValue ) ))) + \
                Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
    closeTag = Combine(_L("")

    openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname)
    closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("" % resname)
    openTag.tag = resname
    closeTag.tag = resname
    return openTag, closeTag

def makeHTMLTags(tagStr):
    """
    Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches
    tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values.

    Example::
        text = 'More info at the pyparsing wiki page'
        # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple
        a,a_end = makeHTMLTags("A")
        link_expr = a + SkipTo(a_end)("link_text") + a_end
        
        for link in link_expr.searchString(text):
            # attributes in the  tag (like "href" shown here) are also accessible as named results
            print(link.link_text, '->', link.href)
    prints::
        pyparsing -> http://pyparsing.wikispaces.com
    """
    return _makeTags( tagStr, False )

def makeXMLTags(tagStr):
    """
    Helper to construct opening and closing tag expressions for XML, given a tag name. Matches
    tags only in the given upper/lower case.

    Example: similar to L{makeHTMLTags}
    """
    return _makeTags( tagStr, True )

def withAttribute(*args,**attrDict):
    """
    Helper to create a validating parse action to be used with start tags created
    with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag
    with a required attribute value, to avoid false matches on common tags such as
    C{} or C{
}. Call C{withAttribute} with a series of attribute names and values. Specify the list of filter attributes names and values as: - keyword arguments, as in C{(align="right")}, or - as an explicit dict with C{**} operator, when an attribute name is also a Python reserved word, as in C{**{"class":"Customer", "align":"right"}} - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) For attribute names with a namespace prefix, you must use the second form. Attribute names are matched insensitive to upper/lower case. If just testing for C{class} (with or without a namespace), use C{L{withClass}}. To verify that the attribute exists, but without specifying a value, pass C{withAttribute.ANY_VALUE} as the value. Example:: html = '''
Some text
1 4 0 1 0
1,3 2,3 1,1
this has no type
''' div,div_end = makeHTMLTags("div") # only match div tag having a type attribute with value "grid" div_grid = div().setParseAction(withAttribute(type="grid")) grid_expr = div_grid + SkipTo(div | div_end)("body") for grid_header in grid_expr.searchString(html): print(grid_header.body) # construct a match with any div tag having a type attribute, regardless of the value div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) div_expr = div_any_type + SkipTo(div | div_end)("body") for div_header in div_expr.searchString(html): print(div_header.body) prints:: 1 4 0 1 0 1 4 0 1 0 1,3 2,3 1,1 """ if args: attrs = args[:] else: attrs = attrDict.items() attrs = [(k,v) for k,v in attrs] def pa(s,l,tokens): for attrName,attrValue in attrs: if attrName not in tokens: raise ParseException(s,l,"no matching attribute " + attrName) if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % (attrName, tokens[attrName], attrValue)) return pa withAttribute.ANY_VALUE = object() def withClass(classname, namespace=''): """ Simplified version of C{L{withAttribute}} when matching on a div class - made difficult because C{class} is a reserved word in Python. Example:: html = '''
Some text
1 4 0 1 0
1,3 2,3 1,1
this <div> has no class
''' div,div_end = makeHTMLTags("div") div_grid = div().setParseAction(withClass("grid")) grid_expr = div_grid + SkipTo(div | div_end)("body") for grid_header in grid_expr.searchString(html): print(grid_header.body) div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) div_expr = div_any_type + SkipTo(div | div_end)("body") for div_header in div_expr.searchString(html): print(div_header.body) prints:: 1 4 0 1 0 1 4 0 1 0 1,3 2,3 1,1 """ classattr = "%s:class" % namespace if namespace else "class" return withAttribute(**{classattr : classname}) opAssoc = _Constants() opAssoc.LEFT = object() opAssoc.RIGHT = object() def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): """ Helper method for constructing grammars of expressions made up of operators working in a precedence hierarchy. Operators may be unary or binary, left- or right-associative. Parse actions can also be attached to operator expressions. The generated parser will also recognize the use of parentheses to override operator precedences (see example below). Note: if you define a deep operator list, you may see performance issues when using infixNotation. See L{ParserElement.enablePackrat} for a mechanism to potentially improve your parser performance. Parameters: - baseExpr - expression representing the most basic element for the nested - opList - list of tuples, one for each operator precedence level in the expression grammar; each tuple is of the form (opExpr, numTerms, rightLeftAssoc, parseAction), where: - opExpr is the pyparsing expression for the operator; may also be a string, which will be converted to a Literal; if numTerms is 3, opExpr is a tuple of two expressions, for the two operators separating the 3 terms - numTerms is the number of terms for this operator (must be 1, 2, or 3) - rightLeftAssoc is the indicator whether the operator is right or left associative, using the pyparsing-defined constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. - parseAction is the parse action to be associated with expressions matching this operator expression (the parse action tuple member may be omitted) - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) Example:: # simple example of four-function arithmetic with ints and variable names integer = pyparsing_common.signed_integer varname = pyparsing_common.identifier arith_expr = infixNotation(integer | varname, [ ('-', 1, opAssoc.RIGHT), (oneOf('* /'), 2, opAssoc.LEFT), (oneOf('+ -'), 2, opAssoc.LEFT), ]) arith_expr.runTests(''' 5+3*6 (5+3)*6 -2--11 ''', fullDump=False) prints:: 5+3*6 [[5, '+', [3, '*', 6]]] (5+3)*6 [[[5, '+', 3], '*', 6]] -2--11 [[['-', 2], '-', ['-', 11]]] """ ret = Forward() lastExpr = baseExpr | ( lpar + ret + rpar ) for i,operDef in enumerate(opList): opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr if arity == 3: if opExpr is None or len(opExpr) != 2: raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") opExpr1, opExpr2 = opExpr thisExpr = Forward().setName(termName) if rightLeftAssoc == opAssoc.LEFT: if arity == 1: matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) elif arity == 2: if opExpr is not None: matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) else: matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) elif arity == 3: matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) else: raise ValueError("operator must be unary (1), binary (2), or ternary (3)") elif rightLeftAssoc == opAssoc.RIGHT: if arity == 1: # try to avoid LR with this extra test if not isinstance(opExpr, Optional): opExpr = Optional(opExpr) matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) elif arity == 2: if opExpr is not None: matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) else: matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) elif arity == 3: matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) else: raise ValueError("operator must be unary (1), binary (2), or ternary (3)") else: raise ValueError("operator must indicate right or left associativity") if pa: matchExpr.setParseAction( pa ) thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) lastExpr = thisExpr ret <<= lastExpr return ret operatorPrecedence = infixNotation """(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): """ Helper method for defining nested lists enclosed in opening and closing delimiters ("(" and ")" are the default). Parameters: - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression - content - expression for items within the nested lists (default=C{None}) - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) If an expression is not provided for the content argument, the nested expression will capture all whitespace-delimited content between delimiters as a list of separate values. Use the C{ignoreExpr} argument to define expressions that may contain opening or closing characters that should not be treated as opening or closing characters for nesting, such as quotedString or a comment expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. The default is L{quotedString}, but if no expressions are to be ignored, then pass C{None} for this argument. Example:: data_type = oneOf("void int short long char float double") decl_data_type = Combine(data_type + Optional(Word('*'))) ident = Word(alphas+'_', alphanums+'_') number = pyparsing_common.number arg = Group(decl_data_type + ident) LPAR,RPAR = map(Suppress, "()") code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) c_function = (decl_data_type("type") + ident("name") + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + code_body("body")) c_function.ignore(cStyleComment) source_code = ''' int is_odd(int x) { return (x%2); } int dec_to_hex(char hchar) { if (hchar >= '0' && hchar <= '9') { return (ord(hchar)-ord('0')); } else { return (10+ord(hchar)-ord('A')); } } ''' for func in c_function.searchString(source_code): print("%(name)s (%(type)s) args: %(args)s" % func) prints:: is_odd (int) args: [['int', 'x']] dec_to_hex (int) args: [['char', 'hchar']] """ if opener == closer: raise ValueError("opening and closing strings cannot be the same") if content is None: if isinstance(opener,basestring) and isinstance(closer,basestring): if len(opener) == 1 and len(closer)==1: if ignoreExpr is not None: content = (Combine(OneOrMore(~ignoreExpr + CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) ).setParseAction(lambda t:t[0].strip())) else: content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS ).setParseAction(lambda t:t[0].strip())) else: if ignoreExpr is not None: content = (Combine(OneOrMore(~ignoreExpr + ~Literal(opener) + ~Literal(closer) + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) ).setParseAction(lambda t:t[0].strip())) else: content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) ).setParseAction(lambda t:t[0].strip())) else: raise ValueError("opening and closing arguments must be strings if no content expression is given") ret = Forward() if ignoreExpr is not None: ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) else: ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) ret.setName('nested %s%s expression' % (opener,closer)) return ret def indentedBlock(blockStatementExpr, indentStack, indent=True): """ Helper method for defining space-delimited indentation blocks, such as those used to define block statements in Python source code. Parameters: - blockStatementExpr - expression defining syntax of statement that is repeated within the indented block - indentStack - list created by caller to manage indentation stack (multiple statementWithIndentedBlock expressions within a single grammar should share a common indentStack) - indent - boolean indicating whether block must be indented beyond the the current level; set to False for block of left-most statements (default=C{True}) A valid block must contain at least one C{blockStatement}. Example:: data = ''' def A(z): A1 B = 100 G = A2 A2 A3 B def BB(a,b,c): BB1 def BBA(): bba1 bba2 bba3 C D def spam(x,y): def eggs(z): pass ''' indentStack = [1] stmt = Forward() identifier = Word(alphas, alphanums) funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") func_body = indentedBlock(stmt, indentStack) funcDef = Group( funcDecl + func_body ) rvalue = Forward() funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") rvalue << (funcCall | identifier | Word(nums)) assignment = Group(identifier + "=" + rvalue) stmt << ( funcDef | assignment | identifier ) module_body = OneOrMore(stmt) parseTree = module_body.parseString(data) parseTree.pprint() prints:: [['def', 'A', ['(', 'z', ')'], ':', [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], 'B', ['def', 'BB', ['(', 'a', 'b', 'c', ')'], ':', [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], 'C', 'D', ['def', 'spam', ['(', 'x', 'y', ')'], ':', [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] """ def checkPeerIndent(s,l,t): if l >= len(s): return curCol = col(l,s) if curCol != indentStack[-1]: if curCol > indentStack[-1]: raise ParseFatalException(s,l,"illegal nesting") raise ParseException(s,l,"not a peer entry") def checkSubIndent(s,l,t): curCol = col(l,s) if curCol > indentStack[-1]: indentStack.append( curCol ) else: raise ParseException(s,l,"not a subentry") def checkUnindent(s,l,t): if l >= len(s): return curCol = col(l,s) if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): raise ParseException(s,l,"not an unindent") indentStack.pop() NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') PEER = Empty().setParseAction(checkPeerIndent).setName('') UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') if indent: smExpr = Group( Optional(NL) + #~ FollowedBy(blockStatementExpr) + INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) else: smExpr = Group( Optional(NL) + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) blockStatementExpr.ignore(_bslash + LineEnd()) return smExpr.setName('indented block') alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) _htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) commonHTMLEntity = Regex('&(?P' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") def replaceHTMLEntity(t): """Helper parser action to replace common HTML entities with their special characters""" return _htmlEntityMap.get(t.entity) # it's easy to get these comment structures wrong - they're very common, so may as well make them available cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") "Comment of the form C{/* ... */}" htmlComment = Regex(r"").setName("HTML comment") "Comment of the form C{}" restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") "Comment of the form C{// ... (to end of line)}" cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") "Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" javaStyleComment = cppStyleComment "Same as C{L{cppStyleComment}}" pythonStyleComment = Regex(r"#.*").setName("Python style comment") "Comment of the form C{# ... (to end of line)}" _commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + Optional( Word(" \t") + ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") """(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" # some other useful expressions - using lower-case class name since we are really using this as a namespace class pyparsing_common: """ Here are some common low-level expressions that may be useful in jump-starting parser development: - numeric forms (L{integers}, L{reals}, L{scientific notation}) - common L{programming identifiers} - network addresses (L{MAC}, L{IPv4}, L{IPv6}) - ISO8601 L{dates} and L{datetime} - L{UUID} - L{comma-separated list} Parse actions: - C{L{convertToInteger}} - C{L{convertToFloat}} - C{L{convertToDate}} - C{L{convertToDatetime}} - C{L{stripHTMLTags}} - C{L{upcaseTokens}} - C{L{downcaseTokens}} Example:: pyparsing_common.number.runTests(''' # any int or real number, returned as the appropriate type 100 -100 +100 3.14159 6.02e23 1e-12 ''') pyparsing_common.fnumber.runTests(''' # any int or real number, returned as float 100 -100 +100 3.14159 6.02e23 1e-12 ''') pyparsing_common.hex_integer.runTests(''' # hex numbers 100 FF ''') pyparsing_common.fraction.runTests(''' # fractions 1/2 -3/4 ''') pyparsing_common.mixed_integer.runTests(''' # mixed fractions 1 1/2 -3/4 1-3/4 ''') import uuid pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) pyparsing_common.uuid.runTests(''' # uuid 12345678-1234-5678-1234-567812345678 ''') prints:: # any int or real number, returned as the appropriate type 100 [100] -100 [-100] +100 [100] 3.14159 [3.14159] 6.02e23 [6.02e+23] 1e-12 [1e-12] # any int or real number, returned as float 100 [100.0] -100 [-100.0] +100 [100.0] 3.14159 [3.14159] 6.02e23 [6.02e+23] 1e-12 [1e-12] # hex numbers 100 [256] FF [255] # fractions 1/2 [0.5] -3/4 [-0.75] # mixed fractions 1 [1] 1/2 [0.5] -3/4 [-0.75] 1-3/4 [1.75] # uuid 12345678-1234-5678-1234-567812345678 [UUID('12345678-1234-5678-1234-567812345678')] """ convertToInteger = tokenMap(int) """ Parse action for converting parsed integers to Python int """ convertToFloat = tokenMap(float) """ Parse action for converting parsed numbers to Python float """ integer = Word(nums).setName("integer").setParseAction(convertToInteger) """expression that parses an unsigned integer, returns an int""" hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) """expression that parses a hexadecimal integer, returns an int""" signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) """expression that parses an integer with optional leading sign, returns an int""" fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") """fractional expression of an integer divided by an integer, returns a float""" fraction.addParseAction(lambda t: t[0]/t[-1]) mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" mixed_integer.addParseAction(sum) real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) """expression that parses a floating point number and returns a float""" sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) """expression that parses a floating point number with optional scientific notation and returns a float""" # streamlining this expression makes the docs nicer-looking number = (sci_real | real | signed_integer).streamline() """any numeric expression, returns the corresponding Python type""" fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) """any int or real number, returned as float""" identifier = Word(alphas+'_', alphanums+'_').setName("identifier") """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") "IPv4 address (C{0.0.0.0 - 255.255.255.255})" _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") "IPv6 address (long, short, or mixed form)" mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" @staticmethod def convertToDate(fmt="%Y-%m-%d"): """ Helper to create a parse action for converting parsed date string to Python datetime.date Params - - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) Example:: date_expr = pyparsing_common.iso8601_date.copy() date_expr.setParseAction(pyparsing_common.convertToDate()) print(date_expr.parseString("1999-12-31")) prints:: [datetime.date(1999, 12, 31)] """ def cvt_fn(s,l,t): try: return datetime.strptime(t[0], fmt).date() except ValueError as ve: raise ParseException(s, l, str(ve)) return cvt_fn @staticmethod def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): """ Helper to create a parse action for converting parsed datetime string to Python datetime.datetime Params - - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) Example:: dt_expr = pyparsing_common.iso8601_datetime.copy() dt_expr.setParseAction(pyparsing_common.convertToDatetime()) print(dt_expr.parseString("1999-12-31T23:59:59.999")) prints:: [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] """ def cvt_fn(s,l,t): try: return datetime.strptime(t[0], fmt) except ValueError as ve: raise ParseException(s, l, str(ve)) return cvt_fn iso8601_date = Regex(r'(?P\d{4})(?:-(?P\d\d)(?:-(?P\d\d))?)?').setName("ISO8601 date") "ISO8601 date (C{yyyy-mm-dd})" iso8601_datetime = Regex(r'(?P\d{4})-(?P\d\d)-(?P\d\d)[T ](?P\d\d):(?P\d\d)(:(?P\d\d(\.\d*)?)?)?(?PZ|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() @staticmethod def stripHTMLTags(s, l, tokens): """ Parse action to remove HTML tags from web page HTML source Example:: # strip HTML links from normal text text = 'More info at the
pyparsing wiki page' td,td_end = makeHTMLTags("TD") table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' """ return pyparsing_common._html_stripper.transformString(tokens[0]) _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') + Optional( White(" \t") ) ) ).streamline().setName("commaItem") comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) """Parse action to convert tokens to upper case.""" downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) """Parse action to convert tokens to lower case.""" if __name__ == "__main__": selectToken = CaselessLiteral("select") fromToken = CaselessLiteral("from") ident = Word(alphas, alphanums + "_$") columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) columnNameList = Group(delimitedList(columnName)).setName("columns") columnSpec = ('*' | columnNameList) tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) tableNameList = Group(delimitedList(tableName)).setName("tables") simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") # demo runTests method, including embedded comments in test string simpleSQL.runTests(""" # '*' as column list and dotted table name select * from SYS.XYZZY # caseless match on "SELECT", and casts back to "select" SELECT * from XYZZY, ABC # list of column names, and mixed case SELECT keyword Select AA,BB,CC from Sys.dual # multiple tables Select A, B, C from Sys.dual, Table2 # invalid SELECT keyword - should fail Xelect A, B, C from Sys.dual # incomplete command - should fail Select # invalid column name - should fail Select ^^^ frox Sys.dual """) pyparsing_common.number.runTests(""" 100 -100 +100 3.14159 6.02e23 1e-12 """) # any int or real number, returned as float pyparsing_common.fnumber.runTests(""" 100 -100 +100 3.14159 6.02e23 1e-12 """) pyparsing_common.hex_integer.runTests(""" 100 FF """) import uuid pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) pyparsing_common.uuid.runTests(""" 12345678-1234-5678-1234-567812345678 """) six.py000064400000072622147205126200005731 0ustar00"""Utilities for writing code that runs on Python 2 and 3""" # Copyright (c) 2010-2015 Benjamin Peterson # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. from __future__ import absolute_import import functools import itertools import operator import sys import types __author__ = "Benjamin Peterson " __version__ = "1.10.0" # Useful for very coarse version differentiation. PY2 = sys.version_info[0] == 2 PY3 = sys.version_info[0] == 3 PY34 = sys.version_info[0:2] >= (3, 4) if PY3: string_types = str, integer_types = int, class_types = type, text_type = str binary_type = bytes MAXSIZE = sys.maxsize else: string_types = basestring, integer_types = (int, long) class_types = (type, types.ClassType) text_type = unicode binary_type = str if sys.platform.startswith("java"): # Jython always uses 32 bits. MAXSIZE = int((1 << 31) - 1) else: # It's possible to have sizeof(long) != sizeof(Py_ssize_t). class X(object): def __len__(self): return 1 << 31 try: len(X()) except OverflowError: # 32-bit MAXSIZE = int((1 << 31) - 1) else: # 64-bit MAXSIZE = int((1 << 63) - 1) del X def _add_doc(func, doc): """Add documentation to a function.""" func.__doc__ = doc def _import_module(name): """Import module, returning the module after the last dot.""" __import__(name) return sys.modules[name] class _LazyDescr(object): def __init__(self, name): self.name = name def __get__(self, obj, tp): result = self._resolve() setattr(obj, self.name, result) # Invokes __set__. try: # This is a bit ugly, but it avoids running this again by # removing this descriptor. delattr(obj.__class__, self.name) except AttributeError: pass return result class MovedModule(_LazyDescr): def __init__(self, name, old, new=None): super(MovedModule, self).__init__(name) if PY3: if new is None: new = name self.mod = new else: self.mod = old def _resolve(self): return _import_module(self.mod) def __getattr__(self, attr): _module = self._resolve() value = getattr(_module, attr) setattr(self, attr, value) return value class _LazyModule(types.ModuleType): def __init__(self, name): super(_LazyModule, self).__init__(name) self.__doc__ = self.__class__.__doc__ def __dir__(self): attrs = ["__doc__", "__name__"] attrs += [attr.name for attr in self._moved_attributes] return attrs # Subclasses should override this _moved_attributes = [] class MovedAttribute(_LazyDescr): def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): super(MovedAttribute, self).__init__(name) if PY3: if new_mod is None: new_mod = name self.mod = new_mod if new_attr is None: if old_attr is None: new_attr = name else: new_attr = old_attr self.attr = new_attr else: self.mod = old_mod if old_attr is None: old_attr = name self.attr = old_attr def _resolve(self): module = _import_module(self.mod) return getattr(module, self.attr) class _SixMetaPathImporter(object): """ A meta path importer to import six.moves and its submodules. This class implements a PEP302 finder and loader. It should be compatible with Python 2.5 and all existing versions of Python3 """ def __init__(self, six_module_name): self.name = six_module_name self.known_modules = {} def _add_module(self, mod, *fullnames): for fullname in fullnames: self.known_modules[self.name + "." + fullname] = mod def _get_module(self, fullname): return self.known_modules[self.name + "." + fullname] def find_module(self, fullname, path=None): if fullname in self.known_modules: return self return None def __get_module(self, fullname): try: return self.known_modules[fullname] except KeyError: raise ImportError("This loader does not know module " + fullname) def load_module(self, fullname): try: # in case of a reload return sys.modules[fullname] except KeyError: pass mod = self.__get_module(fullname) if isinstance(mod, MovedModule): mod = mod._resolve() else: mod.__loader__ = self sys.modules[fullname] = mod return mod def is_package(self, fullname): """ Return true, if the named module is a package. We need this method to get correct spec objects with Python 3.4 (see PEP451) """ return hasattr(self.__get_module(fullname), "__path__") def get_code(self, fullname): """Return None Required, if is_package is implemented""" self.__get_module(fullname) # eventually raises ImportError return None get_source = get_code # same as get_code _importer = _SixMetaPathImporter(__name__) class _MovedItems(_LazyModule): """Lazy loading of moved objects""" __path__ = [] # mark as package _moved_attributes = [ MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), MovedAttribute("intern", "__builtin__", "sys"), MovedAttribute("map", "itertools", "builtins", "imap", "map"), MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), MovedAttribute("reduce", "__builtin__", "functools"), MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), MovedAttribute("StringIO", "StringIO", "io"), MovedAttribute("UserDict", "UserDict", "collections"), MovedAttribute("UserList", "UserList", "collections"), MovedAttribute("UserString", "UserString", "collections"), MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), MovedModule("builtins", "__builtin__"), MovedModule("configparser", "ConfigParser"), MovedModule("copyreg", "copy_reg"), MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), MovedModule("http_cookies", "Cookie", "http.cookies"), MovedModule("html_entities", "htmlentitydefs", "html.entities"), MovedModule("html_parser", "HTMLParser", "html.parser"), MovedModule("http_client", "httplib", "http.client"), MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), MovedModule("cPickle", "cPickle", "pickle"), MovedModule("queue", "Queue"), MovedModule("reprlib", "repr"), MovedModule("socketserver", "SocketServer"), MovedModule("_thread", "thread", "_thread"), MovedModule("tkinter", "Tkinter"), MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), MovedModule("tkinter_tix", "Tix", "tkinter.tix"), MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), MovedModule("tkinter_colorchooser", "tkColorChooser", "tkinter.colorchooser"), MovedModule("tkinter_commondialog", "tkCommonDialog", "tkinter.commondialog"), MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), MovedModule("tkinter_font", "tkFont", "tkinter.font"), MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", "tkinter.simpledialog"), MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), ] # Add windows specific modules. if sys.platform == "win32": _moved_attributes += [ MovedModule("winreg", "_winreg"), ] for attr in _moved_attributes: setattr(_MovedItems, attr.name, attr) if isinstance(attr, MovedModule): _importer._add_module(attr, "moves." + attr.name) del attr _MovedItems._moved_attributes = _moved_attributes moves = _MovedItems(__name__ + ".moves") _importer._add_module(moves, "moves") class Module_six_moves_urllib_parse(_LazyModule): """Lazy loading of moved objects in six.moves.urllib_parse""" _urllib_parse_moved_attributes = [ MovedAttribute("ParseResult", "urlparse", "urllib.parse"), MovedAttribute("SplitResult", "urlparse", "urllib.parse"), MovedAttribute("parse_qs", "urlparse", "urllib.parse"), MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), MovedAttribute("urldefrag", "urlparse", "urllib.parse"), MovedAttribute("urljoin", "urlparse", "urllib.parse"), MovedAttribute("urlparse", "urlparse", "urllib.parse"), MovedAttribute("urlsplit", "urlparse", "urllib.parse"), MovedAttribute("urlunparse", "urlparse", "urllib.parse"), MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), MovedAttribute("quote", "urllib", "urllib.parse"), MovedAttribute("quote_plus", "urllib", "urllib.parse"), MovedAttribute("unquote", "urllib", "urllib.parse"), MovedAttribute("unquote_plus", "urllib", "urllib.parse"), MovedAttribute("urlencode", "urllib", "urllib.parse"), MovedAttribute("splitquery", "urllib", "urllib.parse"), MovedAttribute("splittag", "urllib", "urllib.parse"), MovedAttribute("splituser", "urllib", "urllib.parse"), MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), MovedAttribute("uses_params", "urlparse", "urllib.parse"), MovedAttribute("uses_query", "urlparse", "urllib.parse"), MovedAttribute("uses_relative", "urlparse", "urllib.parse"), ] for attr in _urllib_parse_moved_attributes: setattr(Module_six_moves_urllib_parse, attr.name, attr) del attr Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes _importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), "moves.urllib_parse", "moves.urllib.parse") class Module_six_moves_urllib_error(_LazyModule): """Lazy loading of moved objects in six.moves.urllib_error""" _urllib_error_moved_attributes = [ MovedAttribute("URLError", "urllib2", "urllib.error"), MovedAttribute("HTTPError", "urllib2", "urllib.error"), MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), ] for attr in _urllib_error_moved_attributes: setattr(Module_six_moves_urllib_error, attr.name, attr) del attr Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes _importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), "moves.urllib_error", "moves.urllib.error") class Module_six_moves_urllib_request(_LazyModule): """Lazy loading of moved objects in six.moves.urllib_request""" _urllib_request_moved_attributes = [ MovedAttribute("urlopen", "urllib2", "urllib.request"), MovedAttribute("install_opener", "urllib2", "urllib.request"), MovedAttribute("build_opener", "urllib2", "urllib.request"), MovedAttribute("pathname2url", "urllib", "urllib.request"), MovedAttribute("url2pathname", "urllib", "urllib.request"), MovedAttribute("getproxies", "urllib", "urllib.request"), MovedAttribute("Request", "urllib2", "urllib.request"), MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), MovedAttribute("BaseHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), MovedAttribute("FileHandler", "urllib2", "urllib.request"), MovedAttribute("FTPHandler", "urllib2", "urllib.request"), MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), MovedAttribute("urlretrieve", "urllib", "urllib.request"), MovedAttribute("urlcleanup", "urllib", "urllib.request"), MovedAttribute("URLopener", "urllib", "urllib.request"), MovedAttribute("FancyURLopener", "urllib", "urllib.request"), MovedAttribute("proxy_bypass", "urllib", "urllib.request"), ] for attr in _urllib_request_moved_attributes: setattr(Module_six_moves_urllib_request, attr.name, attr) del attr Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes _importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), "moves.urllib_request", "moves.urllib.request") class Module_six_moves_urllib_response(_LazyModule): """Lazy loading of moved objects in six.moves.urllib_response""" _urllib_response_moved_attributes = [ MovedAttribute("addbase", "urllib", "urllib.response"), MovedAttribute("addclosehook", "urllib", "urllib.response"), MovedAttribute("addinfo", "urllib", "urllib.response"), MovedAttribute("addinfourl", "urllib", "urllib.response"), ] for attr in _urllib_response_moved_attributes: setattr(Module_six_moves_urllib_response, attr.name, attr) del attr Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes _importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), "moves.urllib_response", "moves.urllib.response") class Module_six_moves_urllib_robotparser(_LazyModule): """Lazy loading of moved objects in six.moves.urllib_robotparser""" _urllib_robotparser_moved_attributes = [ MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), ] for attr in _urllib_robotparser_moved_attributes: setattr(Module_six_moves_urllib_robotparser, attr.name, attr) del attr Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes _importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), "moves.urllib_robotparser", "moves.urllib.robotparser") class Module_six_moves_urllib(types.ModuleType): """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" __path__ = [] # mark as package parse = _importer._get_module("moves.urllib_parse") error = _importer._get_module("moves.urllib_error") request = _importer._get_module("moves.urllib_request") response = _importer._get_module("moves.urllib_response") robotparser = _importer._get_module("moves.urllib_robotparser") def __dir__(self): return ['parse', 'error', 'request', 'response', 'robotparser'] _importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), "moves.urllib") def add_move(move): """Add an item to six.moves.""" setattr(_MovedItems, move.name, move) def remove_move(name): """Remove item from six.moves.""" try: delattr(_MovedItems, name) except AttributeError: try: del moves.__dict__[name] except KeyError: raise AttributeError("no such move, %r" % (name,)) if PY3: _meth_func = "__func__" _meth_self = "__self__" _func_closure = "__closure__" _func_code = "__code__" _func_defaults = "__defaults__" _func_globals = "__globals__" else: _meth_func = "im_func" _meth_self = "im_self" _func_closure = "func_closure" _func_code = "func_code" _func_defaults = "func_defaults" _func_globals = "func_globals" try: advance_iterator = next except NameError: def advance_iterator(it): return it.next() next = advance_iterator try: callable = callable except NameError: def callable(obj): return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) if PY3: def get_unbound_function(unbound): return unbound create_bound_method = types.MethodType def create_unbound_method(func, cls): return func Iterator = object else: def get_unbound_function(unbound): return unbound.im_func def create_bound_method(func, obj): return types.MethodType(func, obj, obj.__class__) def create_unbound_method(func, cls): return types.MethodType(func, None, cls) class Iterator(object): def next(self): return type(self).__next__(self) callable = callable _add_doc(get_unbound_function, """Get the function out of a possibly unbound function""") get_method_function = operator.attrgetter(_meth_func) get_method_self = operator.attrgetter(_meth_self) get_function_closure = operator.attrgetter(_func_closure) get_function_code = operator.attrgetter(_func_code) get_function_defaults = operator.attrgetter(_func_defaults) get_function_globals = operator.attrgetter(_func_globals) if PY3: def iterkeys(d, **kw): return iter(d.keys(**kw)) def itervalues(d, **kw): return iter(d.values(**kw)) def iteritems(d, **kw): return iter(d.items(**kw)) def iterlists(d, **kw): return iter(d.lists(**kw)) viewkeys = operator.methodcaller("keys") viewvalues = operator.methodcaller("values") viewitems = operator.methodcaller("items") else: def iterkeys(d, **kw): return d.iterkeys(**kw) def itervalues(d, **kw): return d.itervalues(**kw) def iteritems(d, **kw): return d.iteritems(**kw) def iterlists(d, **kw): return d.iterlists(**kw) viewkeys = operator.methodcaller("viewkeys") viewvalues = operator.methodcaller("viewvalues") viewitems = operator.methodcaller("viewitems") _add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") _add_doc(itervalues, "Return an iterator over the values of a dictionary.") _add_doc(iteritems, "Return an iterator over the (key, value) pairs of a dictionary.") _add_doc(iterlists, "Return an iterator over the (key, [values]) pairs of a dictionary.") if PY3: def b(s): return s.encode("latin-1") def u(s): return s unichr = chr import struct int2byte = struct.Struct(">B").pack del struct byte2int = operator.itemgetter(0) indexbytes = operator.getitem iterbytes = iter import io StringIO = io.StringIO BytesIO = io.BytesIO _assertCountEqual = "assertCountEqual" if sys.version_info[1] <= 1: _assertRaisesRegex = "assertRaisesRegexp" _assertRegex = "assertRegexpMatches" else: _assertRaisesRegex = "assertRaisesRegex" _assertRegex = "assertRegex" else: def b(s): return s # Workaround for standalone backslash def u(s): return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") unichr = unichr int2byte = chr def byte2int(bs): return ord(bs[0]) def indexbytes(buf, i): return ord(buf[i]) iterbytes = functools.partial(itertools.imap, ord) import StringIO StringIO = BytesIO = StringIO.StringIO _assertCountEqual = "assertItemsEqual" _assertRaisesRegex = "assertRaisesRegexp" _assertRegex = "assertRegexpMatches" _add_doc(b, """Byte literal""") _add_doc(u, """Text literal""") def assertCountEqual(self, *args, **kwargs): return getattr(self, _assertCountEqual)(*args, **kwargs) def assertRaisesRegex(self, *args, **kwargs): return getattr(self, _assertRaisesRegex)(*args, **kwargs) def assertRegex(self, *args, **kwargs): return getattr(self, _assertRegex)(*args, **kwargs) if PY3: exec_ = getattr(moves.builtins, "exec") def reraise(tp, value, tb=None): if value is None: value = tp() if value.__traceback__ is not tb: raise value.with_traceback(tb) raise value else: def exec_(_code_, _globs_=None, _locs_=None): """Execute code in a namespace.""" if _globs_ is None: frame = sys._getframe(1) _globs_ = frame.f_globals if _locs_ is None: _locs_ = frame.f_locals del frame elif _locs_ is None: _locs_ = _globs_ exec("""exec _code_ in _globs_, _locs_""") exec_("""def reraise(tp, value, tb=None): raise tp, value, tb """) if sys.version_info[:2] == (3, 2): exec_("""def raise_from(value, from_value): if from_value is None: raise value raise value from from_value """) elif sys.version_info[:2] > (3, 2): exec_("""def raise_from(value, from_value): raise value from from_value """) else: def raise_from(value, from_value): raise value print_ = getattr(moves.builtins, "print", None) if print_ is None: def print_(*args, **kwargs): """The new-style print function for Python 2.4 and 2.5.""" fp = kwargs.pop("file", sys.stdout) if fp is None: return def write(data): if not isinstance(data, basestring): data = str(data) # If the file has an encoding, encode unicode with it. if (isinstance(fp, file) and isinstance(data, unicode) and fp.encoding is not None): errors = getattr(fp, "errors", None) if errors is None: errors = "strict" data = data.encode(fp.encoding, errors) fp.write(data) want_unicode = False sep = kwargs.pop("sep", None) if sep is not None: if isinstance(sep, unicode): want_unicode = True elif not isinstance(sep, str): raise TypeError("sep must be None or a string") end = kwargs.pop("end", None) if end is not None: if isinstance(end, unicode): want_unicode = True elif not isinstance(end, str): raise TypeError("end must be None or a string") if kwargs: raise TypeError("invalid keyword arguments to print()") if not want_unicode: for arg in args: if isinstance(arg, unicode): want_unicode = True break if want_unicode: newline = unicode("\n") space = unicode(" ") else: newline = "\n" space = " " if sep is None: sep = space if end is None: end = newline for i, arg in enumerate(args): if i: write(sep) write(arg) write(end) if sys.version_info[:2] < (3, 3): _print = print_ def print_(*args, **kwargs): fp = kwargs.get("file", sys.stdout) flush = kwargs.pop("flush", False) _print(*args, **kwargs) if flush and fp is not None: fp.flush() _add_doc(reraise, """Reraise an exception.""") if sys.version_info[0:2] < (3, 4): def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, updated=functools.WRAPPER_UPDATES): def wrapper(f): f = functools.wraps(wrapped, assigned, updated)(f) f.__wrapped__ = wrapped return f return wrapper else: wraps = functools.wraps def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" # This requires a bit of explanation: the basic idea is to make a dummy # metaclass for one level of class instantiation that replaces itself with # the actual metaclass. class metaclass(meta): def __new__(cls, name, this_bases, d): return meta(name, bases, d) return type.__new__(metaclass, 'temporary_class', (), {}) def add_metaclass(metaclass): """Class decorator for creating a class with a metaclass.""" def wrapper(cls): orig_vars = cls.__dict__.copy() slots = orig_vars.get('__slots__') if slots is not None: if isinstance(slots, str): slots = [slots] for slots_var in slots: orig_vars.pop(slots_var) orig_vars.pop('__dict__', None) orig_vars.pop('__weakref__', None) return metaclass(cls.__name__, cls.__bases__, orig_vars) return wrapper def python_2_unicode_compatible(klass): """ A decorator that defines __unicode__ and __str__ methods under Python 2. Under Python 3 it does nothing. To support Python 2 and 3 with a single code base, define a __str__ method returning text and apply this decorator to the class. """ if PY2: if '__str__' not in klass.__dict__: raise ValueError("@python_2_unicode_compatible cannot be applied " "to %s because it doesn't define __str__()." % klass.__name__) klass.__unicode__ = klass.__str__ klass.__str__ = lambda self: self.__unicode__().encode('utf-8') return klass # Complete the moves implementation. # This code is at the end of this module to speed up module loading. # Turn this module into a package. __path__ = [] # required for PEP 302 and PEP 451 __package__ = __name__ # see PEP 366 @ReservedAssignment if globals().get("__spec__") is not None: __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable # Remove other six meta path importers, since they cause problems. This can # happen if six is removed from sys.modules and then reloaded. (Setuptools does # this for some reason.) if sys.meta_path: for i, importer in enumerate(sys.meta_path): # Here's some real nastiness: Another "instance" of the six module might # be floating around. Therefore, we can't use isinstance() to check for # the six meta path importer, since the other six instance will have # inserted an importer with different class. if (type(importer).__name__ == "_SixMetaPathImporter" and importer.name == __name__): del sys.meta_path[i] break del i, importer # Finally, add the importer to the meta path import hook. sys.meta_path.append(_importer)