PK@N#] A(site-packages/pkg_resources/__init__.pyonu[ fcF@@s dZddlmZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlmZyddlZWnek r]ddlZnXddlmZddl m!Z!m"Z"m#Z#ddlm$Z$y&ddlm%Z%m&Z&m'Z'e(Z)Wnek re*Z)nXdd lm+Z,dd l-m.Z.m/Z/yddl0j1Z2e2j3Wnek r3e4Z2nXd d l5m6Z6dd lm7Z7ddlm8Z8e9de9de9de9dddfej:koddfknre;dnej<re4Z=e4Z>ne4Z?e4Z@e4ZAe4ZBe4ZCe4ZDe4ZEe4ZFe4ZGe4ZHe4ZIe4ZJe4ZKe4ZLe4ZMe4ZNe4ZOdePfdYZQdZRiZSdZTdZUdZVdZWdZXdZYdZZdZ[Z\d Z]d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@ddAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddegFZ^d<e_fdfYZ`d=e`fdgYZadheafdiYZbd>e`fdjYZcd?e`fdkYZdiZeejfd ZgdZhdlZid ZjdZkdmZldnZmdoZngdpZodqZpdrZqejrdsZsejrdtZteqZuduZvdvZwewZxdwZydxZze4dyZ{dzZ|dTfd{YZ}dUe}fd|YZ~d7efd}YZd~efdYZd6efdYZeZd@e;fdYZd8fdYZdZdZdZdZdZdZe4dZd[fdYZemeed\efdYZd]efdYZejdYefdYZeZdefdYZdefdYZd^efdYZeme jedVefdYZdWefdYZdXefdYZeTddidZe*dZe*dZee jee*dZeeedZe*dZdZdfdYZdZdZdZdZeejeee2dree2jeneTddieTddidZdZdZdZe4dZdZeejeee jeee2dr) ee2jendZeeedZidZdZdZdZdZejrdjZejrdejejBjZd;efdYZdZdZd9efdYZdefdYZdefdYZied6ed6ed6ZdZdefdYZdZd:e8jjfdYZdZdZdZdZdZdZe jddeQde(dZeedZedZdS(sZ Package resource API -------------------- A resource is a logical file contained within a package, or a logical subdirectory thereof. The package resource API expects resource names to have their path parts separated with ``/``, *not* whatever the local path separator is. Do not use os.path operations to manipulate resource names being passed into the API. The package resource API is designed to work with normal filesystem packages, .egg files, and unpacked .egg files. It can also work in a limited way with .zip files and with custom PEP 302 loaders that support the ``get_data()`` method. i(tabsolute_importN(t get_importer(tsix(turllibtmaptfilter(tutime(tmkdirtrenametunlink(topen(tisdirtspliti(t py31compat(tappdirs(t packagings&pkg_resources.extern.packaging.versions)pkg_resources.extern.packaging.specifierss+pkg_resources.extern.packaging.requirementss&pkg_resources.extern.packaging.markersisPython 3.3 or later is requiredt PEP440WarningcB@seZdZRS(sa Used when there is an issue with a version or specifier not complying with PEP 440. (t__name__t __module__t__doc__(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRnscC@s?ytjj|SWn$tjjk r:tjj|SXdS(N(RtversiontVersiontInvalidVersiont LegacyVersion(tv((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt parse_versionuscK@s-tj|tjtj||dS(N(tglobalstupdatet _state_varstdicttfromkeys(tvartypetkw((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_declare_statescC@sLi}t}x6tjD](\}}|d|||||tcC@s{t}tj|}|dk rwtjdkrwy-ddjtd |jdf}Wqwt k rsqwXn|S(sZReturn this platform's maximum compatible version. distutils.util.get_platform() normally reports the minimum version of Mac OS X that would be required to *use* extensions produced by distutils. But what we want when checking compatibility is to know the version of Mac OS X that we are *running*. To allow usage of packages that explicitly require a newer version of Mac OS X, we must also know the current version of the OS. If this condition occurs for any other platform with a version in its platform strings, this function should be extended accordingly. tdarwins macosx-%s-%st.iiN( tget_build_platformtmacosVersionStringtmatchR3tsystplatformtjoint _macosx_verstgroupt ValueError(tplattm((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytget_supported_platforms - trequiret run_scriptt get_providertget_distributiontload_entry_pointt get_entry_maptget_entry_infotiter_entry_pointstresource_stringtresource_streamtresource_filenametresource_listdirtresource_existstresource_isdirtdeclare_namespacet working_settadd_activation_listenertfind_distributionstset_extraction_pathtcleanup_resourcestget_default_cachet Environmentt WorkingSettResourceManagert Distributiont Requirementt EntryPointtResolutionErrortVersionConflicttDistributionNotFoundt UnknownExtratExtractionErrortparse_requirementsRt safe_namet safe_versiont get_platformtcompatible_platformst yield_linestsplit_sectionst safe_extrat to_filenametinvalid_markertevaluate_markertensure_directorytnormalize_pathtEGG_DISTt BINARY_DISTt SOURCE_DISTt CHECKOUT_DISTt DEVELOP_DISTtIMetadataProvidertIResourceProvidert FileMetadatat PathMetadatat EggMetadatat EmptyProvidertempty_providert NullProvidert EggProvidertDefaultProvidert ZipProvidertregister_findertregister_namespace_handlertregister_loader_typetfixup_namespace_packagesRtrun_maintAvailableDistributionscB@seZdZdZRS(s.Abstract base for dependency resolution errorscC@s|jjt|jS(N(t __class__RtreprR4(tself((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__repr__s(RRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR`scB@sDeZdZdZedZedZdZdZRS(s An already-installed version conflicts with the requested version. Should be initialized with the installed Distribution and the requested Requirement. s3{self.dist} is installed but {self.req} is requiredcC@s |jdS(Ni(R4(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytdistscC@s |jdS(Ni(R4(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytreqscC@s|jjtS(N(t _templatetformattlocals(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytreportscC@s$|s |S|j|f}t|S(st If required_by is non-empty, return a version of self that is a ContextualVersionConflict. (R4tContextualVersionConflict(Rt required_byR4((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt with_context s( RRRRtpropertyRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRas  RcB@s*eZdZejdZedZRS(s A VersionConflict that accepts a third parameter, the set of the requirements that required the installed Distribution. s by {self.required_by}cC@s |jdS(Ni(R4(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs(RRRRaRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs cB@sSeZdZdZedZedZedZdZdZ RS(s&A requested distribution was not foundsSThe '{self.req}' distribution was not found and is required by {self.requirers_str}cC@s |jdS(Ni(R4(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR(scC@s |jdS(Ni(R4(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt requirers,scC@s|js dSdj|jS(Nsthe applications, (RR>(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt requirers_str0s cC@s|jjtS(N(RRR(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR6scC@s |jS(N(R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__str__9s( RRRRRRRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRb"s cB@seZdZRS(s>Distribution doesn't have an "extra feature" of the given name(RRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRc=siicC@s|t|eZdZdZdZdZdZdZRS(cC@sdS(s;Does the package's distribution contain the named metadata?N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt has_metadataR6cC@sdS(s'The named metadata resource as a stringN((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt get_metadataR6cC@sdS(sYield named metadata resource as list of non-blank non-comment lines Leading and trailing whitespace is stripped from each line, and lines with ``#`` as the first non-blank character are omitted.N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytget_metadata_linesR6cC@sdS(s>Is the named metadata a directory? (like ``os.path.isdir()``)N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytmetadata_isdirR6cC@sdS(s?List of metadata names in the directory (like ``os.listdir()``)N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytmetadata_listdirR6cC@sdS(s=Execute the named script in the supplied namespace dictionaryN((Rt namespace((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRFR6(RRRRRRRRF(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRws      cB@sDeZdZdZdZdZdZdZdZRS(s3An object that provides access to package resourcescC@sdS(sdReturn a true filesystem path for `resource_name` `manager` must be an ``IResourceManager``N((tmanagert resource_name((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytget_resource_filenameR6cC@sdS(siReturn a readable file-like object for `resource_name` `manager` must be an ``IResourceManager``N((RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytget_resource_stream R6cC@sdS(smReturn a string containing the contents of `resource_name` `manager` must be an ``IResourceManager``N((RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytget_resource_stringR6cC@sdS(s,Does the package contain the named resource?N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt has_resourceR6cC@sdS(s>Is the named resource a directory? (like ``os.path.isdir()``)N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRRR6cC@sdS(s?List of resource names in the directory (like ``os.listdir()``)N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRPR6( RRRRRRRRRRP(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRxs     cB@seZdZddZedZedZdZdZ dZ ddZ dZ d Z deed Zddedd Zdded Zd ZedZdZdZdZRS(sDA collection of active distributions on sys.path (or a similar list)cC@s^g|_i|_i|_g|_|dkr<tj}nx|D]}|j|qCWdS(s?Create working set from list of path entries (default=sys.path)N(tentriest entry_keystby_keyt callbacksR3R<Rt add_entry(RRtentry((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__init__#s       cC@se|}yddlm}Wntk r1|SXy|j|Wntk r`|j|SX|S(s1 Prepare the master working set. i(t __requires__(t__main__RRRERat_build_from_requirements(tclstwsR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt _build_master0s   cC@s|g}t|}|j|t}x|D]}|j|q4Wx0tjD]%}||jkrU|j|qUqUW|jtj(|S(sQ Build a working set from a requirement spec. Rewrites sys.path. (RetresolveRZtaddR<RRR(Rtreq_specRtreqstdistsRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRDs    cC@sT|jj|g|jj|x*t|tD]}|j||tq3WdS(sAdd a path item to ``.entries``, finding any distributions on it ``find_distributions(entry, True)`` is used to find distributions corresponding to the path entry, and they are added. `entry` is always appended to ``.entries``, even if it is already present. (This is because ``sys.path`` can contain the same value more than once, and the ``.entries`` of the ``sys.path`` WorkingSet should always equal ``sys.path``.) N(Rt setdefaultRRRVRRR(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRZs cC@s|jj|j|kS(s9True if `dist` is the active distribution for its project(RRR.(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt __contains__iscC@sC|jj|j}|dk r?||kr?t||n|S(sFind a distribution matching requirement `req` If there is an active distribution for the requested project, this returns it as long as it meets the version requirement specified by `req`. But, if there is an active distribution for the project and it does *not* meet the `req` requirement, ``VersionConflict`` is raised. If there is no active distribution for the requested project, ``None`` is returned. N(RRR.R3Ra(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRms cc@sgx`|D]X}|j|}|dkrGx4|jD] }|Vq5Wq||kr||VqqWdS(sYield entry point objects from `group` matching `name` If `name` is None, yields all entry points in `group` from all distributions in the working set, otherwise only ones matching both `group` and `name` are yielded (in distribution order). N(RJR3tvalues(RR@RRRtep((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRL}s    cC@sQtjdj}|d}|j||d<|j|dj||dS(s?Locate distribution for `requires` and run `script_name` scriptiRiN(R<RRR-RERF(RtrequiresRRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRFs    cc@spi}xc|jD]X}||jkr+qnx:|j|D]+}||kr9d||<|j|Vq9q9WqWdS(sYield distributions for non-duplicate projects in the working set The yield order is the order in which the items' path entries were added to the working set. iN(RRR(RtseentitemR.((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__iter__s  cC@s|r"|j|j|d|n|dkr:|j}n|jj|g}|jj|jg}| r|j|jkrdS||j|j<|j|kr|j|jn|j|kr|j|jn|j |dS(sAdd `dist` to working set, associated with `entry` If `entry` is unspecified, it defaults to the ``.location`` of `dist`. On exit from this routine, `entry` is added to the end of the working set's ``.entries`` (if it wasn't already present). `dist` is only added to the working set if it's for a project that doesn't already have a distribution in the set, unless `replace=True`. If it's added, any callbacks registered with the ``subscribe()`` method will be called. RN( t insert_onRR3tlocationRRR.RRt _added_new(RRRtinsertRtkeystkeys2((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   cC@s+t|ddd}i}i}g}t} tjt} x|r&|jd} | |krmqFn| j| |sqFn|j| j} | dkr|j j| j} | dks| | krz|rz|} |dkr!| dkrt |j }q!t g}t g} n|j| | |d|} || j<| dkrz| j| d}t| |qzn|j| n| | kr| | }t| | j|n| j| jddd}|j|x/|D]'}| |j| j| j| | Map each requirement to the extras that demanded it. c@s@fd|jd|p$dD}j p?t|S(s Evaluate markers for req against each extra that demanded it. Return False if the req has a marker and fails evaluation. Otherwise, return True. c3@s(|]}jji|d6VqdS(textraN(tmarkertevaluate(t.0R)(R(s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pys s(N(N(RR3R*tany(RRR t extra_evals((Rs:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s  N(RRRR3R (((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscB@seZdZd eedZdZdZd dZ dZ dZ d e dZ d dZd Zd Zd ZRS( s5Searchable snapshot of distributions on a search pathcC@s,i|_||_||_|j|dS(s!Snapshot distributions available on a search path Any distributions found on `search_path` are added to the environment. `search_path` should be a sequence of ``sys.path`` items. If not supplied, ``sys.path`` is used. `platform` is an optional string specifying the name of the platform that platform-specific distributions must be compatible with. If unspecified, it defaults to the current platform. `python` is an optional string naming the desired version of Python (e.g. ``'3.3'``); it defaults to the current version. You may explicitly set `platform` (and/or `python`) to ``None`` if you wish to map *all* distributions, not just those compatible with the running platform or Python version. N(t_distmapR=tpythontscan(Rt search_pathR=R0((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   cC@sI|jdkp-|jdkp-|j|jk}|oHt|j|jS(sIs distribution `dist` acceptable for this environment? The distribution must match the platform and python version requirements specified when this environment was created, or False is returned. N(R0R3t py_versionRiR=(RRt py_compat((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytcan_addscC@s|j|jj|dS(s"Remove `dist` from the environmentN(R/R.tremove(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR6scC@sQ|dkrtj}nx2|D]*}x!t|D]}|j|q2WqWdS(sdScan `search_path` for distributions usable in this environment Any distributions found are added to the environment. `search_path` should be a sequence of ``sys.path`` items. If not supplied, ``sys.path`` is used. Only distributions conforming to the platform/python version defined at initialization are added. N(R3R<RRVR(RR2RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR1s    cC@s|j}|jj|gS(sReturn a newest-to-oldest list of distributions for `project_name` Uses case-insensitive `project_name` comparison, assuming all the project's distributions use their project's name converted to all lowercase as their key. (tlowerR/R(RR tdistribution_key((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt __getitem__s cC@su|j|rq|jrq|jj|jg}||krq|j||jdtjddt qqndS(sLAdd `dist` if we ``can_add()`` it and it has not already been added R.thashcmptreverseN( R5t has_versionR/RR.RRtoperatort attrgetterR(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   cC@sy|j|}Wn#tk r8|s/nd}nX|dk rI|Sx%||jD]}||krW|SqWW|j||S(sFind distribution best matching `req` and usable on `working_set` This calls the ``find(req)`` method of the `working_set` to see if a suitable distribution is already active. (This may raise ``VersionConflict`` if an unsuitable version of the project is already active in the specified `working_set`.) If a suitable distribution isn't active, this method returns the newest distribution in the environment that meets the ``Requirement`` in `req`. If no suitable distribution is found, and `installer` is supplied, then the result of calling the environment's ``obtain(req, installer)`` method will be returned. N(RRaR3R.tobtain(RRRTRRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s    cC@s|dk r||SdS(sObtain a distribution matching `requirement` (e.g. via download) Obtain a distro that matches requirement (e.g. via download). In the base ``Environment`` class, this routine just returns ``installer(requirement)``, unless `installer` is None, in which case None is returned instead. This method is a hook that allows subclasses to attempt other ways of obtaining a distribution before falling back to the `installer` argument.N(R3(Rt requirementR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR?#s cc@s0x)|jjD]}||r|VqqWdS(s=Yield the unique project names of the available distributionsN(R/R(RR.((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR/s cC@s{t|tr|j|nXt|trdxF|D](}x||D]}|j|qFWq5Wntd|f|S(s2In-place addition of a distribution or environmentsCan't add %r to environment(RR]RRZR(RtothertprojectR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__iadd__5s cC@s@|jgdddd}x||fD]}||7}q(W|S(s4Add an environment or distribution to an environmentR=R0N(RR3(RRAtnewR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__add__AsN(RRRR3RDtPY_MAJORRR5R6R1R9RRR R?RRCRE(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRZs        cB@seZdZRS(sTAn error occurred extracting a resource The following attributes are available from instances of this exception: manager The resource manager that raised this exception cache_path The base directory for resource extraction original_error The exception instance that caused extraction to fail (RRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRdMs cB@seZdZdZdZdZdZdZdZ dZ dZ dZ dd Z ed Zd Zd Zed ZRS(s'Manage resource extraction and packagescC@s i|_dS(N(t cached_files(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRascC@st|j|S(sDoes the named resource exist?(RGR(Rtpackage_or_requirementR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRQdscC@st|j|S(s,Is the named resource an existing directory?(RGRR(RRHR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRRhs cC@st|j||S(s4Return a true filesystem path for specified resource(RGR(RRHR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyROns cC@st|j||S(s9Return a readable file-like object for specified resource(RGR(RRHR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRNts cC@st|j||S(s%Return specified resource as a string(RGR(RRHR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRMzs cC@st|j|S(s1List the contents of the named resource directory(RGRP(RRHR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRPs cC@sttjd}|jpt}tjdj}t|jt }||_ ||_ ||_ |dS(s5Give an error message for problems extracting file(s)is Can't extract file(s) to egg cache The following error occurred while trying to extract file(s) to the Python egg cache: {old_exc} The Python egg cache directory is currently set to: {cache_path} Perhaps your account does not have write access to this directory? You can change the cache directory by setting the PYTHON_EGG_CACHE environment variable to point to an accessible directory. N( R<texc_infotextraction_pathRYttextwraptdedenttlstripRdRRRt cache_pathtoriginal_error(Rtold_excRNttmplterr((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytextraction_errors   cC@sx|jpt}tjj||d|}yt|Wntk rY|jnX|j|d|j |<|S(sReturn absolute location in cache for `archive_name` and `names` The parent directory of the resulting path will be created if it does not already exist. `archive_name` should be the base filename of the enclosing egg (which may not be the name of the enclosing zipfile!), including its ".egg" extension. `names`, if provided, should be a sequence of path name parts "under" the egg's extraction location. This method should only be called by resource providers that need to obtain an extraction location, and only for names they intend to extract, as it tracks the generated names for possible cleanup later. s-tmpi( RJRYRRR>t_bypass_ensure_directoryt ExceptionRSt_warn_unsafe_extraction_pathRG(Rt archive_nametnamest extract_patht target_path((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytget_cache_paths    cC@swtjdkr*|jtjd r*dStj|j}|tj@sV|tj@rsd|}tj |t ndS(sN If the default extraction path is overridden and set to an insecure location, such as /tmp, it opens up an opportunity for an attacker to replace an extracted file with an unauthorized payload. Warn the user if a known insecure location is used. See Distribute #375 for more details. tnttwindirNs%s is writable by group/others and vulnerable to attack when used with get_resource_filename. Consider a more secure location (set with .set_extraction_path or the PYTHON_EGG_CACHE environment variable).( RRRtenvirontstattst_modetS_IWOTHtS_IWGRPtwarningstwarnt UserWarning(Rtmodetmsg((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRVs &cC@s@tjdkr<tj|jdBd@}tj||ndS(s4Perform any platform-specific postprocessing of `tempname` This is where Mac header rewrites should be done; other platforms don't have anything special they should do. Resource providers should call this method ONLY after successfully extracting a compressed resource. They must NOT call it on resources that are already in the filesystem. `tempname` is the current (temporary) name of the file, and `filename` is the name it will be renamed to by the caller after this routine returns. tposiximiN(RRR_R`tchmod(RttempnametfilenameRf((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt postprocessscC@s%|jrtdn||_dS(sSet the base path where resources will be extracted to, if needed. If you do not call this routine before any extractions take place, the path defaults to the return value of ``get_default_cache()``. (Which is based on the ``PYTHON_EGG_CACHE`` environment variable, with various platform-specific fallbacks. See that routine's documentation for more details.) Resources are extracted to subdirectories of this path based upon information given by the ``IResourceProvider``. You may set this to a temporary directory, but then you must call ``cleanup_resources()`` to delete the extracted files when done. There is no guarantee that ``cleanup_resources()`` will be able to remove all extracted files. (Note: you may not change the extraction path for a given resource manager once resources have been extracted, unless you first call ``cleanup_resources()``.) s5Can't change extraction path, files already extractedN(RGRARJ(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRWs  cC@sdS(sB Delete all extracted resource files and directories, returning a list of the file and directory names that could not be successfully removed. This function does not have any concurrency protection, so it should generally only be called when the extraction path is a temporary directory exclusive to a single process. This method is not automatically called; you must call it explicitly or register it as an ``atexit`` function if you wish to ensure cleanup of a temporary directory used for extractions. N((Rtforce((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRXR6N((RRRR3RJRRQRRRORNRMRPRSR[t staticmethodRVRlRWRRX(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR\]s           cC@s"tjjdp!tjddS(s Return the ``PYTHON_EGG_CACHE`` environment variable or a platform-relevant user cache dir for an app named "Python-Eggs". tPYTHON_EGG_CACHEtappnames Python-Eggs(RR^RRtuser_cache_dir(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRYscC@stjdd|S(sConvert an arbitrary string to a standard distribution name Any runs of non-alphanumeric/. characters are replaced with a single '-'. s[^A-Za-z0-9.]+t-(tretsub(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRfscC@sZyttjj|SWn9tjjk rU|jdd}tjdd|SXdS(sB Convert an arbitrary string to a standard version string RR8s[^A-Za-z0-9.]+RrN(RRRRRRRsRt(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRg%s cC@stjdd|jS(sConvert an arbitrary string to a standard 'extra' name Any runs of non-alphanumeric characters are replaced with a single '_', and the result is always lowercased. s[^A-Za-z0-9.-]+R(RsRtR7(R)((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRl1scC@s|jddS(s|Convert a project or version name to its filename-escaped form Any '-' characters are currently replaced with '_'. RrR(R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRm:scC@s;yt|Wn&tk r6}d|_d|_|SXtS(so Validate text as a PEP 508 environment marker; return an exception if invalid or False otherwise. N(Rot SyntaxErrorR3RktlinenoR(ttextte((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRnBs  cC@sLy tjj|}|jSWn%tjjk rG}t|nXdS(s Evaluate a PEP 508 environment marker. Return a boolean indicating the marker result in this environment. Raise SyntaxError if marker is invalid. This implementation uses the 'pyparsing' module. N(RtmarkerstMarkerR+t InvalidMarkerRu(RwR)R*Rx((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRoPs cB@seZdZdZdZdZdZdZdZ dZ dZ dZ dZ dZd Zd Zd Zd Zd ZdZdZdZdZdZRS(sETry to implement resources and metadata for arbitrary PEP 302 loaderscC@s:t|dd|_tjjt|dd|_dS(NRt__file__R6(RR3RRRtdirnamet module_path(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRfscC@s|j|j|S(N(t_fnR~(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRjscC@stj|j||S(N(tiotBytesIOR(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRmscC@s|j|j|j|S(N(t_getRR~(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRpscC@s|j|j|j|S(N(t_hasRR~(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRsscC@s%|jo$|j|j|j|S(N(tegg_infoRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRvscC@sE|js dS|j|j|j|}tjrA|jdS|S(NR6sutf-8(RRRRtPY3tdecode(RRtvalue((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRys cC@st|j|S(N(RjR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|j|j|j|S(N(t_isdirRR~(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRRscC@s%|jo$|j|j|j|S(N(RRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|j|j|j|S(N(t_listdirRR~(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRPscC@s)|jr%|j|j|j|SgS(N(RRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs c B@sd|}|j|s4edjen|j|jdd}|jdd}|j|j|}||dR (RtbaseR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s2t|jdr"|jj|StddS(Ntget_datas=Can't perform this operation for loaders without 'get_data()'(RRRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRsN(RRRR3tegg_nameRRRRRRRRRRRRRRPRRFRRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR~_s,                 cB@s eZdZdZdZRS(s&Provider based on a virtual filesystemcC@stj|||jdS(N(R~Rt _setup_prefix(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|j}d}xt||krt|rdtjj||_tjj|d|_||_ Pn|}tjj |\}}qWdS(NsEGG-INFO( R~R3t _is_egg_pathRRtbasenameRR>Rtegg_rootR (RRtoldR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   (RRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs cB@sJeZdZdZdZdZdZdZedZ RS(s6Provides access to package resources in the filesystemcC@stjj|S(N(RRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@stjj|S(N(RRR (RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s tj|S(N(Rtlistdir(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@st|j|j|dS(Ntrb(R RR~(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s&t|d}|jSWdQXdS(NR(R R(RRtstream((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s)ttdtd}t||dS(NtSourceFileLoader(Rtimportlib_machineryttypeR3R(Rt loader_cls((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt _registers ( RRRRRRRRR(R(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs     cB@s<eZdZdZdZZdZdZdZ RS(s.Provider that returns nothing for all requestscC@stS(N(R(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR5R6cC@sdS(NR6((RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@sgS(N((RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@sdS(N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR sN( RRRR3R~RRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR|s    t ZipManifestscB@s#eZdZedZeZRS(s zip manifest builder c@sBtj|-fdjD}t|SWdQXdS(s Build a dictionary similar to the zipimport directory caches, except instead of tuples, store ZipInfo objects. Use a platform-specific path separator (os.sep) for the path keys for compatibility with pypy on Windows. c3@s3|])}|jdtjj|fVqdS(RN(RRtseptgetinfo(R,R(tzfile(s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pys sN(tzipfiletZipFiletnamelistR(RRR#((Rs:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytbuilds  (RRRR(Rtload(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRstMemoizedZipManifestscB@s)eZdZejddZdZRS(s% Memoized zipfile manifests. t manifest_modsmanifest mtimecC@svtjj|}tj|j}||ksC||j|krk|j|}|j||||Rt_extract_resourcet _eager_to_zip(RRRRteagersR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRcs     cC@s/|j}|jd}tj|}||fS(Nii(iii(t file_sizet date_timettimetmktime(tzip_stattsizeRt timestamp((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_get_date_and_sizeps  c C@s||jkr^x9|j|D]'}|j|tjj||}q#Wtjj|S|j|j|\}}tst dny(|j |j |j |}|j ||r|Stddtjj|\}} tj||jj|tj|t| ||f|j| |yt| |Wnltjk rtjj|r|j ||r|Stjdkrt|t| ||SnnXWntjk r|jnX|S(Ns>"os.rename" and "os.unlink" are not supported on this platforms .$extracttdirR\(t_indexRRRR>R}RRt WRITE_SUPPORTtIOErrorR[RRt _is_currentt_mkstemptwriteRRtcloseRRlRterrortisfileRR RS( RRRRtlastRRt real_pathtoutfttmpnam((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRysD    c C@s|j|j|\}}tjj|s2tStj|}|j|ks_|j|krctS|j j |}t |d}|j }WdQX||kS(sK Return True if the file_path is current for this zip_path RN( RRRRRRR_tst_sizeRRRR R( Rt file_pathRRRR_t zip_contentstft file_contents((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@sa|jdkrZg}x6dD].}|j|r|j|j|qqW||_n|jS(Nsnative_libs.txtseager_resources.txt(snative_libs.txtseager_resources.txt(RR3RR R(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs  cC@sy |jSWntk ri}x~|jD]s}|jtj}xX|rtjj|d }||kr||j|dPqF|jg||RR(RtindRtpartstparent((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs     cC@s.|j|}||jkp-||jkS(N(RRR(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|j||jkS(N(RR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s%t|jj|j|dS(N((RRRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|j|j|j|S(N(RRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|j|j|j|S(N(RRR~(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRsN(RRRR3RRRRRRRRRRnRRRRRRRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR?s$     7      cB@s;eZdZdZdZdZdZdZRS(s*Metadata handler for standalone PKG-INFO files Usage:: metadata = FileMetadata("/path/to/PKG-INFO") This provider rejects all data and metadata requests except for PKG-INFO, which is treated as existing, and will be the contents of the file at the provided location. cC@s ||_dS(N(R(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|dkotjj|jS(NsPKG-INFO(RRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s_|dkrtdntj|jdddd}|j}WdQX|j||S(NsPKG-INFOs(No metadata except PKG-INFO is availabletencodingsutf-8terrorsR(RRR RRt_warn_on_replacement(RRRtmetadata((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs  ! cC@sGdjd}||krCd}|jt}tj|ndS(Ns�sutf-8s2{self.path} could not be properly decoded in UTF-8(RRRRcRd(RRtreplacement_charRQRg((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s  cC@st|j|S(N(RjR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs(RRRRRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRys     cB@seZdZdZRS(ssMetadata provider for egg directories Usage:: # Development eggs: egg_info = "/path/to/PackageName.egg-info" base_dir = os.path.dirname(egg_info) metadata = PathMetadata(base_dir, egg_info) dist_name = os.path.splitext(os.path.basename(egg_info))[0] dist = Distribution(basedir, project_name=dist_name, metadata=metadata) # Unpacked egg directories: egg_path = "/path/to/PackageName-ver-pyver-etc.egg" metadata = PathMetadata(egg_path, os.path.join(egg_path,'EGG-INFO')) dist = Distribution.from_filename(egg_path, metadata=metadata) cC@s||_||_dS(N(R~R(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR)s (RRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRzscB@seZdZdZRS(s Metadata provider for .egg filescC@s`|jtj|_||_|jrFtjj|j|j|_n |j|_|j dS(s-Create a metadata provider from a zipimporterN( RRRRRtprefixRR>R~R(Rtimporter((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR1s   ! (RRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR{.sRt_distribution_finderscC@s|t|tfind_eggs_in_zipt zipimportt zipimporterR7Rt from_location( RRRRtsubitemtsubpathRRtsubmeta((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRQs$     cC@sdS(N(((RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt find_nothingoscC@sd}t|d|dtS(sL Given a list of filenames, return them in descending order by version number. >>> names = 'bar', 'foo', 'Python-2.7.10.egg', 'Python-2.7.2.egg' >>> _by_version_descending(names) ['Python-2.7.10.egg', 'Python-2.7.2.egg', 'foo', 'bar'] >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.egg' >>> _by_version_descending(names) ['Setuptools-1.2.3.egg', 'Setuptools-1.2.3b1.egg'] >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.post1.egg' >>> _by_version_descending(names) ['Setuptools-1.2.3.post1.egg', 'Setuptools-1.2.3b1.egg'] cS@sYtjj|\}}tj|jd|g}g|D]}tjj|^q=S(s6 Parse each component of the filename Rr( RRtsplitextt itertoolstchainR RRR(RtextRtpart((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt _by_versionsR.R;(tsortedR(RXR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_by_version_descendingvs c #@sttrHtjdttjjdVdSt}fd|D}t |}xQ|D]I}tjj|}t |}x||D] } | VqWqWdS(s6Yield distributions accessible on a sys.path directoryRsEGG-INFONc3@s'|]}t|r|VqdS(N(t dist_factory(R,R(RR(s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pys s( t_normalize_cachedt_is_unpacked_eggR]RRzRRR>t safe_listdirRR( RRRRtfilteredtpath_item_entriesRtfullpathtfactoryR((RRs:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt find_on_paths       cC@sf|j}tt|jd}|r.tS| rEt|rEtS| r_|jdr_tStS(s9 Return a dist_factory for a path_item and entry s .egg-infos .dist-infos .egg-link(s .egg-infos .dist-info( R7R-RRtdistributions_from_metadataRRVtresolve_egg_linktNoDists(RRRR7tis_meta((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   RcB@s2eZdZdZejr'eZndZRS(sS >>> bool(NoDists()) False >>> list(NoDists()('anything')) [] cC@stS(N(R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__bool__scC@s tdS(N((titer(RR ((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__call__s(RRRRRtPY2t __nonzero__R(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs    cC@sytj|SWnnttfk r*nXtk r}|jtjtjtjfkpot |dddk}|sqnXdS(sI Attempt to list contents of path, but suppress some exceptions. twinerrori N(( RRtPermissionErrortNotADirectoryErrortOSErrorterrnotENOTDIRtEACCEStENOENTRR3(RRxt ignorable((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s! cc@stjj|}tjj|rUttj|dkrCdSt||}n t|}tjj|}t j |||dt VdS(Nit precedence( RRR}R RRRzRyRR]RRv(RtrootRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs cc@sDt|2}x(|D] }|j}|r|VqqWWdQXdS(s1 Yield non-empty lines from file at path N(R tstrip(RRtline((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytnon_empty_liness   c@s>t}fd|D}tt|}t|dS(sa Given a path to an .egg-link, resolve distributions present in the referenced path. c3@s0|]&}tjjtjj|VqdS(N(RRR>R}(R,tref(R(s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pys s((R%RRVtnext(Rtreferenced_pathstresolved_pathst dist_groups((Rs:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs    t FileFindert_namespace_handlerst_namespace_packagescC@s|t|(Rt path_partst module_partsR(t package_nameR=(s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytposition_in_sys_pathTs NR.(R<RRRRRR/(t orig_pathRARtpRB((RAR=R<s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR5Ds"  cC@s tjz|tkrdStjd}}d|krdj|jdd }t||tkrxt |nytj |j }Wqt k rt d|qXntj|gj|tj|gx|D]}t||qWWdtjXdS(s9Declare that package 'packageName' is a namespace packageNR8isNot a package:(t_impt acquire_lockR-R<RR3R>R RSRRR/RRRRR8t release_lock(R6RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRSes&        cC@sbtjzFx?tj|dD]+}t||}|r t||q q WWdtjXdS(sDEnsure that previously-declared namespace packages include path_itemN((RERFR-RR8RRG(RRtpackageR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs cC@s`tjj||jdd}t|}x+|jD]}t||kr8Pq8q8W|SdS(sBCompute an ns-package subpath for a filesystem or zipfile importerR8iN(RRR>R RR/(RRR6RRt normalizedR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytfile_ns_handlers " cC@sdS(N(R3(RRR6R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytnull_ns_handlerscC@stjjtjj|S(s1Normalize a file/dir name for comparison purposes(RRtnormcasetrealpath(Rk((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRqscC@s9y ||SWn&tk r4t|||<}|SXdS(N(RRq(RkRtresult((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   cC@s|jjdS(s7 Determine if given path appears to be an egg. s.egg(R7R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s.t|o-tjjtjj|ddS(s@ Determine if given path appears to be an unpacked egg. sEGG-INFOsPKG-INFO(RRRRR>(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs cC@sU|jd}|j}|rQdj|}ttj||tj|ndS(NR8(R RR>tsetattrR<R(R6RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR3s  cc@st|tjrVxn|jD]0}|j}|r|jd r|VqqWn-x*|D]"}xt|D] }|VqpWq]WdS(s9Yield non-empty/non-comment lines of a string or sequencet#N(RRRt splitlinesR#RRj(tstrststss((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRjs  s \w+(\.\w+)*$s (?P[^-]+) ( -(?P[^-]+) ( -py(?P[^-]+) ( -(?P.+) )? )? )? cB@seZdZd d ddZdZdZedZdZ dddZ e j dZ eddZed Zedd Zedd ZRS(s3Object representing an advertised importable objectcC@s[t|std|n||_||_t||_t||_||_dS(NsInvalid module name(tMODULERARt module_namettupletattrsR R(RRRVRXR R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   cC@sfd|j|jf}|jr<|ddj|j7}n|jrb|ddj|j7}n|S(Ns%s = %st:R8s [%s]t,(RRVRXR>R (RRS((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   cC@sdt|S(NsEntryPoint.parse(%r)(R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR scO@sO| s|s|r,tjdtddn|rE|j||n|jS(sH Require packages for this EntryPoint, then resolve it. sJParameters to load are deprecated. Call .resolve and .require separately.t stackleveli(RcRdtDeprecationWarningRER(RRER4tkwargs((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s cC@sdt|jddgdd}ytjt|j|SWn%tk r_}tt|nXdS(sD Resolve the entry point from its module and attrs. tfromlistRtleveliN( RRVt functoolstreduceRRXRRR(RRtexc((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s cC@sr|jr%|j r%td|n|jj|j}tj|||d|j}tttj|dS(Ns&Can't require() without a distributionR ( R RRcRRTRRRR(RRRRR#((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRE s s]\s*(?P.+?)\s*=\s*(?P[\w.]+)\s*(:\s*(?P[\w.]+))?\s*(?P\[.*\])?\s*$cC@s|jj|}|s0d}t||n|j}|j|d}|drl|djdnd}||d|d|||S(sParse a single entry point from string `src` Entry point syntax follows the form:: name = some.module:some.attr [extra1, extra2] The entry name and module name are required, but the ``:attrs`` and ``[extras]`` parts are optional s9EntryPoint must be in 'name=module:attrs [extras]' formatR tattrR8RR((tpatternR;RAt groupdictt _parse_extrasR (RtsrcRRCRgtresR RX((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR6 s  #cC@s9|s dStjd|}|jr2tn|jS(Ntx((R^RtspecsRAR (Rt extras_specR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRfJ s   cC@st|std|ni}xZt|D]L}|j||}|j|krptd||jn|||j '{project_name} ({version})' is being parsed as a legacy, non PEP 440, version. You may find odd behavior and sort order. In particular it will be sorted as less than 0.0. It is recommended to migrate to PEP 440 compatible versions. s R(RRRRRRKRLR#RRcRdRtvarsR(RtLVt is_legacyRQ((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_warn_legacy_version s  cC@sgy |jSWnUtk rbt|j|j}|dkr^d}t||j|n|SXdS(Ns(Missing 'Version:' header and/or %s file(R{RRyt _get_metadatatPKG_INFOR3RA(RRRQ((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s   cC@s>y |jSWn)tk r6|j|j|_nX|jS(s~ A map of extra to its list of (direct) requirements for this distribution, including the null extra. (t_Distribution__dep_mapRt_filter_extrast_build_dep_map(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_dep_map s   cC@sxttd|D]}|}|j|}|jd\}}}|oet|pet| }|rwg}nt|pd}|j|gj |qW|S(s Given a mapping of extras to dependencies, strip off environment markers and filter out any dependencies not matching the markers. RYN( RRR3RRwRnRoRlRR (tdmR)t new_extraRRR*t fails_marker((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s   cC@s`i}xSdD]K}xBt|j|D]+\}}|j|gjt|q)Wq W|S(Ns requires.txts depends.txt(s requires.txts depends.txt(RkRRR Re(RRRR)R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR, s  "'cC@s|j}g}|j|jddxS|D]K}y|j|t|Wq/tk rytd||fq/Xq/W|S(s@List of Requirements needed for this distro if `extras` are useds%s has no such extra feature %rN((RR RR3RlRRc(RR RtdepsR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR3 s   cc@s5|j|r1x|j|D] }|VqWndS(N(RR(RRR$((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRA scC@s|dkrtj}n|j|d||tjkrt|jx6|jdD]"}|tjkrWt|qWqWWndS(s>Ensure distribution is importable on `path` (default=sys.path)Rsnamespace_packages.txtN( R3R<RRRRRRRS(RRRtpkg((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytactivateF s   cC@sOdt|jt|j|jp'tf}|jrK|d|j7}n|S(s@Return what this distribution's standard .egg filename should bes %s-%s-py%sRr(RmR RR3RFR=(RRk((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRQ s  cC@s(|jrd||jfSt|SdS(Ns%s (%s)(RR(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR\ s cC@sMyt|dd}Wntk r/d}nX|p9d}d|j|fS(NRs[unknown version]s%s %s(RR3RAR (RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRb s    cC@s.|jdrt|nt|j|S(sADelegate all unrecognized public attributes to .metadata providerR(RRRR|(RRc((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt __getattr__j scK@s(|jt|tjj|||S(N(RRRRR(RRkRR ((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRp scC@sTt|jtjjr1d|j|jf}nd|j|jf}tj|S(s?Return a ``Requirement`` that matches this distribution exactlys%s==%ss%s===%s(RRRRRR R^R(Rtspec((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRw scC@sD|j||}|dkr:td||ffn|jS(s=Return the `name` entry point of `group` or raise ImportErrorsEntry point %r not foundN(RKR3RR(RR@RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRI s cC@scy |j}Wn3tk rBtj|jd|}|_nX|dk r_|j|iS|S(s=Return the entry point map for `group`, or the full entry mapsentry_points.txtN(t_ep_mapRR_RqRR3R(RR@tep_map((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRJ s    cC@s|j|j|S(s<Return the EntryPoint object for `group`+`name`, or ``None``(RJR(RR@R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRK sc C@s|p |j}|sdSt|}tjj|}g|D]}|rVt|pY|^q>}xt|D]\}}||kr|rPqdSqo||kro|jtkro| r|||krdS|tjkr|j n|j |||j ||PqoqoW|tjkr.|j n|rG|j d|n |j |dSxMt ry|j ||d} Wntk rPq[X|| =|| =| }q[WdS(sEnsure self.location is on path If replace=False (default): - If location is already in path anywhere, do nothing. - Else: - If it's an egg and its parent directory is on path, insert just ahead of the parent. - Else: add to the end of path. If replace=True: - If location is already on path anywhere (not eggs) or higher priority than its parent (eggs) do nothing. - Else: - If it's an egg and its parent directory is on path, insert just ahead of the parent, removing any lower-priority entries. - Else: add it to the front of path. Nii(RRRRR}t enumerateR!RrR<tcheck_version_conflictRRRR:RA( RRtlocRtnloctbdirRDtnpathRtnp((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR sB +       cC@s|jdkrdStj|jd}t|j}x|jdD]}|tjksJ||ksJ|tkr}qJn|dkrqJnt tj|dd}|rt|j |sJ|j |jrqJnt d|||jfqJWdS( Nt setuptoolssnamespace_packages.txts top_level.txtt pkg_resourcestsiteR|sIModule %s was already imported from %s, but %s is being added to sys.path(RRR( R.RRRRqRR<RR-RR3Rt issue_warning(RtnspRtmodnametfn((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s"  cC@s8y |jWn&tk r3tdt|tSXtS(NsUnbuilt egg for (RRARRRR(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR< s   cK@sYd}x0|jD]"}|j|t||dqW|jd|j|j|S(s@Copy this distribution, substituting in any changed keyword argss<project_name version py_version platform location precedenceRN(R RRR3R|R(RR RXRc((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytclone s  cC@s g|jD]}|r |^q S(N(R(Rtdep((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR  sN((.RRRRR3RFRrRR(RRRR:RRRRRRRR.RRRRRnRRRRRRRRRRRRRIRJRKRRR<RR (((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR] sR                      D   tEggInfoDistributioncB@seZdZRS(cC@s.t|j|j}|r*||_n|S(s Packages installed by distutils (e.g. numpy or scipy), which uses an old safe_version, and so their version numbers can get mangled when converted to filenames (e.g., 1.11.0.dev0+2329eae to 1.11.0.dev0_2329eae). These distributions will not be parsed properly downstream by Distribution and safe_version, so take an extra step and try to get the version number from the metadata file itself instead of the filename. (RyRRR{(Rt md_version((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s  (RRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR stDistInfoDistributioncB@sJeZdZdZejdZedZedZ dZ RS(sV Wrap an actual or potential sys.path entry w/metadata, .dist-info style. tMETADATAs([\(,])\s*(\d.*?)\s*([,\)])cC@sTy |jSWnBtk rO|j|j}tjjj||_|jSXdS(sParse and cache metadataN(t _pkg_infoRRRtemailtparsertParsertparsestr(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_parsed_pkg_info! s   cC@s6y |jSWn$tk r1|j|_|jSXdS(N(t_DistInfoDistribution__dep_mapRt_compute_dependencies(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR+ s   c@sigd6}|_gx3|jjdp2gD]}jt|q3Wfd}t|d}|dj|xR|jjdpgD]8}t|j}t t|||||R4(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR` s(RRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR_ scc@stt|}x|D]~}d|krA||jd }n|jdr|d j}y|t|7}Wqtk rdSXnt|VqWdS(sYield ``Requirement`` objects for each specification in `strs` `strs` must be a string, or a (possibly-nested) iterable thereof. s #s\iN(RRjRRR#R't StopIterationR^(RRRlR$((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRed s   cB@sMeZdZdZdZdZdZdZedZ RS(cC@sytt|j|Wn+tjjk rG}tt|nX|j|_ t |j}||j |_ |_ g|jD]}|j|jf^q|_ttt|j|_|j |jt|j|jrt|jndf|_t|j|_dS(s>DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!N(tsuperR^RRRtInvalidRequirementRRRt unsafe_nameRfR7R R.t specifierR=RRjRWRRlR RR*R3thashCmpRt_Requirement__hash(Rtrequirement_stringRxR R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR{ s + $cC@st|to|j|jkS(N(RR^R(RRA((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR scC@s ||k S(N((RRA((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR scC@sGt|tr1|j|jkr%tS|j}n|jj|dtS(Nt prereleases(RR]R.RRRtcontainsR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s  cC@s|jS(N(R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR scC@sdt|S(NsRequirement.parse(%r)(R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR scC@st|\}|S(N(Re(RSR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s( RRRRRRRRRnR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR^z s     cC@st|kr|tfS|S(sJ Ensure object appears in the mro even for old-style classes. (tobject(tclasses((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_always_object s  cC@sPttjt|dt|}x"|D]}||kr.||Sq.WdS(s2Return an adapter factory for `ob` from `registry`RN(RtinspecttgetmroRR(tregistryR/R1tt((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s'  cC@s)tjj|}tj|dtdS(s1Ensure that the parent directory of `path` existstexist_okN(RRR}R tmakedirsR(RR}((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRp scC@s^tstdnt|\}}|rZ|rZt| rZt|t|dndS(s/Sandbox-bypassing version of ensure_directory()s*"os.mkdir" not supported on this platform.iN(RRR R RTR(RR}Rk((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRT s  cc@sd}g}xt|D]y}|jdr|jdrs|sI|rW||fVn|dd!j}g}qtd|q|j|qW||fVdS(ssSplit a string or iterable thereof into (section, content) pairs Each ``section`` is a stripped version of the section header ("[section]") and each ``content`` is a list of stripped lines excluding blank lines and comment-only lines. If there are any such lines before the first section header, they're returned in a first ``section`` of ``None``. t[t]iisInvalid section headingN(R3RjRRR#RAR(RStsectiontcontentR$((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRk s  cO@s7tj}ztt_tj||SWd|t_XdS(N(RR tos_openttempfiletmkstemp(R4R told_open((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s   tignoretcategoryRcO@s||||S(N((RR4R]((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt _call_aside s c@s:t|d<|jfdtDdS(s=Set up global resource manager (deliberately not state-saved)t_managerc3@s3|])}|jds|t|fVqdS(RN(RR(R,R(R(s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pys sN(R\RR(R%((Rs:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt _initialize s    cC@stj}tdd||j}|j}|j}|j}|}td|D|ddtg|_ t t |j t jtjtdS(sE Prepare the master working set and make the ``require()`` API available. This function has explicit effects on the global state of pkg_resources. It is intended to be invoked once at the initialization of this module. Invocation by other packages is unsupported and done at their own risk. RRTcs@s!|]}|jdtVqdS(RN(RR(R,R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pys + scS@s|jdtS(NR(RR(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR5/ R6R%N(R[RR!RERLR&RFRWRRRRRR<RRRR(RTRERLRURFR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_initialize_master_working_set s        (Rt __future__RR<RRRRsR1RRRcR_R`tpkgutilR=R=RRt email.parserRRRRKRRRRERtimptpkg_resources.externRtpkg_resources.extern.six.movesRRRRRRR RRRR Rtos.pathR R timportlib.machineryt machineryRRR3R6R RRRt version_infot RuntimeErrorRRRRERTRUtresources_streamRXt resource_dirRNRWRRRMRLRPRORQRR,R-tRuntimeWarningRRRR!R'R)R,R0R1R2t _sget_nonet _sset_noneRDt__all__RUR`RaRRbRcRRRFRrRsRtRuRvRRGR?RR9RR:RRhRiRFRRHRIRJRKRwRxRR[RRRZRRdR\RYRfRgRlRmRnRoR~RRRR|R}RRRRRyRzR{RRVRRRRRRR RR%Rt ImpImporterRR+RR8R5RSRRJRKRqRRRR3RjR;RUtVERBOSEt IGNORECASERR_RuRyR]RRRRRARReRR^RRRpRTRkRtfilterwarningsRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyts                                 +                                    .        d   '            ! !          }2   6      PK@N#]x(0site-packages/pkg_resources/_vendor/pyparsing.pynu[# 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 """) PK@N#]D\M0site-packages/pkg_resources/_vendor/__init__.pyonu[ fc@sdS(N((((sB/usr/lib/python2.7/site-packages/pkg_resources/_vendor/__init__.pyttPK@N#]5B\|\|+site-packages/pkg_resources/_vendor/six.pycnu[ fcA@@sKdZddlmZddlZddlZddlZddlZddlZdZdZ ej ddkZ ej ddkZ ej dd!dakZ e refZefZefZeZeZejZnefZeefZeejfZeZeZejjd r$edcZnVd efd YZ ye!e Wne"k rjedeZn XedgZ[ dZ#dZ$defdYZ%de%fdYZ&dej'fdYZ(de%fdYZ)defdYZ*e*e+Z,de(fdYZ-e)dddde)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-d.d.d/d-e)d0d.d.d-d0e)d1d'd"d2d1e)d3d'e rd4nd5d6e)d7d'd8e)d9d:d;d<e)ddde)d=d=d>e)d?d?d>e)d@d@d>e)d2d'd"d2d1e)dAd!d"dBdAe)dCd!d!dDdCe&d"d'e&dEdFe&dGdHe&dIdJdKe&dLdMdLe&dNdOdPe&dQdRdSe&dTdUdVe&dWdXdYe&dZd[d\e&d]d^d_e&d`dadbe&dcdddee&dfdgdhe&dididje&dkdkdje&dldldje&dmdmdne&dodpe&dqdre&dsdte&dudvdue&dwdxe&dydzd{e&d|d}d~e&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddd~e&ddde&ddde&ddde&de+dde&de+dde&de+de+de&ddde&ddde&dddg>Z.ejdkr;e.e&ddg7Z.nxJe.D]BZ/e0e-e/j1e/e2e/e&rBe,j3e/de/j1qBqBW[/e.e-_.e-e+dZ4e,j3e4dde(fdYZ5e)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)d<dde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)dddgZ6x!e6D]Z/e0e5e/j1e/q0W[/e6e5_.e,j3e5e+dddde(fdYZ7e)ddde)ddde)dddgZ8x!e8D]Z/e0e7e/j1e/qW[/e8e7_.e,j3e7e+dddde(fdYZ9e)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:x!e:D]Z/e0e9e/j1e/q W[/e:e9_.e,j3e9e+dddde(fdYZ;e)ddde)ddde)ddde)dddgZ<x!e<D]Z/e0e;e/j1e/q W[/e<e;_.e,j3e;e+d d d d e(fd YZ=e)dddgZ>x!e>D]Z/e0e=e/j1e/q; W[/e>e=_.e,j3e=e+ddddej'fdYZ?e,j3e?e+dddZ@dZAe r dZBdZCdZDdZEdZFdZGn$dZBdZCdZDd ZEd!ZFd"ZGy eHZIWneJk r= d#ZInXeIZHy eKZKWneJk rj d$ZKnXe r d%ZLejMZNd&ZOeZPn7d'ZLd(ZNd)ZOd*efd+YZPeKZKe#eLd,ejQeBZRejQeCZSejQeDZTejQeEZUejQeFZVejQeGZWe rd-ZXd.ZYd/ZZd0Z[ej\d1Z]ej\d2Z^ej\d3Z_nQd4ZXd5ZYd6ZZd7Z[ej\d8Z]ej\d9Z^ej\d:Z_e#eXd;e#eYd<e#eZd=e#e[d>e rd?Z`d@ZaebZcddldZdedjedAjfZg[dejhdZiejjZkelZmddlnZnenjoZoenjpZpdBZqej d d krdCZrdDZsq4dEZrdFZsnpdGZ`dHZaecZcebZgdIZidJZkejtejuevZmddloZoeojoZoZpdKZqdCZrdDZse#e`dLe#eadMdNZwdOZxdPZye reze4j{dQZ|ddRZ~ndddSZ|e|dTej d dhkre|dUn)ej d dikre|dVn dWZeze4j{dXdZedkrdYZnej d djkrDeZdZZne#e~d[ej dd!dkkrejejd\Zn ejZd]Zd^Zd_ZgZe+Zejd`dk rge_nejr7xOeejD]>\ZZeej+dkrej1e+kreje=PqqW[[nejje,dS(ls6Utilities for writing code that runs on Python 2 and 3i(tabsolute_importNs'Benjamin Peterson s1.10.0iiitjavaiitXcB@seZdZRS(cC@sdS(NiiI((tself((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt__len__>s(t__name__t __module__R(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR<si?cC@s ||_dS(s Add documentation to a function.N(t__doc__(tfunctdoc((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt_add_docKscC@st|tj|S(s7Import module, returning the module after the last dot.(t __import__tsystmodules(tname((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt_import_modulePs t _LazyDescrcB@seZdZdZRS(cC@s ||_dS(N(R(RR((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt__init__XscC@sN|j}t||j|yt|j|jWntk rInX|S(N(t_resolvetsetattrRtdelattrt __class__tAttributeError(Rtobjttptresult((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt__get__[s  (RRRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRVs t MovedModulecB@s&eZddZdZdZRS(cC@sJtt|j|tr=|dkr1|}n||_n ||_dS(N(tsuperRRtPY3tNonetmod(RRtoldtnew((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRis    cC@s t|jS(N(RR(R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRrscC@s/|j}t||}t||||S(N(RtgetattrR(Rtattrt_moduletvalue((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt __getattr__us N(RRRRRR&(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRgs t _LazyModulecB@s eZdZdZgZRS(cC@s)tt|j||jj|_dS(N(RR'RRR(RR((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR~scC@s3ddg}|g|jD]}|j^q7}|S(NRR(t_moved_attributesR(RtattrsR#((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt__dir__s #(RRRR*R((((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR'|s  tMovedAttributecB@s eZdddZdZRS(cC@stt|j|trp|dkr1|}n||_|dkrd|dkr[|}qd|}n||_n'||_|dkr|}n||_dS(N(RR+RRRRR#(RRtold_modtnew_modtold_attrtnew_attr((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRs           cC@st|j}t||jS(N(RRR"R#(Rtmodule((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRsN(RRRRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR+st_SixMetaPathImportercB@s_eZdZdZdZdZd dZdZdZ dZ dZ e Z RS( s 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 cC@s||_i|_dS(N(Rt known_modules(Rtsix_module_name((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRs cG@s-x&|D]}||j|jd|(RR6((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt is_packagescC@s|j|dS(s;Return None Required, if is_package is implementedN(R>R(RR6((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytget_codes N( RRRRR7R8RR:R>RARDREt get_source(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR1s       t _MovedItemscB@seZdZgZRS(sLazy loading of moved objects(RRRRB(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRGst cStringIOtiotStringIOtfiltert itertoolstbuiltinstifiltert filterfalset ifilterfalsetinputt __builtin__t raw_inputtinternR tmaptimaptgetcwdtostgetcwdutgetcwdbtrangetxranget reload_modulet importlibtimptreloadtreducet functoolst shlex_quotetpipestshlextquotetUserDictt collectionstUserListt UserStringtziptizipt zip_longestt izip_longestt configparsert ConfigParsertcopyregtcopy_regtdbm_gnutgdbmsdbm.gnut _dummy_threadt dummy_threadthttp_cookiejart cookielibshttp.cookiejart http_cookiestCookies http.cookiest html_entitiesthtmlentitydefss html.entitiest html_parsert HTMLParsers html.parsert http_clientthttplibs http.clienttemail_mime_multipartsemail.MIMEMultipartsemail.mime.multiparttemail_mime_nonmultipartsemail.MIMENonMultipartsemail.mime.nonmultiparttemail_mime_textsemail.MIMETextsemail.mime.texttemail_mime_basesemail.MIMEBasesemail.mime.basetBaseHTTPServers http.servert CGIHTTPServertSimpleHTTPServertcPickletpickletqueuetQueuetreprlibtreprt socketservert SocketServert_threadtthreadttkintertTkinterttkinter_dialogtDialogstkinter.dialogttkinter_filedialogt FileDialogstkinter.filedialogttkinter_scrolledtextt ScrolledTextstkinter.scrolledtextttkinter_simpledialogt SimpleDialogstkinter.simpledialogt tkinter_tixtTixs tkinter.tixt tkinter_ttktttks tkinter.ttkttkinter_constantst Tkconstantsstkinter.constantst tkinter_dndtTkdnds tkinter.dndttkinter_colorchooserttkColorChooserstkinter.colorchooserttkinter_commondialogttkCommonDialogstkinter.commondialogttkinter_tkfiledialogt tkFileDialogt tkinter_fontttkFonts tkinter.fontttkinter_messageboxt tkMessageBoxstkinter.messageboxttkinter_tksimpledialogttkSimpleDialogt urllib_parses.moves.urllib_parses urllib.parset urllib_errors.moves.urllib_errors urllib.errorturllibs .moves.urllibturllib_robotparsert robotparsersurllib.robotparsert xmlrpc_clientt xmlrpclibs xmlrpc.clientt xmlrpc_servertSimpleXMLRPCServers xmlrpc.servertwin32twinregt_winregsmoves.s.movestmovestModule_six_moves_urllib_parsecB@seZdZRS(s7Lazy loading of moved objects in six.moves.urllib_parse(RRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR@st ParseResultturlparset SplitResulttparse_qst parse_qslt urldefragturljointurlsplitt urlunparset urlunsplitt quote_plustunquotet unquote_plust urlencodet splitquerytsplittagt splitusert uses_fragmentt uses_netloct uses_paramst uses_queryt uses_relativesmoves.urllib_parsesmoves.urllib.parsetModule_six_moves_urllib_errorcB@seZdZRS(s7Lazy loading of moved objects in six.moves.urllib_error(RRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRhstURLErrorturllib2t HTTPErrortContentTooShortErrors.moves.urllib.errorsmoves.urllib_errorsmoves.urllib.errortModule_six_moves_urllib_requestcB@seZdZRS(s9Lazy loading of moved objects in six.moves.urllib_request(RRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR|sturlopensurllib.requesttinstall_openert build_openert pathname2urlt url2pathnamet getproxiestRequesttOpenerDirectortHTTPDefaultErrorHandlertHTTPRedirectHandlertHTTPCookieProcessort ProxyHandlert BaseHandlertHTTPPasswordMgrtHTTPPasswordMgrWithDefaultRealmtAbstractBasicAuthHandlertHTTPBasicAuthHandlertProxyBasicAuthHandlertAbstractDigestAuthHandlertHTTPDigestAuthHandlertProxyDigestAuthHandlert HTTPHandlert HTTPSHandlert FileHandlert FTPHandlertCacheFTPHandlertUnknownHandlertHTTPErrorProcessort urlretrievet urlcleanupt URLopenertFancyURLopenert proxy_bypasss.moves.urllib.requestsmoves.urllib_requestsmoves.urllib.requestt Module_six_moves_urllib_responsecB@seZdZRS(s:Lazy loading of moved objects in six.moves.urllib_response(RRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRstaddbasesurllib.responset addclosehooktaddinfot addinfourls.moves.urllib.responsesmoves.urllib_responsesmoves.urllib.responset#Module_six_moves_urllib_robotparsercB@seZdZRS(s=Lazy loading of moved objects in six.moves.urllib_robotparser(RRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRstRobotFileParsers.moves.urllib.robotparsersmoves.urllib_robotparsersmoves.urllib.robotparsertModule_six_moves_urllibcB@sheZdZgZejdZejdZejdZejdZ ejdZ dZ RS(sICreate a six.moves.urllib namespace that resembles the Python 3 namespacesmoves.urllib_parsesmoves.urllib_errorsmoves.urllib_requestsmoves.urllib_responsesmoves.urllib_robotparsercC@sdddddgS(NtparseterrortrequesttresponseR((R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR*s( RRRRBt _importerR8RRRRRR*(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRss moves.urllibcC@stt|j|dS(sAdd an item to six.moves.N(RRGR(tmove((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytadd_movescC@s^ytt|WnFtk rYytj|=WqZtk rUtd|fqZXnXdS(sRemove item from six.moves.sno such move, %rN(RRGRRt__dict__R;(R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt remove_moves  t__func__t__self__t __closure__t__code__t __defaults__t __globals__tim_functim_selft func_closuret func_codet func_defaultst func_globalscC@s |jS(N(tnext(tit((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytadvance_iterator scC@stdt|jDS(Ncs@s|]}d|jkVqdS(t__call__N(R (t.0tklass((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pys s(tanyttypet__mro__(R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytcallablescC@s|S(N((tunbound((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytget_unbound_functionscC@s|S(N((Rtcls((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytcreate_unbound_methodscC@s|jS(N(R(R"((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR#"scC@stj|||jS(N(ttypest MethodTypeR(RR((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytcreate_bound_method%scC@stj|d|S(N(R&R'R(RR$((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR%(stIteratorcB@seZdZRS(cC@st|j|S(N(Rt__next__(R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR-s(RRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR)+ss3Get the function out of a possibly unbound functioncK@st|j|S(N(titertkeys(tdtkw((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytiterkeys>scK@st|j|S(N(R+tvalues(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt itervaluesAscK@st|j|S(N(R+titems(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt iteritemsDscK@st|j|S(N(R+tlists(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt iterlistsGsR,R0R2cK@s |j|S(N(R/(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR/PscK@s |j|S(N(R1(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR1SscK@s |j|S(N(R3(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR3VscK@s |j|S(N(R5(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR5Ystviewkeyst viewvaluest viewitemss1Return an iterator over the keys of a dictionary.s3Return an iterator over the values of a dictionary.s?Return an iterator over the (key, value) pairs of a dictionary.sBReturn an iterator over the (key, [values]) pairs of a dictionary.cC@s |jdS(Nslatin-1(tencode(ts((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytbkscC@s|S(N((R:((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytunss>BtassertCountEqualtassertRaisesRegexptassertRegexpMatchestassertRaisesRegext assertRegexcC@s|S(N((R:((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR;scC@st|jdddS(Ns\\s\\\\tunicode_escape(tunicodetreplace(R:((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR<scC@st|dS(Ni(tord(tbs((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytbyte2intscC@st||S(N(RE(tbufti((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt indexbytesstassertItemsEquals Byte literals Text literalcO@st|t||S(N(R"t_assertCountEqual(Rtargstkwargs((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR=scO@st|t||S(N(R"t_assertRaisesRegex(RRMRN((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR@scO@st|t||S(N(R"t _assertRegex(RRMRN((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRAstexeccC@sC|dkr|}n|j|k r9|j|n|dS(N(Rt __traceback__twith_traceback(RR%ttb((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytreraises   cB@sc|dkrBejd}|j}|dkr<|j}n~n|dkrW|}nddUdS(sExecute code in a namespace.isexec _code_ in _globs_, _locs_N(RR t _getframet f_globalstf_locals(t_code_t_globs_t_locs_tframe((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytexec_s      s9def reraise(tp, value, tb=None): raise tp, value, tb srdef raise_from(value, from_value): if from_value is None: raise value raise value from from_value sCdef raise_from(value, from_value): raise value from from_value cC@s |dS(N((R%t from_value((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt raise_fromstprintc @s|jdtjdkr%dSfd}t}|jdd}|dk rt|trpt}qt|tst dqn|jdd}|dk rt|trt}qt|tst dqn|rt dn|s0x*|D]}t|tr t}Pq q Wn|rQtd }td }n d }d }|dkrr|}n|dkr|}nx7t |D])\} }| r||n||qW||dS( s4The new-style print function for Python 2.4 and 2.5.tfileNc@st|tst|}nttrt|trjdk rtdd}|dkrrd}n|jj|}nj |dS(Nterrorststrict( R?t basestringtstrRaRCtencodingRR"R9twrite(tdataRb(tfp(s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRgs  tsepssep must be None or a stringtendsend must be None or a strings$invalid keyword arguments to print()s t ( tpopR tstdoutRtFalseR?RCtTrueRet TypeErrort enumerate( RMRNRgt want_unicodeRjRktargtnewlinetspaceRI((Ris=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytprint_sL              cO@sW|jdtj}|jdt}t|||rS|dk rS|jndS(NRatflush(tgetR RnRmRot_printRRx(RMRNRiRx((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRw s  sReraise an exception.c@sfd}|S(Nc@s(tj|}|_|S(N(Rbtwrapst __wrapped__(tf(tassignedtupdatedtwrapped(s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytwrappers ((RR~RR((R~RRs=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR{sc@s5dffdY}tj|ddiS(s%Create a base class with a metaclass.t metaclassc@seZfdZRS(c@s||S(N((R$Rt this_basesR-(tbasestmeta(s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt__new__'s(RRR((RR(s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR%sttemporary_class((RR(RRR((RRs=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytwith_metaclass sc@sfd}|S(s6Class decorator for creating a class with a metaclass.c@s|jj}|jd}|dk rft|trE|g}nx|D]}|j|qLWn|jdd|jdd|j|j|S(Nt __slots__R t __weakref__( R tcopyRyRR?ReRmRt __bases__(R$t orig_varstslotst slots_var(R(s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR.s   ((RR((Rs=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt add_metaclass,s cC@sJtrFd|jkr+td|jn|j|_d|_n|S(s 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. t__str__sY@python_2_unicode_compatible cannot be applied to %s because it doesn't define __str__().cS@s|jjdS(Nsutf-8(t __unicode__R9(R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytJt(tPY2R t ValueErrorRRR(R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytpython_2_unicode_compatible<s t__spec__(iiIiIill(ii(ii(ii(ii(Rt __future__RRbRLtoperatorR R&t __author__t __version__t version_infoRRtPY34Ret string_typestintt integer_typesRt class_typest text_typetbytest binary_typetmaxsizetMAXSIZERdtlongt ClassTypeRCtplatformt startswithtobjectRtlent OverflowErrorR RRRt ModuleTypeR'R+R1RRRGR(R#RRR?R7RRt_urllib_parse_moved_attributesRt_urllib_error_moved_attributesRt _urllib_request_moved_attributesRt!_urllib_response_moved_attributesRt$_urllib_robotparser_moved_attributesRR R t _meth_funct _meth_selft _func_closuret _func_codet_func_defaultst _func_globalsRRt NameErrorR!R#R'R(R%R)t attrgettertget_method_functiontget_method_selftget_function_closuretget_function_codetget_function_defaultstget_function_globalsR/R1R3R5t methodcallerR6R7R8R;R<tchrtunichrtstructtStructtpacktint2bytet itemgetterRGtgetitemRJR+t iterbytesRIRJtBytesIORLRORPtpartialRVRER=R@RAR"RMR]RRUR_RwRztWRAPPER_ASSIGNMENTStWRAPPER_UPDATESR{RRRRBt __package__tglobalsRyRtsubmodule_search_locationst meta_pathRrRItimportertappend(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyts               >                                                                                 5         PK@N#]5B\|\|+site-packages/pkg_resources/_vendor/six.pyonu[ fcA@@sKdZddlmZddlZddlZddlZddlZddlZdZdZ ej ddkZ ej ddkZ ej dd!dakZ e refZefZefZeZeZejZnefZeefZeejfZeZeZejjd r$edcZnVd efd YZ ye!e Wne"k rjedeZn XedgZ[ dZ#dZ$defdYZ%de%fdYZ&dej'fdYZ(de%fdYZ)defdYZ*e*e+Z,de(fdYZ-e)dddde)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-d.d.d/d-e)d0d.d.d-d0e)d1d'd"d2d1e)d3d'e rd4nd5d6e)d7d'd8e)d9d:d;d<e)ddde)d=d=d>e)d?d?d>e)d@d@d>e)d2d'd"d2d1e)dAd!d"dBdAe)dCd!d!dDdCe&d"d'e&dEdFe&dGdHe&dIdJdKe&dLdMdLe&dNdOdPe&dQdRdSe&dTdUdVe&dWdXdYe&dZd[d\e&d]d^d_e&d`dadbe&dcdddee&dfdgdhe&dididje&dkdkdje&dldldje&dmdmdne&dodpe&dqdre&dsdte&dudvdue&dwdxe&dydzd{e&d|d}d~e&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddde&ddd~e&ddde&ddde&ddde&de+dde&de+dde&de+de+de&ddde&ddde&dddg>Z.ejdkr;e.e&ddg7Z.nxJe.D]BZ/e0e-e/j1e/e2e/e&rBe,j3e/de/j1qBqBW[/e.e-_.e-e+dZ4e,j3e4dde(fdYZ5e)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)d<dde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)ddde)dddgZ6x!e6D]Z/e0e5e/j1e/q0W[/e6e5_.e,j3e5e+dddde(fdYZ7e)ddde)ddde)dddgZ8x!e8D]Z/e0e7e/j1e/qW[/e8e7_.e,j3e7e+dddde(fdYZ9e)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:x!e:D]Z/e0e9e/j1e/q W[/e:e9_.e,j3e9e+dddde(fdYZ;e)ddde)ddde)ddde)dddgZ<x!e<D]Z/e0e;e/j1e/q W[/e<e;_.e,j3e;e+d d d d e(fd YZ=e)dddgZ>x!e>D]Z/e0e=e/j1e/q; W[/e>e=_.e,j3e=e+ddddej'fdYZ?e,j3e?e+dddZ@dZAe r dZBdZCdZDdZEdZFdZGn$dZBdZCdZDd ZEd!ZFd"ZGy eHZIWneJk r= d#ZInXeIZHy eKZKWneJk rj d$ZKnXe r d%ZLejMZNd&ZOeZPn7d'ZLd(ZNd)ZOd*efd+YZPeKZKe#eLd,ejQeBZRejQeCZSejQeDZTejQeEZUejQeFZVejQeGZWe rd-ZXd.ZYd/ZZd0Z[ej\d1Z]ej\d2Z^ej\d3Z_nQd4ZXd5ZYd6ZZd7Z[ej\d8Z]ej\d9Z^ej\d:Z_e#eXd;e#eYd<e#eZd=e#e[d>e rd?Z`d@ZaebZcddldZdedjedAjfZg[dejhdZiejjZkelZmddlnZnenjoZoenjpZpdBZqej d d krdCZrdDZsq4dEZrdFZsnpdGZ`dHZaecZcebZgdIZidJZkejtejuevZmddloZoeojoZoZpdKZqdCZrdDZse#e`dLe#eadMdNZwdOZxdPZye reze4j{dQZ|ddRZ~ndddSZ|e|dTej d dhkre|dUn)ej d dikre|dVn dWZeze4j{dXdZedkrdYZnej d djkrDeZdZZne#e~d[ej dd!dkkrejejd\Zn ejZd]Zd^Zd_ZgZe+Zejd`dk rge_nejr7xOeejD]>\ZZeej+dkrej1e+kreje=PqqW[[nejje,dS(ls6Utilities for writing code that runs on Python 2 and 3i(tabsolute_importNs'Benjamin Peterson s1.10.0iiitjavaiitXcB@seZdZRS(cC@sdS(NiiI((tself((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt__len__>s(t__name__t __module__R(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR<si?cC@s ||_dS(s Add documentation to a function.N(t__doc__(tfunctdoc((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt_add_docKscC@st|tj|S(s7Import module, returning the module after the last dot.(t __import__tsystmodules(tname((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt_import_modulePs t _LazyDescrcB@seZdZdZRS(cC@s ||_dS(N(R(RR((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt__init__XscC@sN|j}t||j|yt|j|jWntk rInX|S(N(t_resolvetsetattrRtdelattrt __class__tAttributeError(Rtobjttptresult((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt__get__[s  (RRRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRVs t MovedModulecB@s&eZddZdZdZRS(cC@sJtt|j|tr=|dkr1|}n||_n ||_dS(N(tsuperRRtPY3tNonetmod(RRtoldtnew((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRis    cC@s t|jS(N(RR(R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRrscC@s/|j}t||}t||||S(N(RtgetattrR(Rtattrt_moduletvalue((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt __getattr__us N(RRRRRR&(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRgs t _LazyModulecB@s eZdZdZgZRS(cC@s)tt|j||jj|_dS(N(RR'RRR(RR((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR~scC@s3ddg}|g|jD]}|j^q7}|S(NRR(t_moved_attributesR(RtattrsR#((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt__dir__s #(RRRR*R((((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR'|s  tMovedAttributecB@s eZdddZdZRS(cC@stt|j|trp|dkr1|}n||_|dkrd|dkr[|}qd|}n||_n'||_|dkr|}n||_dS(N(RR+RRRRR#(RRtold_modtnew_modtold_attrtnew_attr((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRs           cC@st|j}t||jS(N(RRR"R#(Rtmodule((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRsN(RRRRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR+st_SixMetaPathImportercB@s_eZdZdZdZdZd dZdZdZ dZ dZ e Z RS( s 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 cC@s||_i|_dS(N(Rt known_modules(Rtsix_module_name((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRs cG@s-x&|D]}||j|jd|(RR6((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt is_packagescC@s|j|dS(s;Return None Required, if is_package is implementedN(R>R(RR6((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytget_codes N( RRRRR7R8RR:R>RARDREt get_source(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR1s       t _MovedItemscB@seZdZgZRS(sLazy loading of moved objects(RRRRB(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRGst cStringIOtiotStringIOtfiltert itertoolstbuiltinstifiltert filterfalset ifilterfalsetinputt __builtin__t raw_inputtinternR tmaptimaptgetcwdtostgetcwdutgetcwdbtrangetxranget reload_modulet importlibtimptreloadtreducet functoolst shlex_quotetpipestshlextquotetUserDictt collectionstUserListt UserStringtziptizipt zip_longestt izip_longestt configparsert ConfigParsertcopyregtcopy_regtdbm_gnutgdbmsdbm.gnut _dummy_threadt dummy_threadthttp_cookiejart cookielibshttp.cookiejart http_cookiestCookies http.cookiest html_entitiesthtmlentitydefss html.entitiest html_parsert HTMLParsers html.parsert http_clientthttplibs http.clienttemail_mime_multipartsemail.MIMEMultipartsemail.mime.multiparttemail_mime_nonmultipartsemail.MIMENonMultipartsemail.mime.nonmultiparttemail_mime_textsemail.MIMETextsemail.mime.texttemail_mime_basesemail.MIMEBasesemail.mime.basetBaseHTTPServers http.servert CGIHTTPServertSimpleHTTPServertcPickletpickletqueuetQueuetreprlibtreprt socketservert SocketServert_threadtthreadttkintertTkinterttkinter_dialogtDialogstkinter.dialogttkinter_filedialogt FileDialogstkinter.filedialogttkinter_scrolledtextt ScrolledTextstkinter.scrolledtextttkinter_simpledialogt SimpleDialogstkinter.simpledialogt tkinter_tixtTixs tkinter.tixt tkinter_ttktttks tkinter.ttkttkinter_constantst Tkconstantsstkinter.constantst tkinter_dndtTkdnds tkinter.dndttkinter_colorchooserttkColorChooserstkinter.colorchooserttkinter_commondialogttkCommonDialogstkinter.commondialogttkinter_tkfiledialogt tkFileDialogt tkinter_fontttkFonts tkinter.fontttkinter_messageboxt tkMessageBoxstkinter.messageboxttkinter_tksimpledialogttkSimpleDialogt urllib_parses.moves.urllib_parses urllib.parset urllib_errors.moves.urllib_errors urllib.errorturllibs .moves.urllibturllib_robotparsert robotparsersurllib.robotparsert xmlrpc_clientt xmlrpclibs xmlrpc.clientt xmlrpc_servertSimpleXMLRPCServers xmlrpc.servertwin32twinregt_winregsmoves.s.movestmovestModule_six_moves_urllib_parsecB@seZdZRS(s7Lazy loading of moved objects in six.moves.urllib_parse(RRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR@st ParseResultturlparset SplitResulttparse_qst parse_qslt urldefragturljointurlsplitt urlunparset urlunsplitt quote_plustunquotet unquote_plust urlencodet splitquerytsplittagt splitusert uses_fragmentt uses_netloct uses_paramst uses_queryt uses_relativesmoves.urllib_parsesmoves.urllib.parsetModule_six_moves_urllib_errorcB@seZdZRS(s7Lazy loading of moved objects in six.moves.urllib_error(RRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRhstURLErrorturllib2t HTTPErrortContentTooShortErrors.moves.urllib.errorsmoves.urllib_errorsmoves.urllib.errortModule_six_moves_urllib_requestcB@seZdZRS(s9Lazy loading of moved objects in six.moves.urllib_request(RRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR|sturlopensurllib.requesttinstall_openert build_openert pathname2urlt url2pathnamet getproxiestRequesttOpenerDirectortHTTPDefaultErrorHandlertHTTPRedirectHandlertHTTPCookieProcessort ProxyHandlert BaseHandlertHTTPPasswordMgrtHTTPPasswordMgrWithDefaultRealmtAbstractBasicAuthHandlertHTTPBasicAuthHandlertProxyBasicAuthHandlertAbstractDigestAuthHandlertHTTPDigestAuthHandlertProxyDigestAuthHandlert HTTPHandlert HTTPSHandlert FileHandlert FTPHandlertCacheFTPHandlertUnknownHandlertHTTPErrorProcessort urlretrievet urlcleanupt URLopenertFancyURLopenert proxy_bypasss.moves.urllib.requestsmoves.urllib_requestsmoves.urllib.requestt Module_six_moves_urllib_responsecB@seZdZRS(s:Lazy loading of moved objects in six.moves.urllib_response(RRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRstaddbasesurllib.responset addclosehooktaddinfot addinfourls.moves.urllib.responsesmoves.urllib_responsesmoves.urllib.responset#Module_six_moves_urllib_robotparsercB@seZdZRS(s=Lazy loading of moved objects in six.moves.urllib_robotparser(RRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRstRobotFileParsers.moves.urllib.robotparsersmoves.urllib_robotparsersmoves.urllib.robotparsertModule_six_moves_urllibcB@sheZdZgZejdZejdZejdZejdZ ejdZ dZ RS(sICreate a six.moves.urllib namespace that resembles the Python 3 namespacesmoves.urllib_parsesmoves.urllib_errorsmoves.urllib_requestsmoves.urllib_responsesmoves.urllib_robotparsercC@sdddddgS(NtparseterrortrequesttresponseR((R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR*s( RRRRBt _importerR8RRRRRR*(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRss moves.urllibcC@stt|j|dS(sAdd an item to six.moves.N(RRGR(tmove((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytadd_movescC@s^ytt|WnFtk rYytj|=WqZtk rUtd|fqZXnXdS(sRemove item from six.moves.sno such move, %rN(RRGRRt__dict__R;(R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt remove_moves  t__func__t__self__t __closure__t__code__t __defaults__t __globals__tim_functim_selft func_closuret func_codet func_defaultst func_globalscC@s |jS(N(tnext(tit((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytadvance_iterator scC@stdt|jDS(Ncs@s|]}d|jkVqdS(t__call__N(R (t.0tklass((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pys s(tanyttypet__mro__(R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytcallablescC@s|S(N((tunbound((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytget_unbound_functionscC@s|S(N((Rtcls((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytcreate_unbound_methodscC@s|jS(N(R(R"((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR#"scC@stj|||jS(N(ttypest MethodTypeR(RR((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytcreate_bound_method%scC@stj|d|S(N(R&R'R(RR$((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR%(stIteratorcB@seZdZRS(cC@st|j|S(N(Rt__next__(R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR-s(RRR(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR)+ss3Get the function out of a possibly unbound functioncK@st|j|S(N(titertkeys(tdtkw((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytiterkeys>scK@st|j|S(N(R+tvalues(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt itervaluesAscK@st|j|S(N(R+titems(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt iteritemsDscK@st|j|S(N(R+tlists(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt iterlistsGsR,R0R2cK@s |j|S(N(R/(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR/PscK@s |j|S(N(R1(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR1SscK@s |j|S(N(R3(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR3VscK@s |j|S(N(R5(R-R.((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR5Ystviewkeyst viewvaluest viewitemss1Return an iterator over the keys of a dictionary.s3Return an iterator over the values of a dictionary.s?Return an iterator over the (key, value) pairs of a dictionary.sBReturn an iterator over the (key, [values]) pairs of a dictionary.cC@s |jdS(Nslatin-1(tencode(ts((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytbkscC@s|S(N((R:((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytunss>BtassertCountEqualtassertRaisesRegexptassertRegexpMatchestassertRaisesRegext assertRegexcC@s|S(N((R:((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR;scC@st|jdddS(Ns\\s\\\\tunicode_escape(tunicodetreplace(R:((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR<scC@st|dS(Ni(tord(tbs((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytbyte2intscC@st||S(N(RE(tbufti((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt indexbytesstassertItemsEquals Byte literals Text literalcO@st|t||S(N(R"t_assertCountEqual(Rtargstkwargs((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR=scO@st|t||S(N(R"t_assertRaisesRegex(RRMRN((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR@scO@st|t||S(N(R"t _assertRegex(RRMRN((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRAstexeccC@sC|dkr|}n|j|k r9|j|n|dS(N(Rt __traceback__twith_traceback(RR%ttb((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytreraises   cB@sc|dkrBejd}|j}|dkr<|j}n~n|dkrW|}nddUdS(sExecute code in a namespace.isexec _code_ in _globs_, _locs_N(RR t _getframet f_globalstf_locals(t_code_t_globs_t_locs_tframe((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytexec_s      s9def reraise(tp, value, tb=None): raise tp, value, tb srdef raise_from(value, from_value): if from_value is None: raise value raise value from from_value sCdef raise_from(value, from_value): raise value from from_value cC@s |dS(N((R%t from_value((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt raise_fromstprintc @s|jdtjdkr%dSfd}t}|jdd}|dk rt|trpt}qt|tst dqn|jdd}|dk rt|trt}qt|tst dqn|rt dn|s0x*|D]}t|tr t}Pq q Wn|rQtd }td }n d }d }|dkrr|}n|dkr|}nx7t |D])\} }| r||n||qW||dS( s4The new-style print function for Python 2.4 and 2.5.tfileNc@st|tst|}nttrt|trjdk rtdd}|dkrrd}n|jj|}nj |dS(Nterrorststrict( R?t basestringtstrRaRCtencodingRR"R9twrite(tdataRb(tfp(s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRgs  tsepssep must be None or a stringtendsend must be None or a strings$invalid keyword arguments to print()s t ( tpopR tstdoutRtFalseR?RCtTrueRet TypeErrort enumerate( RMRNRgt want_unicodeRjRktargtnewlinetspaceRI((Ris=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytprint_sL              cO@sW|jdtj}|jdt}t|||rS|dk rS|jndS(NRatflush(tgetR RnRmRot_printRRx(RMRNRiRx((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyRw s  sReraise an exception.c@sfd}|S(Nc@s(tj|}|_|S(N(Rbtwrapst __wrapped__(tf(tassignedtupdatedtwrapped(s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytwrappers ((RR~RR((R~RRs=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR{sc@s5dffdY}tj|ddiS(s%Create a base class with a metaclass.t metaclassc@seZfdZRS(c@s||S(N((R$Rt this_basesR-(tbasestmeta(s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt__new__'s(RRR((RR(s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR%sttemporary_class((RR(RRR((RRs=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytwith_metaclass sc@sfd}|S(s6Class decorator for creating a class with a metaclass.c@s|jj}|jd}|dk rft|trE|g}nx|D]}|j|qLWn|jdd|jdd|j|j|S(Nt __slots__R t __weakref__( R tcopyRyRR?ReRmRt __bases__(R$t orig_varstslotst slots_var(R(s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyR.s   ((RR((Rs=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyt add_metaclass,s cC@sJtrFd|jkr+td|jn|j|_d|_n|S(s 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. t__str__sY@python_2_unicode_compatible cannot be applied to %s because it doesn't define __str__().cS@s|jjdS(Nsutf-8(t __unicode__R9(R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytJt(tPY2R t ValueErrorRRR(R((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pytpython_2_unicode_compatible<s t__spec__(iiIiIill(ii(ii(ii(ii(Rt __future__RRbRLtoperatorR R&t __author__t __version__t version_infoRRtPY34Ret string_typestintt integer_typesRt class_typest text_typetbytest binary_typetmaxsizetMAXSIZERdtlongt ClassTypeRCtplatformt startswithtobjectRtlent OverflowErrorR RRRt ModuleTypeR'R+R1RRRGR(R#RRR?R7RRt_urllib_parse_moved_attributesRt_urllib_error_moved_attributesRt _urllib_request_moved_attributesRt!_urllib_response_moved_attributesRt$_urllib_robotparser_moved_attributesRR R t _meth_funct _meth_selft _func_closuret _func_codet_func_defaultst _func_globalsRRt NameErrorR!R#R'R(R%R)t attrgettertget_method_functiontget_method_selftget_function_closuretget_function_codetget_function_defaultstget_function_globalsR/R1R3R5t methodcallerR6R7R8R;R<tchrtunichrtstructtStructtpacktint2bytet itemgetterRGtgetitemRJR+t iterbytesRIRJtBytesIORLRORPtpartialRVRER=R@RAR"RMR]RRUR_RwRztWRAPPER_ASSIGNMENTStWRAPPER_UPDATESR{RRRRBt __package__tglobalsRyRtsubmodule_search_locationst meta_pathRrRItimportertappend(((s=/usr/lib/python2.7/site-packages/pkg_resources/_vendor/six.pyts               >                                                                                 5         PK@N#]] dQdQ/site-packages/pkg_resources/_vendor/appdirs.pycnu[ fc@s@dZd,ZdjeeeZddlZddlZejddkZ e r^eZ nej j drddl Z e j ddZej d rd Zqej d rd Zqd Zn ej ZdddedZdddedZdddedZdddedZdddedZdddedZdefdYZdZdZdZdZed kr!yddlZ eZ!Wq!e"k ryddl#m$Z$eZ!Wqe"k ryddl%Z&eZ!Wqe"k reZ!qXqXq!Xne'dkr<dZ(dZ)d-Z*d$GHee(e)d%d&Z+x&e*D]Z,d'e,e-e+e,fGHq`Wd(GHee(e)Z+x&e*D]Z,d'e,e-e+e,fGHqWd)GHee(Z+x&e*D]Z,d'e,e-e+e,fGHqWd*GHee(d+eZ+x)e*D]Z,d'e,e-e+e,fGHqWndS(.syUtilities for determining application-specific dirs. See for details and usage. iiit.iNitjavatWindowstwin32tMactdarwintlinux2cCs6tdkr|dkr!|}n|r-dp0d}tjjt|}|r|tk rxtjj|||}qtjj||}qn{tdkrtjjd}|rtjj||}qn<tj dtjjd}|rtjj||}n|r2|r2tjj||}n|S( sJReturn 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/". Rt CSIDL_APPDATAtCSIDL_LOCAL_APPDATARs~/Library/Application Support/t XDG_DATA_HOMEs~/.local/shareN( tsystemtNonetostpathtnormpatht_get_win_foldertFalsetjoint expandusertgetenv(tappnamet appauthortversiontroamingtconstR ((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt user_data_dir-s&      cCstdkr|d kr!|}ntjjtd}|r|tk rftjj|||}q~tjj||}qntdkrtjjd}|rtjj||}qntj dtj jddg}g|j tj D]$}tjj|j tj ^q}|rs|rEtjj||}ng|D]}tj j||g^qL}n|rtj j|}n |d}|S|r|rtjj||}n|S( siReturn 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. RtCSIDL_COMMON_APPDATARs/Library/Application Supportt XDG_DATA_DIRSs/usr/local/shares /usr/shareiN(R R R R RRRRRRtpathseptsplittrstriptsep(RRRt multipathR txtpathlist((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt site_data_dirds4      =.  cCstdkr$t||d|}n<tjdtjjd}|r`tjj||}n|r|rtjj||}n|S(sReturn 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/". RRtXDG_CONFIG_HOMEs ~/.config(RRN(R RR R RR RR(RRRRR ((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pytuser_config_dirs  cCs tdkrBt||}|r|rtjj||}qntjdd}g|jtjD]$}tjj|j tj ^qg}|r|rtjj||}ng|D]}tj j||g^q}n|rtjj|}n |d}|S(sReturn 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. RRtXDG_CONFIG_DIRSs/etc/xdgi(RR( R R#R R RRRRRRR(RRRR R R!R"((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pytsite_config_dirs  =. cCsBtdkr|dkr!|}ntjjtd}|r|tk rftjj|||}ntjj||}|rtjj|d}qqn{tdkrtjjd}|rtjj||}qn<tj dtjjd}|rtjj||}n|r>|r>tjj||}n|S( sReturn 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. RRtCacheRs~/Library/CachestXDG_CACHE_HOMEs~/.cacheN( R R R R RRRRRR(RRRtopinionR ((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pytuser_cache_dirs(!      cCstdkr0tjjtjjd|}n{tdkrut|||}t}|rtjj|d}qn6t|||}t}|rtjj|d}n|r|rtjj||}n|S(sReturn 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. Rs~/Library/LogsRtLogstlog(R R R RRRRR+(RRRR*R ((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt user_log_dir:s     tAppDirscBs}eZdZddeedZedZedZedZ edZ edZ edZ RS( s1Convenience wrapper for getting application dirs.cCs1||_||_||_||_||_dS(N(RRRRR (tselfRRRRR ((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt__init__os     cCs%t|j|jd|jd|jS(NRR(RRRRR(R0((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyRwscCs%t|j|jd|jd|jS(NRR (R#RRRR (R0((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyR#|scCs%t|j|jd|jd|jS(NRR(R%RRRR(R0((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyR%scCs%t|j|jd|jd|jS(NRR (R'RRRR (R0((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyR'scCst|j|jd|jS(NR(R+RRR(R0((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyR+scCst|j|jd|jS(NR(R.RRR(R0((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyR.sN( t__name__t __module__t__doc__R RR1tpropertyRR#R%R'R+R.(((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyR/ms  cCs\ddl}idd6dd6dd6|}|j|jd }|j||\}}|S( sThis 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. iNtAppDataRsCommon AppDataRs Local AppDataRs@Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders(t_winregtOpenKeytHKEY_CURRENT_USERt QueryValueEx(t csidl_nameR7tshell_folder_nametkeytdirttype((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt_get_win_folder_from_registrys  cCsddlm}m}|jdt||dd}yt|}t}x*|D]"}t|dkrSt}PqSqSW|ryddl }|j |}Wqt k rqXnWnt k rnX|S(Ni(tshellcontshellii( twin32com.shellRARBtSHGetFolderPathtgetattrtunicodeRtordtTruetwin32apitGetShortPathNamet ImportErrort UnicodeError(R;RARBR>t has_high_chartcRI((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt_get_win_folder_with_pywin32s$!      cCsddl}idd6dd6dd6|}|jd}|jjjd|dd |t}x*|D]"}t|d krft}PqfqfW|r|jd}|jj j |j |dr|}qn|j S( NiiRi#RiRiii( tctypestcreate_unicode_buffertwindlltshell32tSHGetFolderPathWR RRGRHtkernel32tGetShortPathNameWtvalue(R;RPt csidl_consttbufRMRNtbuf2((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt_get_win_folder_with_ctypess$   c Cs=ddl}ddlm}ddlm}|jjd}|jd|}|jj }|j dt |j |d|j j||jj|jjd}t}x*|D]"} t| dkrt}PqqW|r9|jd|}|jj } tj|||r9|jj|jjd}q9n|S(Ni(tjna(RiRNsi(tarraytcom.sunR\tcom.sun.jna.platformRtWinDeftMAX_PATHtzerostShell32tINSTANCERDR REtShlObjtSHGFP_TYPE_CURRENTtNativettoStringttostringRRRGRHtKernel32tkernalRJ( R;R]R\Rtbuf_sizeRYRBR>RMRNtkernel((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt_get_win_folder_with_jnas&  +!  '(RRt__main__tMyAppt MyCompanyRR#R%R'R+R.s%-- app dirs (with optional 'version')Rs1.0s%s: %ss) -- app dirs (without optional 'version')s+ -- app dirs (without optional 'appauthor')s( -- app dirs (with disabled 'appauthor')R(iii(RR#R%R'R+R.(.R4t__version_info__Rtmaptstrt __version__tsysR t version_infotPY3RFtplatformt startswithtjava_vertos_nameR R RRR#R%R'RHR+R.tobjectR/R@ROR[RnRCtwin32comRRKRPRRt com.sun.jnatcomR2RRtpropstdirstpropRE(((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt s~        7B(393+                   PK@N#]b:cXX7site-packages/pkg_resources/_vendor/packaging/utils.pyonu[ fc@`sDddlmZmZmZddlZejdZdZdS(i(tabsolute_importtdivisiontprint_functionNs[-_.]+cC`stjd|jS(Nt-(t_canonicalize_regextsubtlower(tname((sI/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/utils.pytcanonicalize_name s(t __future__RRRtretcompileRR(((sI/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/utils.pyts PK@N#]'6site-packages/pkg_resources/_vendor/packaging/utils.pynu[# 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() PK@N#]1;site-packages/pkg_resources/_vendor/packaging/__about__.pycnu[ fc@`srddlmZmZmZdddddddd gZd Zd Zd Zd ZdZ dZ dZ de Z dS(i(tabsolute_importtdivisiontprint_functiont __title__t __summary__t__uri__t __version__t __author__t __email__t __license__t __copyright__t packagings"Core utilities for Python packagess!https://github.com/pypa/packagings16.8s)Donald Stufft and individual contributorssdonald@stufft.ios"BSD or Apache License, Version 2.0sCopyright 2014-2016 %sN( t __future__RRRt__all__RRRRRRR R (((sM/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/__about__.pytsPK@N#]Sff:site-packages/pkg_resources/_vendor/packaging/__init__.pyonu[ fc@`sxddlmZmZmZddlmZmZmZmZm Z m Z m Z m Z dddddd d d gZ d S( i(tabsolute_importtdivisiontprint_functioni(t __author__t __copyright__t __email__t __license__t __summary__t __title__t__uri__t __version__RRR R RRRRN(t __future__RRRt __about__RRRRRRR R t__all__(((sL/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/__init__.pyts:PK@N#]889site-packages/pkg_resources/_vendor/packaging/version.pycnu[ fc@`snddlmZmZmZddlZddlZddlZddlmZddddd gZ ej d d d d dddgZ dZ de fdYZdefdYZdefdYZejdejZidd6dd6dd6dd6dd 6ZdZdZdZdefd YZd!Zejd"Zd#Zd$ZdS(%i(tabsolute_importtdivisiontprint_functionNi(tInfinitytparsetVersiont LegacyVersiontInvalidVersiontVERSION_PATTERNt_VersiontepochtreleasetdevtpretposttlocalcC`s-yt|SWntk r(t|SXdS(s 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(RRR(tversion((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyRs cB`seZdZRS(sF An invalid version was found, users should refer to PEP 440. (t__name__t __module__t__doc__(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR$st _BaseVersioncB`sPeZdZdZdZdZdZdZdZdZ RS(cC`s t|jS(N(thasht_key(tself((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__hash__,scC`s|j|dS(NcS`s ||kS(N((tsto((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt0t(t_compare(Rtother((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__lt__/scC`s|j|dS(NcS`s ||kS(N((RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR3R(R(RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__le__2scC`s|j|dS(NcS`s ||kS(N((RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR6R(R(RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__eq__5scC`s|j|dS(NcS`s ||kS(N((RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR9R(R(RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__ge__8scC`s|j|dS(NcS`s ||kS(N((RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR<R(R(RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__gt__;scC`s|j|dS(NcS`s ||kS(N((RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR?R(R(RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__ne__>scC`s&t|tstS||j|jS(N(t isinstanceRtNotImplementedR(RRtmethod((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyRAs( RRRRR R!R"R#R$R(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR*s       cB`sneZdZdZdZedZedZedZedZ edZ RS(cC`s%t||_t|j|_dS(N(tstrt_versiont_legacy_cmpkeyR(RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__init__JscC`s|jS(N(R)(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__str__NscC`sdjtt|S(Ns(tformattreprR((R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__repr__QscC`s|jS(N(R)(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pytpublicTscC`s|jS(N(R)(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt base_versionXscC`sdS(N(tNone(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR\scC`stS(N(tFalse(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt is_prerelease`scC`stS(N(R3(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pytis_postreleaseds( RRR+R,R/tpropertyR0R1RR4R5(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyRHs   s(\d+ | [a-z]+ | \.| -)tctpreviewsfinal-t-trct@cc`sxxltj|D][}tj||}| s|dkrAqn|d dkrb|jdVqd|VqWdVdS(Nt.it 0123456789it*s*final(t_legacy_version_component_retsplitt_legacy_version_replacement_maptgettzfill(Rtpart((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt_parse_version_partsrs cC`sd}g}xt|jD]}|jdr|dkrjx'|rf|ddkrf|jqCWnx'|r|ddkr|jqmWn|j|qWt|}||fS(NiR>s*finals*final-t00000000(REtlowert startswithtpoptappendttuple(RR tpartsRD((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR*s  s 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
cB`seZejdedejejBZdZdZ	dZ
edZedZ
edZedZed	ZRS(
s^\s*s\s*$cC`s[|jj|}|s0tdj|ntd|jdrZt|jdnddtd|jdjdDdt	|jd|jd	d
t	|jd|jdp|jd
dt	|jd|jddt
|jd|_t|jj
|jj|jj|jj|jj|jj|_dS(NsInvalid version: '{0}'R
iRcs`s|]}t|VqdS(N(tint(t.0ti((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	sR<R
tpre_ltpre_nRtpost_ltpost_n1tpost_n2Rtdev_ltdev_nR(t_regextsearchRR-R	tgroupRMRKR@t_parse_letter_versiont_parse_local_versionR)t_cmpkeyR
RR
RRRR(RRtmatch((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR+s.*(!					cC`sdjtt|S(Ns(R-R.R((R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR/scC`sSg}|jjdkr7|jdj|jjn|jdjd|jjD|jjdk	r|jdjd|jjDn|jjdk	r|jdj|jjdn|jj	dk	r|jd	j|jj	dn|jj
dk	rF|jd
jdjd|jj
Dndj|S(Nis{0}!R<cs`s|]}t|VqdS(N(R((RNtx((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	sRcs`s|]}t|VqdS(N(R((RNR^((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	ss.post{0}is.dev{0}s+{0}cs`s|]}t|VqdS(N(R((RNR^((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	s(R)R
RJR-tjoinRR
R2RRR(RRL((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR,s&)##,cC`st|jdddS(Nt+ii(R(R@(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR0
scC`sjg}|jjdkr7|jdj|jjn|jdjd|jjDdj|S(Nis{0}!R<cs`s|]}t|VqdS(N(R((RNR^((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	sR(R)R
RJR-R_R(RRL((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR1s
&cC`s0t|}d|kr,|jdddSdS(NR`i(R(R@(Rtversion_string((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyRscC`st|jjp|jjS(N(tboolR)RR
(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR4!scC`st|jjS(N(RbR)R(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR5%s(RRtretcompileRtVERBOSEt
IGNORECASERWR+R/R,R6R0R1RR4R5(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyRs	#		
cC`s|r|dkrd}n|j}|dkr<d}n?|dkrQd}n*|d
krfd	}n|dkr{d}n|t|fS|r|rd}|t|fSdS(NitalphatatbetatbR7R
R8R:trevtrR(R7R
R8(RkRl(R2RGRM(tlettertnumber((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyRZ*s 					
s[\._-]cC`s-|dk	r)tdtj|DSdS(sR
    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
    cs`s3|])}|js!|jn	t|VqdS(N(tisdigitRGRM(RNRD((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	RsN(R2RKt_local_version_seperatorsR@(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR[LscC`sttttjdt|}|dkr[|dkr[|dk	r[t}n|dkrpt}n|dkrt}n|dkrt}n|dkrt}ntd|D}||||||fS(NcS`s
|dkS(Ni((R^((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR`Rcs`s7|]-}t|tr$|dfn
t|fVqdS(RN(R%RMR(RNRO((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	s(RKtreversedtlistt	itertoolst	dropwhileR2R(R
RR
RRR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR\Ws&	$
	
	
	
(t
__future__RRRtcollectionsRsRct_structuresRt__all__t
namedtupleR	Rt
ValueErrorRtobjectRRRdReR?RARER*RRRZRpR[R\(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyts0	!&		9k		PK@N#]889site-packages/pkg_resources/_vendor/packaging/version.pyonu[
fc@`snddlmZmZmZddlZddlZddlZddlmZddddd	gZ	ej
d
ddd
dddgZdZde
fdYZdefdYZdefdYZejdejZidd6dd6dd6dd6dd
6ZdZdZdZdefd YZd!Zejd"Zd#Zd$ZdS(%i(tabsolute_importtdivisiontprint_functionNi(tInfinitytparsetVersiont
LegacyVersiontInvalidVersiontVERSION_PATTERNt_VersiontepochtreleasetdevtpretposttlocalcC`s-yt|SWntk
r(t|SXdS(s
    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(RRR(tversion((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyRs
cB`seZdZRS(sF
    An invalid version was found, users should refer to PEP 440.
    (t__name__t
__module__t__doc__(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR$st_BaseVersioncB`sPeZdZdZdZdZdZdZdZdZ	RS(cC`s
t|jS(N(thasht_key(tself((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__hash__,scC`s|j|dS(NcS`s
||kS(N((tsto((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt0t(t_compare(Rtother((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__lt__/scC`s|j|dS(NcS`s
||kS(N((RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR3R(R(RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__le__2scC`s|j|dS(NcS`s
||kS(N((RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR6R(R(RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__eq__5scC`s|j|dS(NcS`s
||kS(N((RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR9R(R(RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__ge__8scC`s|j|dS(NcS`s
||kS(N((RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR<R(R(RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__gt__;scC`s|j|dS(NcS`s
||kS(N((RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR?R(R(RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__ne__>scC`s&t|tstS||j|jS(N(t
isinstanceRtNotImplementedR(RRtmethod((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyRAs(
RRRRR R!R"R#R$R(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR*s							cB`sneZdZdZdZedZedZedZedZ	edZ
RS(cC`s%t||_t|j|_dS(N(tstrt_versiont_legacy_cmpkeyR(RR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__init__JscC`s|jS(N(R)(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__str__NscC`sdjtt|S(Ns(tformattreprR((R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt__repr__QscC`s|jS(N(R)(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pytpublicTscC`s|jS(N(R)(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pytbase_versionXscC`sdS(N(tNone(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR\scC`stS(N(tFalse(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt
is_prerelease`scC`stS(N(R3(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pytis_postreleaseds(RRR+R,R/tpropertyR0R1RR4R5(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyRHs			s(\d+ | [a-z]+ | \.| -)tctpreviewsfinal-t-trct@cc`sxxltj|D][}tj||}|s|dkrAqn|d dkrb|jdVqd|VqWdVdS(Nt.it
0123456789it*s*final(t_legacy_version_component_retsplitt_legacy_version_replacement_maptgettzfill(Rtpart((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyt_parse_version_partsrs
cC`sd}g}xt|jD]}|jdr|dkrjx'|rf|ddkrf|jqCWnx'|r|ddkr|jqmWn|j|qWt|}||fS(NiR>s*finals*final-t00000000(REtlowert
startswithtpoptappendttuple(RR
tpartsRD((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR*ss
    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
cB`seZejdedejejBZdZdZ	dZ
edZedZ
edZedZed	ZRS(
s^\s*s\s*$cC`s[|jj|}|s0tdj|ntd|jdrZt|jdnddtd|jdjdDdt	|jd|jd	d
t	|jd|jdp|jd
dt	|jd|jddt
|jd|_t|jj
|jj|jj|jj|jj|jj|_dS(NsInvalid version: '{0}'R
iRcs`s|]}t|VqdS(N(tint(t.0ti((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	sR<R
tpre_ltpre_nRtpost_ltpost_n1tpost_n2Rtdev_ltdev_nR(t_regextsearchRR-R	tgroupRMRKR@t_parse_letter_versiont_parse_local_versionR)t_cmpkeyR
RR
RRRR(RRtmatch((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR+s.*(!					cC`sdjtt|S(Ns(R-R.R((R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR/scC`sSg}|jjdkr7|jdj|jjn|jdjd|jjD|jjdk	r|jdjd|jjDn|jjdk	r|jdj|jjdn|jj	dk	r|jd	j|jj	dn|jj
dk	rF|jd
jdjd|jj
Dndj|S(Nis{0}!R<cs`s|]}t|VqdS(N(R((RNtx((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	sRcs`s|]}t|VqdS(N(R((RNR^((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	ss.post{0}is.dev{0}s+{0}cs`s|]}t|VqdS(N(R((RNR^((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	s(R)R
RJR-tjoinRR
R2RRR(RRL((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR,s&)##,cC`st|jdddS(Nt+ii(R(R@(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR0
scC`sjg}|jjdkr7|jdj|jjn|jdjd|jjDdj|S(Nis{0}!R<cs`s|]}t|VqdS(N(R((RNR^((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	sR(R)R
RJR-R_R(RRL((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR1s
&cC`s0t|}d|kr,|jdddSdS(NR`i(R(R@(Rtversion_string((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyRscC`st|jjp|jjS(N(tboolR)RR
(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR4!scC`st|jjS(N(RbR)R(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR5%s(RRtretcompileRtVERBOSEt
IGNORECASERWR+R/R,R6R0R1RR4R5(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyRs	#		
cC`s|r|dkrd}n|j}|dkr<d}n?|dkrQd}n*|d
krfd	}n|dkr{d}n|t|fS|r|rd}|t|fSdS(NitalphatatbetatbR7R
R8R:trevtrR(R7R
R8(RkRl(R2RGRM(tlettertnumber((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyRZ*s 					
s[\._-]cC`s-|dk	r)tdtj|DSdS(sR
    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
    cs`s3|])}|js!|jn	t|VqdS(N(tisdigitRGRM(RNRD((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	RsN(R2RKt_local_version_seperatorsR@(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR[LscC`sttttjdt|}|dkr[|dkr[|dk	r[t}n|dkrpt}n|dkrt}n|dkrt}n|dkrt}ntd|D}||||||fS(NcS`s
|dkS(Ni((R^((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR`Rcs`s7|]-}t|tr$|dfn
t|fVqdS(RN(R%RMR(RNRO((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pys	s(RKtreversedtlistt	itertoolst	dropwhileR2R(R
RR
RRR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyR\Ws&	$
	
	
	
(t
__future__RRRtcollectionsRsRct_structuresRt__all__t
namedtupleR	Rt
ValueErrorRtobjectRRRdReR?RARER*RRRZRpR[R\(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/version.pyts0	!&		9k		PK@N#]<)X:site-packages/pkg_resources/_vendor/packaging/__about__.pynu[# 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__
PK@N#]@Fk9site-packages/pkg_resources/_vendor/packaging/_compat.pycnu[
fc@`svddlmZmZmZddlZejddkZejddkZer`efZ	n	e
fZ	dZdS(i(tabsolute_importtdivisiontprint_functionNiic`s5dffdY}tj|ddiS(s/
    Create a base class with a metaclass.
    t	metaclassc`seZfdZRS(c`s||S(N((tclstnamet
this_basestd(tbasestmeta(sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_compat.pyt__new__s(t__name__t
__module__R
((RR	(sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_compat.pyRsttemporary_class((ttypeR
(R	RR((RR	sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_compat.pytwith_metaclasss(t
__future__RRRtsystversion_infotPY2tPY3tstrtstring_typest
basestringR(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_compat.pyts	PK@N#]ơ$-$-8site-packages/pkg_resources/_vendor/packaging/version.pynu[# 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
PK@N#]iJ\\8site-packages/pkg_resources/_vendor/packaging/_compat.pynu[# 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', (), {})
PK@N#]@Fk9site-packages/pkg_resources/_vendor/packaging/_compat.pyonu[
fc@`svddlmZmZmZddlZejddkZejddkZer`efZ	n	e
fZ	dZdS(i(tabsolute_importtdivisiontprint_functionNiic`s5dffdY}tj|ddiS(s/
    Create a base class with a metaclass.
    t	metaclassc`seZfdZRS(c`s||S(N((tclstnamet
this_basestd(tbasestmeta(sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_compat.pyt__new__s(t__name__t
__module__R
((RR	(sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_compat.pyRsttemporary_class((ttypeR
(R	RR((RR	sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_compat.pytwith_metaclasss(t
__future__RRRtsystversion_infotPY2tPY3tstrtstring_typest
basestringR(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_compat.pyts	PK@N#]h =site-packages/pkg_resources/_vendor/packaging/_structures.pyonu[
fc@`s^ddlmZmZmZdefdYZeZdefdYZeZdS(i(tabsolute_importtdivisiontprint_functiontInfinitycB`sYeZdZdZdZdZdZdZdZdZ	dZ
RS(	cC`sdS(NR((tself((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__repr__	scC`stt|S(N(thashtrepr(R((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__hash__scC`stS(N(tFalse(Rtother((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__lt__scC`stS(N(R	(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__le__scC`st||jS(N(t
isinstancet	__class__(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__eq__scC`st||jS(N(R
R(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__ne__scC`stS(N(tTrue(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__gt__scC`stS(N(R(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__ge__scC`stS(N(tNegativeInfinity(R((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__neg__!s(t__name__t
__module__RRRRRRRRR(((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyRs								RcB`sYeZdZdZdZdZdZdZdZdZ	dZ
RS(	cC`sdS(Ns	-Infinity((R((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR)scC`stt|S(N(RR(R((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR,scC`stS(N(R(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR/scC`stS(N(R(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR2scC`st||jS(N(R
R(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR5scC`st||jS(N(R
R(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR8scC`stS(N(R	(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR;scC`stS(N(R	(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR>scC`stS(N(R(R((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyRAs(RRRRRRRRRRR(((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR's								N(t
__future__RRRtobjectRR(((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyts	PK@N#][9cc<site-packages/pkg_resources/_vendor/packaging/specifiers.pyonu[
fc@`s<ddlmZmZmZddlZddlZddlZddlZddlm	Z	m
Z
ddlmZm
Z
mZdefdYZde
ejefd	YZd
efdYZdefd
YZdZdefdYZejdZdZdZdefdYZdS(i(tabsolute_importtdivisiontprint_functionNi(tstring_typestwith_metaclass(tVersiont
LegacyVersiontparsetInvalidSpecifiercB`seZdZRS(sH
    An invalid specifier was found, users should refer to PEP 440.
    (t__name__t
__module__t__doc__(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRst
BaseSpecifiercB`seZejdZejdZejdZejdZejdZ	e	j
dZ	ejddZejddZ
RS(	cC`sdS(s
        Returns the str representation of this Specifier like object. This
        should be representative of the Specifier itself.
        N((tself((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__str__tcC`sdS(sF
        Returns a hash value for this Specifier like object.
        N((R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__hash__RcC`sdS(sq
        Returns a boolean representing whether or not the two Specifier like
        objects are equal.
        N((R
tother((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__eq__$RcC`sdS(su
        Returns a boolean representing whether or not the two Specifier like
        objects are not equal.
        N((R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__ne__+RcC`sdS(sg
        Returns whether or not pre-releases as a whole are allowed by this
        specifier.
        N((R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pytprereleases2RcC`sdS(sd
        Sets whether or not pre-releases as a whole are allowed by this
        specifier.
        N((R
tvalue((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR9RcC`sdS(sR
        Determines if the given item is contained within this specifier.
        N((R
titemR((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pytcontains@RcC`sdS(s
        Takes an iterable of items and filters them so that only items which
        are contained within this specifier are allowed in it.
        N((R
titerableR((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pytfilterFRN(R	R
tabctabstractmethodRRRRtabstractpropertyRtsettertNoneRR(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRst_IndividualSpecifiercB`seZiZdddZdZdZdZdZdZ	dZ
dZed	Z
ed
ZedZejdZd
ZddZddZRS(RcC`sj|jj|}|s0tdj|n|jdj|jdjf|_||_dS(NsInvalid specifier: '{0}'toperatortversion(t_regextsearchRtformattgrouptstript_spect_prereleases(R
tspecRtmatch((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__init__RscC`sF|jdk	r!dj|jnd}dj|jjt||S(Ns, prereleases={0!r}Rs<{0}({1!r}{2})>(R(RR$Rt	__class__R	tstr(R
tpre((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__repr___s!		cC`sdj|jS(Ns{0}{1}(R$R'(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRlscC`s
t|jS(N(thashR'(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRoscC`s`t|tr:y|j|}WqPtk
r6tSXnt||jsPtS|j|jkS(N(t
isinstanceRR,RtNotImplementedR'(R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRrs
cC`s`t|tr:y|j|}WqPtk
r6tSXnt||jsPtS|j|jkS(N(R1RR,RR2R'(R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR}s
cC`st|dj|j|S(Ns_compare_{0}(tgetattrR$t
_operators(R
top((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt
_get_operatorscC`s(t|ttfs$t|}n|S(N(R1RRR(R
R!((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_coerce_versionscC`s|jdS(Ni(R'(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR scC`s|jdS(Ni(R'(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR!scC`s|jS(N(R((R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscC`s
||_dS(N(R((R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscC`s
|j|S(N(R(R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__contains__scC`sW|dkr|j}n|j|}|jr;|r;tS|j|j||jS(N(RRR7t
is_prereleasetFalseR6R R!(R
RR((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscc`st}g}i|dk	r!|ntd6}xf|D]^}|j|}|j||r2|jr|pn|jr|j|qt}|Vq2q2W|r|rx|D]}|VqWndS(NR(R:RtTrueR7RR9Rtappend(R
RRtyieldedtfound_prereleasestkwR!tparsed_version((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRs
	

N(R	R
R4RR+R/RRRRR6R7tpropertyR R!RRR8RR(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRNs 
	
							tLegacySpecifiercB`seZdZejdedejejBZidd6dd6dd6d	d
6dd6d
d6ZdZ	dZ
dZdZdZ
dZdZRS(s
        (?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.
        )
        s^\s*s\s*$tequals==t	not_equals!=tless_than_equals<=tgreater_than_equals>=t	less_thantcC`s(t|ts$tt|}n|S(N(R1RR-(R
R!((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR7scC`s||j|kS(N(R7(R
tprospectiveR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_equalscC`s||j|kS(N(R7(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_not_equalscC`s||j|kS(N(R7(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_less_than_equalscC`s||j|kS(N(R7(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_greater_than_equalscC`s||j|kS(N(R7(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_less_thanscC`s||j|kS(N(R7(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_greater_thans(R	R
t
_regex_strtretcompiletVERBOSEt
IGNORECASER"R4R7RLRMRNRORPRQ(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRBs"

						c`s"tjfd}|S(Nc`s#t|tstS|||S(N(R1RR:(R
RKR)(tfn(sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pytwrappeds(t	functoolstwraps(RWRX((RWsN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_require_version_compare
st	SpecifiercB`seZdZejdedejejBZidd6dd6dd6d	d
6dd6d
d6dd6dd6Ze	dZ
e	dZe	dZe	dZ
e	dZe	dZe	dZdZedZejdZRS(s
        (?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.
                (?=RGRHRIRJt	arbitrarys===cC`sfdjttjdt|d }|d7}|jd||oe|jd||S(Nt.cS`s|jdo|jdS(Ntposttdev(t
startswith(tx((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pytsis.*s>=s==(tjointlistt	itertoolst	takewhilet_version_splitR6(R
RKR)tprefix((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_compatibles

cC`s|jdrht|j}t|d }tt|}|t| }t||\}}n't|}|jst|j}n||kS(Ns.*i(tendswithRtpublicRiR-tlent_pad_versiontlocal(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRLs	cC`s|j||S(N(RL(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRMscC`s|t|kS(N(R(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRNscC`s|t|kS(N(R(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyROscC`sXt|}||kstS|jrT|jrTt|jt|jkrTtSntS(N(RR:R9tbase_versionR;(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRPscC`st|}||kstS|jrT|jrTt|jt|jkrTtSn|jdk	rt|jt|jkrtSntS(N(RR:tis_postreleaseRqRpRR;(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRQscC`s"t|jt|jkS(N(R-tlower(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_arbitraryscC`ss|jdk	r|jS|j\}}|dkro|dkrY|jdrY|d }nt|jrotSntS(	Ns==s>=s<=s~=s===s.*i(s==s>=s<=s~=s===(R(RR'RlRR9R;R:(R
R R!((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRs
cC`s
||_dS(N(R((R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRs(R	R
RRRSRTRURVR"R4R[RkRLRMRNRORPRQRtRARR(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR\s,^
#	s^([0-9]+)((?:a|b|c|rc)[0-9]+)$cC`s\g}xO|jdD]>}tj|}|rG|j|jq|j|qW|S(NR_(tsplitt
_prefix_regexR#textendtgroupsR<(R!tresultRR*((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRi'sc	C`sgg}}|jttjd||jttjd||j|t|d|j|t|d|jddgtdt|dt|d|jddgtdt|dt|dttj|ttj|fS(NcS`s
|jS(N(tisdigit(Rc((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRd6RcS`s
|jS(N(Rz(Rc((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRd7Riit0(R<RfRgRhRntinserttmaxtchain(tlefttrightt
left_splittright_split((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRo2s
""//tSpecifierSetcB`seZdddZdZdZdZdZdZdZ	dZ
d	Zed
Z
e
jdZ
dZdd
ZddZRS(RcC`sg|jdD]}|jr|j^q}t}xL|D]D}y|jt|WqDtk
r|jt|qDXqDWt||_||_	dS(Nt,(
RuR&tsettaddR\RRBt	frozensett_specsR((R
t
specifiersRtstparsedt	specifier((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR+Os4	

cC`s=|jdk	r!dj|jnd}djt||S(Ns, prereleases={0!r}Rs(R(RR$RR-(R
R.((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR/ds!cC`s djtd|jDS(NRcs`s|]}t|VqdS(N(R-(t.0R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pys	ns(RetsortedR(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRmscC`s
t|jS(N(R0R(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRpscC`st|trt|}nt|ts1tSt}t|j|jB|_|jdkr|jdk	r|j|_nZ|jdk	r|jdkr|j|_n-|j|jkr|j|_ntd|S(NsFCannot combine SpecifierSets with True and False prerelease overrides.(	R1RRR2RRR(Rt
ValueError(R
RR((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__and__ss		cC`set|trt|}n7t|trBtt|}nt|tsUtS|j|jkS(N(R1RRRR-R2R(R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscC`set|trt|}n7t|trBtt|}nt|tsUtS|j|jkS(N(R1RRRR-R2R(R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscC`s
t|jS(N(RnR(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__len__scC`s
t|jS(N(titerR(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__iter__scC`s:|jdk	r|jS|js#dStd|jDS(Ncs`s|]}|jVqdS(N(R(RR((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pys	s(R(RRtany(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRs
	cC`s
||_dS(N(R((R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscC`s
|j|S(N(R(R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR8sc`sptttfs$tndkr<|jnrPjrPtStfd|j	DS(Nc3`s$|]}|jdVqdS(RN(R(RR(RR(sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pys	s(
R1RRRRRR9R:tallR(R
RR((RRsN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscC`s|dkr|j}n|jrTx,|jD]!}|j|dt|}q+W|Sg}g}x|D]{}t|ttfst|}n|}t|trqgn|j	r|r|s|j
|qqg|j
|qgW|r|r|dkr|S|SdS(NR(RRRRtboolR1RRRR9R<(R
RRR)tfilteredR>RR@((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRs*	
N(R	R
RR+R/RRRRRRRRARRR8RR(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRMs						
	
			(t
__future__RRRRRYRgRSt_compatRRR!RRRRRtABCMetatobjectRRRBR[R\RTRvRiRoR(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyts""94				PK@N#]R#/#/9site-packages/pkg_resources/_vendor/packaging/markers.pycnu[
fc@`suddlmZmZmZddlZddlZddlZddlZddlm	Z	m
Z
mZmZddlm
Z
mZmZmZddlmZddlmZddlmZmZd	d
ddd
gZd	efdYZd
efdYZdefdYZdefdYZdefdYZdefdYZ defdYZ!ededBedBedBedBedBedBed Bed!Bed"Bed#Bed$Bed%Bed&Bed'Bed(Bed)Bed*BZ"id#d$6d"d%6dd&6dd'6dd(6dd)6Z#e"j$d+ed,ed-Bed.Bed/Bed0Bed1Bed2Bed3BZ%e%ed4Bed5BZ&e&j$d6ed7ed8BZ'e'j$d9ed:ed;BZ(e"e'BZ)ee)e&e)Z*e*j$d<ed=j+Z,ed>j+Z-eZ.e*ee,e.e-BZ/e.e/e
e(e.>ee.eZ0d?Z1e2d@Z3idAd56dBd46ej4d36ej5d/6ej6d-6ej7d06ej8d.6ej9d26Z:dCZ;eZ<dDZ=dEZ>dFZ?dGZ@defdHYZAdS(Ii(tabsolute_importtdivisiontprint_functionN(tParseExceptiontParseResultststringStartt	stringEnd(t
ZeroOrMoretGrouptForwardtQuotedString(tLiterali(tstring_types(t	SpecifiertInvalidSpecifiert
InvalidMarkertUndefinedComparisontUndefinedEnvironmentNametMarkertdefault_environmentcB`seZdZRS(sE
    An invalid marker was found, users should refer to PEP 508.
    (t__name__t
__module__t__doc__(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRscB`seZdZRS(sP
    An invalid operation was attempted on a value that doesn't support it.
    (RRR(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRscB`seZdZRS(s\
    A name was attempted to be used that does not exist inside of the
    environment.
    (RRR(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR%stNodecB`s,eZdZdZdZdZRS(cC`s
||_dS(N(tvalue(tselfR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyt__init__.scC`s
t|jS(N(tstrR(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyt__str__1scC`sdj|jjt|S(Ns<{0}({1!r})>(tformatt	__class__RR(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyt__repr__4scC`s
tdS(N(tNotImplementedError(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyt	serialize7s(RRRRRR!(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR,s			tVariablecB`seZdZRS(cC`s
t|S(N(R(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR!=s(RRR!(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR";stValuecB`seZdZRS(cC`s
dj|S(Ns"{0}"(R(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR!Cs(RRR!(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR#AstOpcB`seZdZRS(cC`s
t|S(N(R(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR!Is(RRR!(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR$Gstimplementation_versiontplatform_python_implementationtimplementation_nametpython_full_versiontplatform_releasetplatform_versiontplatform_machinetplatform_systemtpython_versiontsys_platformtos_namesos.namessys.platformsplatform.versionsplatform.machinesplatform.python_implementationtpython_implementationtextracC`sttj|d|dS(Ni(R"tALIASEStget(tstltt((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pytits===s==s>=s<=s!=s~=t>tst RARB(	RCtlistR@RtAssertionErrortlenRHtjoinR!(tmarkerRGtinnerRK((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRHs!
&cC`s
||kS(N((tlhstrhs((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR7R8cC`s
||kS(N((RSRT((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR7R8cC`sy%tdj|j|g}Wntk
r8nX|j|Stj|j}|dkrtdj	|||n|||S(NR8s#Undefined {0!r} on {1!r} and {2!r}.(
R
RPR!Rtcontainst
_operatorsR3tNoneRR(RStopRTtspectoper((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyt_eval_ops%

cC`s:|j|t}|tkr6tdj|n|S(Ns/{0!r} does not exist in evaluation environment.(R3t
_undefinedRR(tenvironmenttnameR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyt_get_envs
c	C`s,gg}x|D]}t|tttfs4tt|tr`|djt||qt|tr|\}}}t|trt||j	}|j	}n|j	}t||j	}|djt
|||q|dkst|dkr|jgqqWtd|DS(NiR>R?cs`s|]}t|VqdS(N(tall(RJtitem((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pys	s(R>R?(RCRMR@RRNtappendt_evaluate_markersR"R_RR[tany(	tmarkersR]tgroupsRQRSRXRTt	lhs_valuet	rhs_value((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRcs"	
	 cC`sFdj|}|j}|dkrB||dt|j7}n|S(Ns{0.major}.{0.minor}.{0.micro}tfinali(RtreleaselevelRtserial(tinfotversiontkind((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pytformat_full_versions
	cC`sttdr0ttjj}tjj}nd}d}i|d6|d6tjd6tjd6tj	d6tj
d	6tjd
6tjd6tjd6tjd
 d6tjd6S(Ntimplementationt0R8R'R%R/R+R)R,R*R(R&iR-R.(
thasattrtsysRoRpRmR^tostplatformtmachinetreleasetsystemR-R0(tiverR'((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRs"






cB`s/eZdZdZdZddZRS(cC`seyttj||_WnBtk
r`}dj|||j|jd!}t|nXdS(Ns+Invalid marker: {0!r}, parse error at {1!r}i(RDtMARKERtparseStringt_markersRRtlocR(RRQteterr_str((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRscC`s
t|jS(N(RHR|(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRscC`sdjt|S(Ns(RR(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRscC`s5t}|dk	r%|j|nt|j|S(s$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(RRWtupdateRcR|(RR]tcurrent_environment((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pytevaluate s		N(RRRRRRWR(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRs			(Bt
__future__RRRtoperatorRtRuRstpkg_resources.extern.pyparsingRRRRRRR	R
RtLt_compatRt
specifiersR
Rt__all__t
ValueErrorRRRtobjectRR"R#R$tVARIABLER2tsetParseActiontVERSION_CMPt	MARKER_OPtMARKER_VALUEtBOOLOPt
MARKER_VARtMARKER_ITEMtsuppresstLPARENtRPARENtMARKER_EXPRtMARKER_ATOMRzRDtTrueRHtlttleteqtnetgetgtRVR[R\R_RcRoRR(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyts|""	

	E

		







						PK@N#]oMM>site-packages/pkg_resources/_vendor/packaging/requirements.pycnu[
fc@`sYddlmZmZmZddlZddlZddlmZmZm	Z	m
Z
ddlmZmZm
Z
mZmZddlmZddlmZddlmZmZdd	lmZmZmZd
efdYZeejejZ edj!Z"ed
j!Z#edj!Z$edj!Z%edj!Z&edj!Z'edj!Z(edZ)e ee)e BZ*ee ee*Z+e+dZ,e+Z-eddZ.e(e.Z/e-ee&e-Z0e"e
e0e#dZ1eej2ej3ej4BZ5eej2ej3ej4BZ6e5e6AZ7ee7ee&e7ddde8dZ9e
e$e9e%e9BZ:e:j;de	e:dZ<e<j;de	edZej;de'Z=e=eZ>e<e
e>Z?e/e
e>Z@e,e
e1e@e?BZAeeAeZBd eCfd!YZDdS("i(tabsolute_importtdivisiontprint_functionN(tstringStartt	stringEndtoriginalTextFortParseException(t
ZeroOrMoretWordtOptionaltRegextCombine(tLiteral(tparsei(tMARKER_EXPRtMarker(tLegacySpecifiert	SpecifiertSpecifierSettInvalidRequirementcB`seZdZRS(sJ
    An invalid requirement was found, users should refer to PEP 508.
    (t__name__t
__module__t__doc__(((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyRst[t]t(t)t,t;t@s-_.tnames[^ ]+turltextrast
joinStringtadjacentt	_raw_speccC`s
|jpdS(Nt(R#(tstltt((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyt6R$t	specifiercC`s|dS(Ni((R%R&R'((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyR(9R$tmarkercC`st||j|j!S(N(Rt_original_startt
_original_end(R%R&R'((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyR(=R$tRequirementcB`s)eZdZdZdZdZRS(sParse 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.
    cC`sytj|}Wn9tk
rN}tdj||j|jd!nX|j|_|jrtj|j}|j	o|j
s|j	r|j
rtdn|j|_n	d|_t|j
r|j
jng|_
t|j|_|jr|jnd|_dS(Ns+Invalid requirement, parse error at "{0!r}"isInvalid URL given(tREQUIREMENTtparseStringRRtformattlocRRturlparsetschemetnetloctNonetsetR tasListRR)R*(tselftrequirement_stringtreqtet
parsed_url((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyt__init__Xs"!		'cC`s|jg}|jr@|jdjdjt|jn|jrb|jt|jn|jr|jdj|jn|j	r|jdj|j	ndj|S(Ns[{0}]Rs@ {0}s; {0}R$(
RR tappendR0tjointsortedR)tstrRR*(R8tparts((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyt__str__ms	+			cC`sdjt|S(Ns(R0RA(R8((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyt__repr__~s(RRRR=RCRD(((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyR-Ks		(Et
__future__RRRtstringtretpkg_resources.extern.pyparsingRRRRRRR	R
RRtLt%pkg_resources.extern.six.moves.urllibR
R2tmarkersRRt
specifiersRRRt
ValueErrorRt
ascii_letterstdigitstALPHANUMtsuppresstLBRACKETtRBRACKETtLPARENtRPARENtCOMMAt	SEMICOLONtATtPUNCTUATIONtIDENTIFIER_ENDt
IDENTIFIERtNAMEtEXTRAtURItURLtEXTRAS_LISTtEXTRASt
_regex_strtVERBOSEt
IGNORECASEtVERSION_PEP440tVERSION_LEGACYtVERSION_ONEtFalsetVERSION_MANYt
_VERSION_SPECtsetParseActiontVERSION_SPECtMARKER_SEPERATORtMARKERtVERSION_AND_MARKERtURL_AND_MARKERtNAMED_REQUIREMENTR.tobjectR-(((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pytsZ"(



PK@N#][9cc<site-packages/pkg_resources/_vendor/packaging/specifiers.pycnu[
fc@`s<ddlmZmZmZddlZddlZddlZddlZddlm	Z	m
Z
ddlmZm
Z
mZdefdYZde
ejefd	YZd
efdYZdefd
YZdZdefdYZejdZdZdZdefdYZdS(i(tabsolute_importtdivisiontprint_functionNi(tstring_typestwith_metaclass(tVersiont
LegacyVersiontparsetInvalidSpecifiercB`seZdZRS(sH
    An invalid specifier was found, users should refer to PEP 440.
    (t__name__t
__module__t__doc__(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRst
BaseSpecifiercB`seZejdZejdZejdZejdZejdZ	e	j
dZ	ejddZejddZ
RS(	cC`sdS(s
        Returns the str representation of this Specifier like object. This
        should be representative of the Specifier itself.
        N((tself((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__str__tcC`sdS(sF
        Returns a hash value for this Specifier like object.
        N((R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__hash__RcC`sdS(sq
        Returns a boolean representing whether or not the two Specifier like
        objects are equal.
        N((R
tother((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__eq__$RcC`sdS(su
        Returns a boolean representing whether or not the two Specifier like
        objects are not equal.
        N((R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__ne__+RcC`sdS(sg
        Returns whether or not pre-releases as a whole are allowed by this
        specifier.
        N((R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pytprereleases2RcC`sdS(sd
        Sets whether or not pre-releases as a whole are allowed by this
        specifier.
        N((R
tvalue((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR9RcC`sdS(sR
        Determines if the given item is contained within this specifier.
        N((R
titemR((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pytcontains@RcC`sdS(s
        Takes an iterable of items and filters them so that only items which
        are contained within this specifier are allowed in it.
        N((R
titerableR((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pytfilterFRN(R	R
tabctabstractmethodRRRRtabstractpropertyRtsettertNoneRR(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRst_IndividualSpecifiercB`seZiZdddZdZdZdZdZdZ	dZ
dZed	Z
ed
ZedZejdZd
ZddZddZRS(RcC`sj|jj|}|s0tdj|n|jdj|jdjf|_||_dS(NsInvalid specifier: '{0}'toperatortversion(t_regextsearchRtformattgrouptstript_spect_prereleases(R
tspecRtmatch((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__init__RscC`sF|jdk	r!dj|jnd}dj|jjt||S(Ns, prereleases={0!r}Rs<{0}({1!r}{2})>(R(RR$Rt	__class__R	tstr(R
tpre((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__repr___s!		cC`sdj|jS(Ns{0}{1}(R$R'(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRlscC`s
t|jS(N(thashR'(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRoscC`s`t|tr:y|j|}WqPtk
r6tSXnt||jsPtS|j|jkS(N(t
isinstanceRR,RtNotImplementedR'(R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRrs
cC`s`t|tr:y|j|}WqPtk
r6tSXnt||jsPtS|j|jkS(N(R1RR,RR2R'(R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR}s
cC`st|dj|j|S(Ns_compare_{0}(tgetattrR$t
_operators(R
top((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt
_get_operatorscC`s(t|ttfs$t|}n|S(N(R1RRR(R
R!((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_coerce_versionscC`s|jdS(Ni(R'(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR scC`s|jdS(Ni(R'(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR!scC`s|jS(N(R((R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscC`s
||_dS(N(R((R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscC`s
|j|S(N(R(R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__contains__scC`sW|dkr|j}n|j|}|jr;|r;tS|j|j||jS(N(RRR7t
is_prereleasetFalseR6R R!(R
RR((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscc`st}g}i|dk	r!|ntd6}xf|D]^}|j|}|j||r2|jr|pn|jr|j|qt}|Vq2q2W|r|rx|D]}|VqWndS(NR(R:RtTrueR7RR9Rtappend(R
RRtyieldedtfound_prereleasestkwR!tparsed_version((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRs
	

N(R	R
R4RR+R/RRRRR6R7tpropertyR R!RRR8RR(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRNs 
	
							tLegacySpecifiercB`seZdZejdedejejBZidd6dd6dd6d	d
6dd6d
d6ZdZ	dZ
dZdZdZ
dZdZRS(s
        (?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.
        )
        s^\s*s\s*$tequals==t	not_equals!=tless_than_equals<=tgreater_than_equals>=t	less_thantcC`s(t|ts$tt|}n|S(N(R1RR-(R
R!((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR7scC`s||j|kS(N(R7(R
tprospectiveR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_equalscC`s||j|kS(N(R7(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_not_equalscC`s||j|kS(N(R7(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_less_than_equalscC`s||j|kS(N(R7(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_greater_than_equalscC`s||j|kS(N(R7(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_less_thanscC`s||j|kS(N(R7(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_greater_thans(R	R
t
_regex_strtretcompiletVERBOSEt
IGNORECASER"R4R7RLRMRNRORPRQ(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRBs"

						c`s"tjfd}|S(Nc`s#t|tstS|||S(N(R1RR:(R
RKR)(tfn(sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pytwrappeds(t	functoolstwraps(RWRX((RWsN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_require_version_compare
st	SpecifiercB`seZdZejdedejejBZidd6dd6dd6d	d
6dd6d
d6dd6dd6Ze	dZ
e	dZe	dZe	dZ
e	dZe	dZe	dZdZedZejdZRS(s
        (?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.
                (?=RGRHRIRJt	arbitrarys===cC`sfdjttjdt|d }|d7}|jd||oe|jd||S(Nt.cS`s|jdo|jdS(Ntposttdev(t
startswith(tx((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pytsis.*s>=s==(tjointlistt	itertoolst	takewhilet_version_splitR6(R
RKR)tprefix((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_compatibles

cC`s|jdrht|j}t|d }tt|}|t| }t||\}}n't|}|jst|j}n||kS(Ns.*i(tendswithRtpublicRiR-tlent_pad_versiontlocal(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRLs	cC`s|j||S(N(RL(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRMscC`s|t|kS(N(R(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRNscC`s|t|kS(N(R(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyROscC`sXt|}||kstS|jrT|jrTt|jt|jkrTtSntS(N(RR:R9tbase_versionR;(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRPscC`st|}||kstS|jrT|jrTt|jt|jkrTtSn|jdk	rt|jt|jkrtSntS(N(RR:tis_postreleaseRqRpRR;(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRQscC`s"t|jt|jkS(N(R-tlower(R
RKR)((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt_compare_arbitraryscC`ss|jdk	r|jS|j\}}|dkro|dkrY|jdrY|d }nt|jrotSntS(	Ns==s>=s<=s~=s===s.*i(s==s>=s<=s~=s===(R(RR'RlRR9R;R:(R
R R!((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRs
cC`s
||_dS(N(R((R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRs(R	R
RRRSRTRURVR"R4R[RkRLRMRNRORPRQRtRARR(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR\s,^
#	s^([0-9]+)((?:a|b|c|rc)[0-9]+)$cC`s\g}xO|jdD]>}tj|}|rG|j|jq|j|qW|S(NR_(tsplitt
_prefix_regexR#textendtgroupsR<(R!tresultRR*((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRi'sc	C`sgg}}|jttjd||jttjd||j|t|d|j|t|d|jddgtdt|dt|d|jddgtdt|dt|dttj|ttj|fS(NcS`s
|jS(N(tisdigit(Rc((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRd6RcS`s
|jS(N(Rz(Rc((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRd7Riit0(R<RfRgRhRntinserttmaxtchain(tlefttrightt
left_splittright_split((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRo2s
""//tSpecifierSetcB`seZdddZdZdZdZdZdZdZ	dZ
d	Zed
Z
e
jdZ
dZdd
ZddZRS(RcC`sg|jdD]}|jr|j^q}t}xL|D]D}y|jt|WqDtk
r|jt|qDXqDWt||_||_	dS(Nt,(
RuR&tsettaddR\RRBt	frozensett_specsR((R
t
specifiersRtstparsedt	specifier((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR+Os4	

cC`s=|jdk	r!dj|jnd}djt||S(Ns, prereleases={0!r}Rs(R(RR$RR-(R
R.((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR/ds!cC`s djtd|jDS(NRcs`s|]}t|VqdS(N(R-(t.0R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pys	ns(RetsortedR(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRmscC`s
t|jS(N(R0R(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRpscC`st|trt|}nt|ts1tSt}t|j|jB|_|jdkr|jdk	r|j|_nZ|jdk	r|jdkr|j|_n-|j|jkr|j|_ntd|S(NsFCannot combine SpecifierSets with True and False prerelease overrides.(	R1RRR2RRR(Rt
ValueError(R
RR((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__and__ss		cC`set|trt|}n7t|trBtt|}nt|tsUtS|j|jkS(N(R1RRRR-R2R(R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscC`set|trt|}n7t|trBtt|}nt|tsUtS|j|jkS(N(R1RRRR-R2R(R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscC`s
t|jS(N(RnR(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__len__scC`s
t|jS(N(titerR(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyt__iter__scC`s:|jdk	r|jS|js#dStd|jDS(Ncs`s|]}|jVqdS(N(R(RR((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pys	s(R(RRtany(R
((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRs
	cC`s
||_dS(N(R((R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscC`s
|j|S(N(R(R
R((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyR8sc`sptttfs$tndkr<|jnrPjrPtStfd|j	DS(Nc3`s$|]}|jdVqdS(RN(R(RR(RR(sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pys	s(
R1RRRRRR9R:tallR(R
RR((RRsN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRscC`s|dkr|j}n|jrTx,|jD]!}|j|dt|}q+W|Sg}g}x|D]{}t|ttfst|}n|}t|trqgn|j	r|r|s|j
|qqg|j
|qgW|r|r|dkr|S|SdS(NR(RRRRtboolR1RRRR9R<(R
RRR)tfilteredR>RR@((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRs*	
N(R	R
RR+R/RRRRRRRRARRR8RR(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyRMs						
	
			(t
__future__RRRRRYRgRSt_compatRRR!RRRRRtABCMetatobjectRRRBR[R\RTRvRiRoR(((sN/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/specifiers.pyts""94				PK@N#]08 8 8site-packages/pkg_resources/_vendor/packaging/markers.pynu[# 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)
PK@N#]1;site-packages/pkg_resources/_vendor/packaging/__about__.pyonu[
fc@`srddlmZmZmZdddddddd	gZd
ZdZdZd
ZdZ	dZ
dZde	ZdS(i(tabsolute_importtdivisiontprint_functiont	__title__t__summary__t__uri__t__version__t
__author__t	__email__t__license__t
__copyright__t	packagings"Core utilities for Python packagess!https://github.com/pypa/packagings16.8s)Donald Stufft and individual contributorssdonald@stufft.ios"BSD or Apache License, Version 2.0sCopyright 2014-2016 %sN(
t
__future__RRRt__all__RRRRRRR	R
(((sM/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/__about__.pytsPK@N#]<site-packages/pkg_resources/_vendor/packaging/_structures.pynu[# 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()
PK@N#]pxؙ..9site-packages/pkg_resources/_vendor/packaging/markers.pyonu[
fc@`suddlmZmZmZddlZddlZddlZddlZddlm	Z	m
Z
mZmZddlm
Z
mZmZmZddlmZddlmZddlmZmZd	d
ddd
gZd	efdYZd
efdYZdefdYZdefdYZdefdYZdefdYZ defdYZ!ededBedBedBedBedBedBed Bed!Bed"Bed#Bed$Bed%Bed&Bed'Bed(Bed)Bed*BZ"id#d$6d"d%6dd&6dd'6dd(6dd)6Z#e"j$d+ed,ed-Bed.Bed/Bed0Bed1Bed2Bed3BZ%e%ed4Bed5BZ&e&j$d6ed7ed8BZ'e'j$d9ed:ed;BZ(e"e'BZ)ee)e&e)Z*e*j$d<ed=j+Z,ed>j+Z-eZ.e*ee,e.e-BZ/e.e/e
e(e.>ee.eZ0d?Z1e2d@Z3idAd56dBd46ej4d36ej5d/6ej6d-6ej7d06ej8d.6ej9d26Z:dCZ;eZ<dDZ=dEZ>dFZ?dGZ@defdHYZAdS(Ii(tabsolute_importtdivisiontprint_functionN(tParseExceptiontParseResultststringStartt	stringEnd(t
ZeroOrMoretGrouptForwardtQuotedString(tLiterali(tstring_types(t	SpecifiertInvalidSpecifiert
InvalidMarkertUndefinedComparisontUndefinedEnvironmentNametMarkertdefault_environmentcB`seZdZRS(sE
    An invalid marker was found, users should refer to PEP 508.
    (t__name__t
__module__t__doc__(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRscB`seZdZRS(sP
    An invalid operation was attempted on a value that doesn't support it.
    (RRR(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRscB`seZdZRS(s\
    A name was attempted to be used that does not exist inside of the
    environment.
    (RRR(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR%stNodecB`s,eZdZdZdZdZRS(cC`s
||_dS(N(tvalue(tselfR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyt__init__.scC`s
t|jS(N(tstrR(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyt__str__1scC`sdj|jjt|S(Ns<{0}({1!r})>(tformatt	__class__RR(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyt__repr__4scC`s
tdS(N(tNotImplementedError(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyt	serialize7s(RRRRRR!(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR,s			tVariablecB`seZdZRS(cC`s
t|S(N(R(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR!=s(RRR!(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR";stValuecB`seZdZRS(cC`s
dj|S(Ns"{0}"(R(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR!Cs(RRR!(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR#AstOpcB`seZdZRS(cC`s
t|S(N(R(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR!Is(RRR!(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR$Gstimplementation_versiontplatform_python_implementationtimplementation_nametpython_full_versiontplatform_releasetplatform_versiontplatform_machinetplatform_systemtpython_versiontsys_platformtos_namesos.namessys.platformsplatform.versionsplatform.machinesplatform.python_implementationtpython_implementationtextracC`sttj|d|dS(Ni(R"tALIASEStget(tstltt((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pytits===s==s>=s<=s!=s~=t>tst RARB(RCtlisttlenR@RHtjoinR!(tmarkerRGtinnerRK((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRHs!
&cC`s
||kS(N((tlhstrhs((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR7R8cC`s
||kS(N((RRRS((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyR7R8cC`sy%tdj|j|g}Wntk
r8nX|j|Stj|j}|dkrtdj	|||n|||S(NR8s#Undefined {0!r} on {1!r} and {2!r}.(
R
ROR!Rtcontainst
_operatorsR3tNoneRR(RRtopRStspectoper((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyt_eval_ops%

cC`s:|j|t}|tkr6tdj|n|S(Ns/{0!r} does not exist in evaluation environment.(R3t
_undefinedRR(tenvironmenttnameR((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyt_get_envs
c	C`sgg}x|D]}t|trB|djt||qt|tr|\}}}t|trt||j}|j}n|j}t||j}|djt|||q|dkr|jgqqWt	d|DS(NiR?cs`s|]}t|VqdS(N(tall(RJtitem((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pys	s(
RCRMtappendt_evaluate_markersR@R"R^RRZtany(	tmarkersR\tgroupsRPRRRWRSt	lhs_valuet	rhs_value((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRbs	
	 cC`sFdj|}|j}|dkrB||dt|j7}n|S(Ns{0.major}.{0.minor}.{0.micro}tfinali(RtreleaselevelRtserial(tinfotversiontkind((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pytformat_full_versions
	cC`sttdr0ttjj}tjj}nd}d}i|d6|d6tjd6tjd6tj	d6tj
d	6tjd
6tjd6tjd6tjd
 d6tjd6S(Ntimplementationt0R8R'R%R/R+R)R,R*R(R&iR-R.(
thasattrtsysRnRoRlR]tostplatformtmachinetreleasetsystemR-R0(tiverR'((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRs"






cB`s/eZdZdZdZddZRS(cC`seyttj||_WnBtk
r`}dj|||j|jd!}t|nXdS(Ns+Invalid marker: {0!r}, parse error at {1!r}i(RDtMARKERtparseStringt_markersRRtlocR(RRPteterr_str((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRscC`s
t|jS(N(RHR{(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRscC`sdjt|S(Ns(RR(R((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRscC`s5t}|dk	r%|j|nt|j|S(s$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(RRVtupdateRbR{(RR\tcurrent_environment((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pytevaluate s		N(RRRRRRVR(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyRs			(Bt
__future__RRRtoperatorRsRtRrtpkg_resources.extern.pyparsingRRRRRRR	R
RtLt_compatRt
specifiersR
Rt__all__t
ValueErrorRRRtobjectRR"R#R$tVARIABLER2tsetParseActiontVERSION_CMPt	MARKER_OPtMARKER_VALUEtBOOLOPt
MARKER_VARtMARKER_ITEMtsuppresstLPARENtRPARENtMARKER_EXPRtMARKER_ATOMRyRDtTrueRHtlttleteqtnetgetgtRURZR[R^RbRnRR(((sK/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/markers.pyts|""	

	E

		







						PK@N#]oMM>site-packages/pkg_resources/_vendor/packaging/requirements.pyonu[
fc@`sYddlmZmZmZddlZddlZddlmZmZm	Z	m
Z
ddlmZmZm
Z
mZmZddlmZddlmZddlmZmZdd	lmZmZmZd
efdYZeejejZ edj!Z"ed
j!Z#edj!Z$edj!Z%edj!Z&edj!Z'edj!Z(edZ)e ee)e BZ*ee ee*Z+e+dZ,e+Z-eddZ.e(e.Z/e-ee&e-Z0e"e
e0e#dZ1eej2ej3ej4BZ5eej2ej3ej4BZ6e5e6AZ7ee7ee&e7ddde8dZ9e
e$e9e%e9BZ:e:j;de	e:dZ<e<j;de	edZej;de'Z=e=eZ>e<e
e>Z?e/e
e>Z@e,e
e1e@e?BZAeeAeZBd eCfd!YZDdS("i(tabsolute_importtdivisiontprint_functionN(tstringStartt	stringEndtoriginalTextFortParseException(t
ZeroOrMoretWordtOptionaltRegextCombine(tLiteral(tparsei(tMARKER_EXPRtMarker(tLegacySpecifiert	SpecifiertSpecifierSettInvalidRequirementcB`seZdZRS(sJ
    An invalid requirement was found, users should refer to PEP 508.
    (t__name__t
__module__t__doc__(((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyRst[t]t(t)t,t;t@s-_.tnames[^ ]+turltextrast
joinStringtadjacentt	_raw_speccC`s
|jpdS(Nt(R#(tstltt((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyt6R$t	specifiercC`s|dS(Ni((R%R&R'((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyR(9R$tmarkercC`st||j|j!S(N(Rt_original_startt
_original_end(R%R&R'((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyR(=R$tRequirementcB`s)eZdZdZdZdZRS(sParse 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.
    cC`sytj|}Wn9tk
rN}tdj||j|jd!nX|j|_|jrtj|j}|j	o|j
s|j	r|j
rtdn|j|_n	d|_t|j
r|j
jng|_
t|j|_|jr|jnd|_dS(Ns+Invalid requirement, parse error at "{0!r}"isInvalid URL given(tREQUIREMENTtparseStringRRtformattlocRRturlparsetschemetnetloctNonetsetR tasListRR)R*(tselftrequirement_stringtreqtet
parsed_url((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyt__init__Xs"!		'cC`s|jg}|jr@|jdjdjt|jn|jrb|jt|jn|jr|jdj|jn|j	r|jdj|j	ndj|S(Ns[{0}]Rs@ {0}s; {0}R$(
RR tappendR0tjointsortedR)tstrRR*(R8tparts((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyt__str__ms	+			cC`sdjt|S(Ns(R0RA(R8((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyt__repr__~s(RRRR=RCRD(((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pyR-Ks		(Et
__future__RRRtstringtretpkg_resources.extern.pyparsingRRRRRRR	R
RRtLt%pkg_resources.extern.six.moves.urllibR
R2tmarkersRRt
specifiersRRRt
ValueErrorRt
ascii_letterstdigitstALPHANUMtsuppresstLBRACKETtRBRACKETtLPARENtRPARENtCOMMAt	SEMICOLONtATtPUNCTUATIONtIDENTIFIER_ENDt
IDENTIFIERtNAMEtEXTRAtURItURLtEXTRAS_LISTtEXTRASt
_regex_strtVERBOSEt
IGNORECASEtVERSION_PEP440tVERSION_LEGACYtVERSION_ONEtFalsetVERSION_MANYt
_VERSION_SPECtsetParseActiontVERSION_SPECtMARKER_SEPERATORtMARKERtVERSION_AND_MARKERtURL_AND_MARKERtNAMED_REQUIREMENTR.tobjectR-(((sP/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/requirements.pytsZ"(



PK@N#]=site-packages/pkg_resources/_vendor/packaging/requirements.pynu[# 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))
PK@N#]b:cXX7site-packages/pkg_resources/_vendor/packaging/utils.pycnu[
fc@`sDddlmZmZmZddlZejdZdZdS(i(tabsolute_importtdivisiontprint_functionNs[-_.]+cC`stjd|jS(Nt-(t_canonicalize_regextsubtlower(tname((sI/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/utils.pytcanonicalize_names(t
__future__RRRtretcompileRR(((sI/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/utils.pytsPK@N#]v9site-packages/pkg_resources/_vendor/packaging/__init__.pynu[# 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__",
]
PK@N#]|Eymym;site-packages/pkg_resources/_vendor/packaging/specifiers.pynu[# 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
PK@N#]Sff:site-packages/pkg_resources/_vendor/packaging/__init__.pycnu[
fc@`sxddlmZmZmZddlmZmZmZmZm	Z	m
Z
mZmZdddddd	d
dgZ
dS(
i(tabsolute_importtdivisiontprint_functioni(t
__author__t
__copyright__t	__email__t__license__t__summary__t	__title__t__uri__t__version__RRR	R
RRRRN(t
__future__RRRt	__about__RRRRRRR	R
t__all__(((sL/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/__init__.pyts:PK@N#]h =site-packages/pkg_resources/_vendor/packaging/_structures.pycnu[
fc@`s^ddlmZmZmZdefdYZeZdefdYZeZdS(i(tabsolute_importtdivisiontprint_functiontInfinitycB`sYeZdZdZdZdZdZdZdZdZ	dZ
RS(	cC`sdS(NR((tself((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__repr__	scC`stt|S(N(thashtrepr(R((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__hash__scC`stS(N(tFalse(Rtother((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__lt__scC`stS(N(R	(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__le__scC`st||jS(N(t
isinstancet	__class__(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__eq__scC`st||jS(N(R
R(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__ne__scC`stS(N(tTrue(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__gt__scC`stS(N(R(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__ge__scC`stS(N(tNegativeInfinity(R((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyt__neg__!s(t__name__t
__module__RRRRRRRRR(((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyRs								RcB`sYeZdZdZdZdZdZdZdZdZ	dZ
RS(	cC`sdS(Ns	-Infinity((R((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR)scC`stt|S(N(RR(R((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR,scC`stS(N(R(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR/scC`stS(N(R(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR2scC`st||jS(N(R
R(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR5scC`st||jS(N(R
R(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR8scC`stS(N(R	(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR;scC`stS(N(R	(RR
((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR>scC`stS(N(R(R((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyRAs(RRRRRRRRRRR(((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyR's								N(t
__future__RRRtobjectRR(((sO/usr/lib/python2.7/site-packages/pkg_resources/_vendor/packaging/_structures.pyts	PK@N#]c+̓̓1site-packages/pkg_resources/_vendor/pyparsing.pycnu[
fci@sdZdZdZdZddlZddlmZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlZddlZddlZddlmZyddlmZWn!ek
rddlmZnXydd	l
mZWn?ek
r=ydd	lmZWnek
r9eZnXnXd
ddd
ddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdgdhdidjdkdldmdndodpdqdrgiZee	jds ZedtdskZere	jZ e!Z"e#Z$e!Z%e&e'e(e)e*ee+e,e-e.e/gZ0nre	j1Z e2Z3duZ%gZ0ddl4Z4xEdvj5D]7Z6ye0j7e8e4e6Wne9k
rZq$nXq$We:dwe3dxDZ;dyZ<dze=fd{YZ>ej?ej@ZAd|ZBeBd}ZCeAeBZDe#d~ZEdjFdejGDZHd!eIfdYZJd#eJfdYZKd%eJfdYZLd'eLfdYZMd*eIfdYZNde=fdYZOd&e=fdYZPe
jQjRePdZSdZTdZUdZVdZWdZXdZYddZZd(e=fdYZ[d0e[fdYZ\de\fdYZ]de\fdYZ^de\fdYZ_e_Z`e_e[_ade\fdYZbde_fdYZcdebfdYZddpe\fdYZed3e\fdYZfd+e\fdYZgd)e\fdYZhd
e\fdYZid2e\fdYZjde\fdYZkdekfdYZldekfdYZmdekfdYZnd.ekfdYZod-ekfdYZpd5ekfdYZqd4ekfdYZrd$e[fdYZsd
esfdYZtd esfdYZudesfdYZvdesfdYZwd"e[fdYZxdexfdYZydexfdYZzdexfdYZ{de{fdYZ|d6e{fdYZ}de=fdYZ~e~ZdexfdYZd,exfdYZdexfdYZdefdYZd1exfdYZdefdYZdefdYZdefdYZd/efdYZde=fdYZdZdedZedZdZdZdZdZeedZdZedZdZdZe]jdGZemjdMZenjdLZeojdeZepjddZefeEdddjdZegdjdZegdjdZeeBeBefeHddddxBegdejBZeeedeZe_dedjdee|eeBjddZdZdZdZdZdZedZedZdZdZdZdZe=e_ddZe>Ze=e_e=e_ededdZeZeegddjdZeegddjdZeegddegddBjdZee`dejjdZddeejdZedZedZedZeefeAeDdjd\ZZeedj5dZegddjFejdjdZdZeegddjdZegdjdZegd	jjd
ZegdjdZeegddeBjd
ZeZegdjdZee|efeHddeefde_denjjdZeeejeBddjd>ZdrfdYZedkrecdZecdZefeAeDdZeeddejeZeeejdZdeBZeeddejeZeeejdZededeedZejdejjdejjdejjd ddlZejjeejejjd!ndS("sS
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
s2.1.10s07 Oct 2016 01:31 UTCs*Paul McGuire iN(tref(tdatetime(tRLock(tOrderedDicttAndtCaselessKeywordtCaselessLiteralt
CharsNotIntCombinetDicttEachtEmptyt
FollowedBytForwardt
GoToColumntGrouptKeywordtLineEndt	LineStarttLiteralt
MatchFirsttNoMatchtNotAnyt	OneOrMoretOnlyOncetOptionaltOrtParseBaseExceptiontParseElementEnhancetParseExceptiontParseExpressiontParseFatalExceptiontParseResultstParseSyntaxExceptiont
ParserElementtQuotedStringtRecursiveGrammarExceptiontRegextSkipTot	StringEndtStringStarttSuppresstTokentTokenConvertertWhitetWordtWordEndt	WordStartt
ZeroOrMoret	alphanumstalphast
alphas8bittanyCloseTagt
anyOpenTagt
cStyleCommenttcoltcommaSeparatedListtcommonHTMLEntitytcountedArraytcppStyleCommenttdblQuotedStringtdblSlashCommentt
delimitedListtdictOftdowncaseTokenstemptythexnumsthtmlCommenttjavaStyleCommenttlinetlineEndt	lineStarttlinenotmakeHTMLTagstmakeXMLTagstmatchOnlyAtColtmatchPreviousExprtmatchPreviousLiteralt
nestedExprtnullDebugActiontnumstoneOftopAssoctoperatorPrecedencet
printablestpunc8bittpythonStyleCommenttquotedStringtremoveQuotestreplaceHTMLEntitytreplaceWitht
restOfLinetsglQuotedStringtsranget	stringEndtstringStartttraceParseActiont
unicodeStringtupcaseTokenst
withAttributet
indentedBlocktoriginalTextFortungroupt
infixNotationtlocatedExprt	withClasst
CloseMatchttokenMaptpyparsing_commoniicCs}t|tr|Syt|SWnUtk
rxt|jtjd}td}|jd|j	|SXdS(sDrop-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 | ... >.
        txmlcharrefreplaces&#\d+;cSs#dtt|ddd!dS(Ns\uiii(thextint(tt((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyttN(
t
isinstancetunicodetstrtUnicodeEncodeErrortencodetsystgetdefaultencodingR%tsetParseActionttransformString(tobjtrett
xmlcharref((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_ustrs
s6sum len sorted reversed list tuple set any all min maxccs|]}|VqdS(N((t.0ty((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	sicCsRd}ddjD}x/t||D]\}}|j||}q,W|S(s/Escape &, <, >, ", ', etc. in a string of data.s&><"'css|]}d|dVqdS(t&t;N((Rts((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	ssamp gt lt quot apos(tsplittziptreplace(tdatatfrom_symbolst
to_symbolstfrom_tto_((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_xml_escapes
t
_ConstantscBseZRS((t__name__t
__module__(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRst
0123456789tABCDEFabcdefi\Rrccs$|]}|tjkr|VqdS(N(tstringt
whitespace(Rtc((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	scBs_eZdZdd
d
dZedZdZdZdZ	ddZ
d	ZRS(s7base exception class for all parsing runtime exceptionsicCs[||_|dkr*||_d|_n||_||_||_|||f|_dS(NRr(tloctNonetmsgtpstrt
parserElementtargs(tselfRRRtelem((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__init__s					cCs||j|j|j|jS(s
        internal factory method to simplify creating one type of ParseException 
        from another - avoids having __init__ signature conflicts among subclasses
        (RRRR(tclstpe((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_from_exceptionscCsm|dkrt|j|jS|dkr>t|j|jS|dkr]t|j|jSt|dS(ssupported 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
        RHR7tcolumnREN(R7R(RHRRR7REtAttributeError(Rtaname((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__getattr__scCs d|j|j|j|jfS(Ns"%s (at char %d), (line:%d, col:%d)(RRRHR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__str__scCs
t|S(N(R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__repr__ss>!} ('-' operator) indicates that parsing is to stop 
       immediately because an unbacktrackable syntax error has been found(RRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR!scBs eZdZdZdZRS(sZexception thrown by L{ParserElement.validate} if the grammar could be improperly recursivecCs
||_dS(N(tparseElementTrace(RtparseElementList((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCsd|jS(NsRecursiveGrammarException: %s(R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s(RRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR$s	t_ParseResultsWithOffsetcBs,eZdZdZdZdZRS(cCs||f|_dS(N(ttup(Rtp1tp2((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR$scCs|j|S(N(R(Rti((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__getitem__&scCst|jdS(Ni(treprR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR(scCs|jd|f|_dS(Ni(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt	setOffset*s(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR#s			cBseZdZd-d-eedZd-d-eeedZdZedZ	dZ
dZdZdZ
e
Zd	Zd
ZdZdZd
ZereZeZeZn-eZeZeZdZdZdZdZdZd-dZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'ddZ(d Z)d!Z*d"Z+d-e,ded#Z-d$Z.d%Z/dd&ed'Z0d(Z1d)Z2d*Z3d+Z4d,Z5RS(.sI
    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
    cCs/t||r|Stj|}t|_|S(N(Rstobjectt__new__tTruet_ParseResults__doinit(RttoklisttnametasListtmodaltretobj((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRTs
	cCs|jrt|_d|_d|_i|_||_||_|dkrTg}n||trp||_	n-||t
rt||_	n|g|_	t|_n|dk	r|r|sd|j|s(R(R((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_itervaluesscsfdjDS(Nc3s|]}||fVqdS(N((RR(R(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	s(R(R((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt
_iteritemsscCst|jS(sVReturns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).(RR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytkeysscCst|jS(sXReturns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).(Rt
itervalues(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytvaluesscCst|jS(sfReturns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).(Rt	iteritems(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCs
t|jS(sSince keys() returns an iterator, this method is helpful in bypassing
           code that looks for the existence of any defined results names.(tboolR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pythaskeysscOs|sdg}nxI|jD];\}}|dkrJ|d|f}qtd|qWt|dtst|dks|d|kr|d}||}||=|S|d}|SdS(s
        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']
        itdefaultis-pop() got an unexpected keyword argument '%s'iN(RRRsRoR(RRtkwargsRRtindexR}tdefaultvalue((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytpops"


cCs||kr||S|SdS(si
        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
        N((RtkeytdefaultValue((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCsw|jj||x]|jjD]L\}}x=t|D]/\}\}}t||||k|| ['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(RtinsertRRRR(RRtinsStrRRRRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR2scCs|jj|dS(s
        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(Rtappend(Rtitem((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRFscCs0t|tr||7}n|jj|dS(s
        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(RsR Rtextend(Rtitemseq((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRTs

cCs|j2|jjdS(s7
        Clear all elements and results names.
        N(RRtclear(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRfscCsy||SWntk
r dSX||jkr}||jkrR|j|ddStg|j|D]}|d^qcSndSdS(NRrii(RRRR (RRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRms
+cCs|j}||7}|S(N(R(RtotherR}((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__add__{s
c	s|jrt|jfd}|jj}g|D]<\}}|D])}|t|d||df^qMq=}xJ|D]?\}}|||st](RR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRsRrcCsog}xb|jD]W}|r2|r2|j|nt|trT||j7}q|jt|qW|S(N(RRRsR t
_asStringListR(RtseptoutR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCs5g|jD]'}t|tr+|jn|^q
S(s
        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']
        (RRsR R(Rtres((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscsGtr|j}n	|j}fdtfd|DS(s
        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"}
        csMt|trE|jr%|jSg|D]}|^q,Sn|SdS(N(RsR RtasDict(R|R(ttoItem(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs

 c3s'|]\}}||fVqdS(N((RRR(R(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	s(tPY_3RRR(Rtitem_fn((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
		cCsPt|j}|jj|_|j|_|jj|j|j|_|S(sA
        Returns a new copy of a C{ParseResults} object.
        (R RRRRRR
R(RR}((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCsd}g}td|jjD}|d}|sPd}d}d}nd	}	|d	k	rk|}	n|jr|j}	n|	s|rdSd}	n|||d|	dg7}x	t|jD]\}
}t|trI|
|kr||j	||
|o|d	k||g7}q||j	d	|o6|d	k||g7}qd	}|
|krh||
}n|s|rzqqd}nt
t|}
|||d|d|
d|dg	7}qW|||d|	dg7}dj|S(
s
        (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names.
        s
css2|](\}}|D]}|d|fVqqdS(iN((RRRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	s	s  RrtITEMtsgss
%s%s- %s: s  icss|]}t|tVqdS(N(RsR (Rtvv((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	sss
%s%s[%d]:
%s%s%sRr(
RRRRtsortedRRsR tdumpRtanyRR(RR$tdepthtfullRtNLRRRRR1((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR3Ps, B?cOstj|j||dS(s
        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(tpprintR(RRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR8}scCsC|j|jj|jdk	r-|jp0d|j|jffS(N(RRRRRRR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__getstate__s
cCsm|d|_|d\|_}}|_i|_|jj||dk	r`t||_n	d|_dS(Nii(RRRRR
RRR(RtstateR/tinAccumNames((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__setstate__s
	cCs|j|j|j|jfS(N(RRRR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__getnewargs__scCs tt|t|jS(N(RRRR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRsN(6RRRRRRRsRRRRRRRt__nonzero__RRRRRRRRRRRRRRRRRRRRR
RRRRRRRRRR!R-R0R3R8R9R<R=R(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR -sh&	'		
														4												#	=		%-			
	cCsW|}d|ko#t|knr@||ddkr@dS||jdd|S(sReturns 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.
   iis
(Rtrfind(RtstrgR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR7s
cCs|jdd|dS(sReturns 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.
   s
ii(tcount(RR@((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRHs
cCsR|jdd|}|jd|}|dkrB||d|!S||dSdS(sfReturns the line of text containing loc within a string, counting newlines as line separators.
       s
iiN(R?tfind(RR@tlastCRtnextCR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyREs
cCsAdt|dt|dt||t||fGHdS(NsMatch s at loc s(%d,%d)(RRHR7(tinstringRtexpr((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_defaultStartDebugActionscCs'dt|dt|jGHdS(NsMatched s -> (RRuR(REtstartloctendlocRFttoks((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_defaultSuccessDebugActionscCsdt|GHdS(NsException raised:(R(RERRFtexc((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_defaultExceptionDebugActionscGsdS(sG'Do-nothing' debug action, to suppress debugging output during parsing.N((R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyROsicstkrfdSdgtgtd dkrVdd}ddntj}tjd}|d	dd
}|d|d|ffd}d
}y"tdtdj}Wntk
rt	}nX||_|S(Ncs
|S(N((RtlRp(tfunc(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRriiiicSsJtdkrdnd}tjd||d|}|j|jfgS(	Niiiiitlimiti(iii(tsystem_versiont	tracebackt
extract_stacktfilenameRH(RPRt
frame_summary((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRSscSs2tj|d|}|d}|j|jfgS(NRPi(RRt
extract_tbRTRH(ttbRPtframesRU((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRVs
iRPiicsxy&|d}td<|SWqtk
rdrInAz:tjd}|dddd ksnWd~Xdkrdcd7Rt	__class__(ii(
tsingleArgBuiltinsRRQRRRSRVtgetattrRt	ExceptionRu(ROR[RSt	LINE_DIFFt	this_lineR]t	func_name((RVRZRORPR[R\sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_trim_aritys*
					
	cBseZdZdZeZedZedZedZ	dZ
dZedZe
dZd	Zd
ZdZdZd
ZdZe
dZdZe
e
dZdZdZdefdYZedFk	rdefdYZndefdYZiZe Z!ddgZ"e
e
dZ#eZ$edZ%eZ&eddZ'edZ(e)edZ*d Z+e)d!Z,e)ed"Z-d#Z.d$Z/d%Z0d&Z1d'Z2d(Z3d)Z4d*Z5d+Z6d,Z7d-Z8d.Z9d/Z:dFd0Z;d1Z<d2Z=d3Z>d4Z?d5Z@d6ZAe
d7ZBd8ZCd9ZDd:ZEd;ZFgd<ZGed=ZHd>ZId?ZJd@ZKdAZLdBZMe
dCZNe
dDe
e
edEZORS(Gs)Abstract base level parser element class.s 
	
cCs
|t_dS(s
        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"tDEFAULT_WHITE_CHARS(tchars((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetDefaultWhitespaceChars=s
cCs
|t_dS(s
        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"t_literalStringClass(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytinlineLiteralsUsingLscCst|_d|_d|_d|_||_t|_t	j
|_t|_t
|_t
|_t|_t
|_t
|_t|_d|_t|_d|_d|_t|_t
|_dS(NRr(NNN(RtparseActionRt
failActiontstrReprtresultsNamet
saveAsListRtskipWhitespaceR"Rft
whiteCharstcopyDefaultWhiteCharsRtmayReturnEmptytkeepTabstignoreExprstdebugtstreamlinedt
mayIndexErrorterrmsgtmodalResultstdebugActionstretcallPreparset
callDuringTry(Rtsavelist((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRas(																cCsEtj|}|j|_|j|_|jrAtj|_n|S(s$
        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")
        (RRkRuRrR"RfRq(Rtcpy((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRxs

	cCs>||_d|j|_t|dr:|j|j_n|S(sf
        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)
        s	Expected t	exception(RRyRRR(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetNames
	cCsE|j}|jdr.|d }t}n||_||_|S(sP
        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")
        t*i(RtendswithRRnRz(RRtlistAllMatchestnewself((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetResultsNames
		
csa|r9|jttfd}|_||_n$t|jdr]|jj|_n|S(sMethod to invoke the Python pdb debugger when this element is
           about to be parsed. Set C{breakFlag} to True to enable, False to
           disable.
        cs)ddl}|j||||S(Ni(tpdbt	set_trace(RERt	doActionstcallPreParseR(t_parseMethod(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytbreakers
t_originalParseMethod(t_parseRRR(Rt	breakFlagR((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetBreaks		cOs7tttt||_|jdt|_|S(s
        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]
        R~(RtmapReRkRRR~(RtfnsR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRzs"cOsF|jtttt|7_|jp<|jdt|_|S(s
        Add parse action to expression's list of parse actions. See L{I{setParseAction}}.
        
        See examples in L{I{copy}}.
        R~(RkRRReR~RR(RRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytaddParseActions$cs|jdd|jdtr*tntx3|D]+fd}|jj|q7W|jp~|jdt|_|S(sAdd 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)
        tmessagesfailed user-defined conditiontfatalcs7tt|||s3||ndS(N(RRe(RRNRp(texc_typetfnR(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytpasR~(RRRRRkRR~(RRRR((RRRsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytaddConditions
cCs
||_|S(sDefine 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.(Rl(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt
setFailActions
	cCsnt}xa|rit}xN|jD]C}y)x"|j||\}}t}q+WWqtk
raqXqWq	W|S(N(RRRuRR(RRERt
exprsFoundtetdummy((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_skipIgnorables#s	
cCsp|jr|j||}n|jrl|j}t|}x-||krh|||krh|d7}q?Wn|S(Ni(RuRRpRqR(RRERtwttinstrlen((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytpreParse0s			cCs
|gfS(N((RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt	parseImpl<scCs|S(N((RRERt	tokenlist((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt	postParse?sc	Cs|j}|s|jr,|jdr?|jd|||n|rc|jrc|j||}n|}|}yUy|j|||\}}Wn/tk
rt|t||j	|nXWqt
k
r(}	|jdr|jd||||	n|jr"|j||||	nqXn|rP|jrP|j||}n|}|}|jsw|t|kry|j|||\}}Wqtk
rt|t||j	|qXn|j|||\}}|j|||}t
||jd|jd|j}
|jrf|s7|jrf|ryrxk|jD]`}||||
}|dk	rJt
||jd|jot|t
tfd|j}
qJqJWWqct
k
r}	|jdr|jd||||	nqcXqfxn|jD]`}||||
}|dk	rt
||jd|joMt|t
tfd|j}
qqWn|r|jdr|jd|||||
qn||
fS(NiiRRi(RvRlR{R}RRRRRRyRRxRR RnRoRzRkR~RRsR(RRERRRt	debuggingtprelocttokensStartttokensterrt	retTokensR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt
_parseNoCacheCsp	

&
	

%$	

	
#cCsNy|j||dtdSWn)tk
rIt|||j|nXdS(NRi(RRRRRy(RRER((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyttryParses
cCs7y|j||Wnttfk
r.tSXtSdS(N(RRRRR(RRER((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytcanParseNexts
t_UnboundedCachecBseZdZRS(csit|_fd}fd}fd}tj|||_tj|||_tj|||_dS(Ncsj|S(N(R(RR(tcachetnot_in_cache(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscs||})
         - 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
        iN(
R"RRwt
streamlineRuRtt
expandtabsRRRR'Rtverbose_stacktrace(RREtparseAllRRRtseRL((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytparseString#s$
	
		
ccs|js|jnx|jD]}|jq W|jsRt|j}nt|}d}|j}|j}t	j
d}	yx||kra|	|kray.|||}
|||
dt\}}Wntk
r|
d}qX||krT|	d7}	||
|fV|rK|||}
|
|kr>|}qQ|d7}q^|}q|
d}qWWn(t
k
r}t	jrq|nXdS(s
        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
        iRiN(RwRRuRtRRRRRR"RRRRR(RREt
maxMatchestoverlapRRRt
preparseFntparseFntmatchesRtnextLocRtnextlocRL((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt
scanStringUsB	
			


	
		c	Cs%g}d}t|_yx|j|D]}\}}}|j|||!|rt|trs||j7}qt|tr||7}q|j|n|}q(W|j||g|D]}|r|^q}djt	t
t|SWn(tk
r }t
jrq!|nXdS(sf
        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.
        iRrN(RRtRRRsR RRRRRt_flattenRR"R(	RRERtlastERpRRtoRL((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR{s(	

 	cCsey6tg|j||D]\}}}|^qSWn(tk
r`}tjrWqa|nXdS(s~
        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']
        N(R RRR"R(RRERRpRRRL((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsearchStrings6	c	csfd}d}xJ|j|d|D]3\}}}|||!V|rO|dVn|}q"W||VdS(s[
        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', '']
        iRN(R(	RREtmaxsplittincludeSeparatorstsplitstlastRpRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
%
cCsdt|tr!tj|}nt|tsTtjdt|tdddSt	||gS(s
        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', '!']
        s4Cannot combine element of type %s with ParserElementt
stackleveliN(
RsRR"RitwarningstwarnRt
SyntaxWarningRR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
s
cCs\t|tr!tj|}nt|tsTtjdt|tdddS||S(s]
        Implementation of + operator when left operand is not a C{L{ParserElement}}
        s4Cannot combine element of type %s with ParserElementRiN(	RsRR"RiRRRRR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
cCsmt|tr!tj|}nt|tsTtjdt|tdddSt	|t	j
|gS(sQ
        Implementation of - operator, returns C{L{And}} with error stop
        s4Cannot combine element of type %s with ParserElementRiN(RsRR"RiRRRRRRt
_ErrorStop(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__sub__s
cCs\t|tr!tj|}nt|tsTtjdt|tdddS||S(s]
        Implementation of - operator when left operand is not a C{L{ParserElement}}
        s4Cannot combine element of type %s with ParserElementRiN(	RsRR"RiRRRRR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__rsub__ s
csEt|tr|d}}n-t|tr7|dd }|dd
kr_d|df}nt|dtr|dd
kr|ddkrtS|ddkrtS|dtSqLt|dtrt|dtr|\}}||8}qLtdt|dt|dntdt||dkrgtdn|dkrtdn||kodknrtdn|rfd	|r
|dkr|}qt	g||}qA|}n(|dkr.}nt	g|}|S(s
        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}
        iiis7cannot multiply 'ParserElement' and ('%s','%s') objectss0cannot multiply 'ParserElement' and '%s' objectss/cannot multiply ParserElement by negative values@second tuple value must be greater or equal to first tuple values+cannot multiply ParserElement by 0 or (0,0)cs2|dkr$t|dStSdS(Ni(R(tn(tmakeOptionalListR(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR]sN(NN(
RsRottupleRR0RRRt
ValueErrorR(RR	tminElementstoptElementsR}((RRsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__mul__,sD#

&
) 	cCs
|j|S(N(R(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__rmul__pscCsdt|tr!tj|}nt|tsTtjdt|tdddSt	||gS(sI
        Implementation of | operator - returns C{L{MatchFirst}}
        s4Cannot combine element of type %s with ParserElementRiN(
RsRR"RiRRRRRR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__or__ss
cCs\t|tr!tj|}nt|tsTtjdt|tdddS||BS(s]
        Implementation of | operator when left operand is not a C{L{ParserElement}}
        s4Cannot combine element of type %s with ParserElementRiN(	RsRR"RiRRRRR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__ror__s
cCsdt|tr!tj|}nt|tsTtjdt|tdddSt	||gS(sA
        Implementation of ^ operator - returns C{L{Or}}
        s4Cannot combine element of type %s with ParserElementRiN(
RsRR"RiRRRRRR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__xor__s
cCs\t|tr!tj|}nt|tsTtjdt|tdddS||AS(s]
        Implementation of ^ operator when left operand is not a C{L{ParserElement}}
        s4Cannot combine element of type %s with ParserElementRiN(	RsRR"RiRRRRR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__rxor__s
cCsdt|tr!tj|}nt|tsTtjdt|tdddSt	||gS(sC
        Implementation of & operator - returns C{L{Each}}
        s4Cannot combine element of type %s with ParserElementRiN(
RsRR"RiRRRRRR
(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__and__s
cCs\t|tr!tj|}nt|tsTtjdt|tdddS||@S(s]
        Implementation of & operator when left operand is not a C{L{ParserElement}}
        s4Cannot combine element of type %s with ParserElementRiN(	RsRR"RiRRRRR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__rand__s
cCs
t|S(sE
        Implementation of ~ operator - returns C{L{NotAny}}
        (R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt
__invert__scCs'|dk	r|j|S|jSdS(s

        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(RRR(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__call__s
cCs
t|S(s
        Suppresses the output of this C{ParserElement}; useful to keep punctuation from
        cluttering up returned output.
        (R)(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsuppressscCs
t|_|S(s
        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.
        (RRp(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytleaveWhitespaces	cCst|_||_t|_|S(s8
        Overrides the default whitespace chars
        (RRpRqRRr(RRg((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetWhitespaceCharss			cCs
t|_|S(s
        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.
        (RRt(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt
parseWithTabss	cCsrt|trt|}nt|trR||jkrn|jj|qnn|jjt|j|S(s
        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']
        (RsRR)RuRR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytignores
cCs1|p	t|pt|ptf|_t|_|S(sT
        Enable display of debugging messages while doing pattern matching.
        (RGRKRMR{RRv(RtstartActiont
successActiontexceptionAction((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetDebugActions
s
			cCs)|r|jtttn	t|_|S(s
        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...)"}.
        (RRGRKRMRRv(Rtflag((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetDebugs#	cCs|jS(N(R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR@scCs
t|S(N(R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRCscCst|_d|_|S(N(RRwRRm(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRFs		cCsdS(N((RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytcheckRecursionKscCs|jgdS(sj
        Check defined expressions for valid structure, check for infinite recursive definitions.
        N(R(Rt
validateTrace((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytvalidateNscCsy|j}Wn5tk
rGt|d}|j}WdQXnXy|j||SWn(tk
r}tjr}q|nXdS(s
        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.
        trN(treadRtopenRRR"R(Rtfile_or_filenameRt
file_contentstfRL((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt	parseFileTs
	cCsdt|tr1||kp0t|t|kSt|trM|j|Stt||kSdS(N(RsR"tvarsRRtsuper(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__eq__hs
"
cCs||kS(N((RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__ne__pscCstt|S(N(thashtid(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__hash__sscCs
||kS(N((RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__req__vscCs||kS(N((RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__rne__yscCs:y!|jt|d|tSWntk
r5tSXdS(s
        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")
        RN(RRRRR(Rt
testStringR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR|s


t#cCsyt|tr6tttj|jj}nt|trTt|}ng}g}t	}	x|D]}
|dk	r|j|
ts|r|
r|j
|
qmn|
sqmndj||
g}g}yQ|
jdd}
|j|
d|}|j
|jd||	o%|}	Wntk
r}
t|
trPdnd}d|
kr|j
t|
j|
|j
dt|
j|
dd	|n|j
d|
jd	||j
d
t|
|	o|}	|
}n<tk
r*}|j
dt||	o|}	|}nX|rX|rG|j
dndj|GHn|j
|
|fqmW|	|fS(
s3
        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'.)
        s
s\nRR6s(FATAL)Rrt it^sFAIL: sFAIL-EXCEPTION: N(RsRRRRuRtrstript
splitlinesRRRRRRRRRR3RRRERR7Ra(RttestsRtcommenttfullDumptprintResultstfailureTestst
allResultstcommentstsuccessRpRtresultRRRL((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytrunTestssNW'
+
,	
N(PRRRRfRRtstaticmethodRhRjRRRRRRRzRRRRRRRRRRRRRRRRRRRRRRRRRt_MAX_INTRR{RRR
RRRRRRRRRRRRRRRRRRRRRRRRRR	RR
RRRRR"(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR"8s			&	
		
	
		H			"2G	+					D																	
)									cBseZdZdZRS(sT
    Abstract C{ParserElement} subclass, for defining atomic matching patterns.
    cCstt|jdtdS(NR(RR*RR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR	s(RRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR*	scBseZdZdZRS(s,
    An empty token, will always match.
    cCs2tt|jd|_t|_t|_dS(NR(RRRRRRsRRx(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR	s		(RRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR	scBs#eZdZdZedZRS(s(
    A token that will never match.
    cCs;tt|jd|_t|_t|_d|_dS(NRsUnmatchable token(	RRRRRRsRRxRy(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR*	s
			cCst|||j|dS(N(RRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR1	s(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR&	s	cBs#eZdZdZedZRS(s
    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}.
    cCstt|j||_t||_y|d|_Wn0tk
rntj	dt
ddt|_nXdt
|j|_d|j|_t|_t|_dS(Nis2null string passed to Literal; use Empty() insteadRis"%s"s	Expected (RRRtmatchRtmatchLentfirstMatchCharRRRRRR^RRRyRRsRx(RtmatchString((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRC	s	
	

	cCsg|||jkrK|jdks7|j|j|rK||j|jfSt|||j|dS(Ni(R'R&t
startswithR%RRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRV	s$(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR5	s
	cBsKeZdZedZdedZedZ	dZ
edZRS(s\
    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}.
    s_$cCstt|j|dkr+tj}n||_t||_y|d|_Wn't	k
r}t
jdtddnXd|j|_
d|j
|_t|_t|_||_|r|j|_|j}nt||_dS(Nis2null string passed to Keyword; use Empty() insteadRis"%s"s	Expected (RRRRtDEFAULT_KEYWORD_CHARSR%RR&R'RRRRRRyRRsRxtcaselesstuppert
caselessmatchRt
identChars(RR(R.R+((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRq	s&	
				cCsb|jr||||j!j|jkrF|t||jkse|||jj|jkrF|dks||dj|jkrF||j|jfSn|||jkrF|jdks|j|j|rF|t||jks|||j|jkrF|dks2||d|jkrF||j|jfSt	|||j
|dS(Nii(R+R&R,R-RR.R%R'R)RRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR	s	#9)$3#cCs%tt|j}tj|_|S(N(RRRR*R.(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR	scCs
|t_dS(s,Overrides the default Keyword chars
        N(RR*(Rg((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetDefaultKeywordChars	sN(
RRRR1R*RRRRRRR#R/(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR^	s
	cBs#eZdZdZedZRS(sl
    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}.)
    cCsItt|j|j||_d|j|_d|j|_dS(Ns'%s's	Expected (RRRR,treturnStringRRy(RR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR	s	cCsS||||j!j|jkr7||j|jfSt|||j|dS(N(R&R,R%R0RRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR	s#(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR	s
	cBs&eZdZddZedZRS(s
    Caseless version of L{Keyword}.

    Example::
        OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD']
        
    (Contrast with example for L{CaselessLiteral}.)
    cCs#tt|j||dtdS(NR+(RRRR(RR(R.((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR	scCs||||j!j|jkrp|t||jks\|||jj|jkrp||j|jfSt|||j|dS(N(R&R,R-RR.R%RRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR	s#9N(RRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR	scBs&eZdZddZedZRS(sx
    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']})
    icCs]tt|j||_||_||_d|j|jf|_t|_t|_	dS(Ns&Expected %r (with up to %d mismatches)(
RRjRRtmatch_stringt
maxMismatchesRyRRxRs(RR1R2((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR	s				cCs|}t|}|t|j}||kr|j}d}g}	|j}
xtt|||!|jD]J\}}|\}}
||
kro|	j|t|	|
krPqqoqoW|d}t|||!g}|j|d<|	|d<||fSnt|||j|dS(Niitoriginalt
mismatches(	RR1R2RRRR RRy(RRERRtstartRtmaxlocR1tmatch_stringlocR4R2ts_mtsrctmattresults((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR	s(		,




(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRj	s	cBs>eZdZddddeddZedZdZRS(s	
    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=",")
    iicstt|jrcdjfd|D}|rcdjfd|D}qcn||_t||_|r||_t||_n||_t||_|dk|_	|dkrt
dn||_|dkr||_n	t
|_|dkr)||_||_nt||_d|j|_t|_||_d|j|jkr}|dkr}|dkr}|dkr}|j|jkrd	t|j|_net|jdkrd
tj|jt|jf|_n%dt|jt|jf|_|jrDd|jd|_nytj|j|_Wq}tk
ryd|_q}XndS(
NRrc3s!|]}|kr|VqdS(N((RR(texcludeChars(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	7
sc3s!|]}|kr|VqdS(N((RR(R<(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	9
siisZcannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitteds	Expected Rs[%s]+s%s[%s]*s	[%s][%s]*s\b(RR-RRt
initCharsOrigRt	initCharst
bodyCharsOrigt	bodyCharstmaxSpecifiedRtminLentmaxLenR$RRRyRRxt	asKeywordt_escapeRegexRangeCharstreStringRR|tescapetcompileRaR(RR>R@tmintmaxtexactRDR<((R<sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR4
sT%								:	
c
Cs|jr[|jj||}|s?t|||j|n|j}||jfS|||jkrt|||j|n|}|d7}t|}|j}||j	}t
||}x*||kr|||kr|d7}qWt}	|||jkrt
}	n|jrG||krG|||krGt
}	n|jr|dkrp||d|ks||kr|||krt
}	qn|	rt|||j|n||||!fS(Nii(R|R%RRytendtgroupR>RR@RCRIRRBRRARD(
RRERRR!R5Rt	bodycharsR6tthrowException((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRj
s6	
	
	%		<cCsytt|jSWntk
r*nX|jdkrd}|j|jkr}d||j||jf|_qd||j|_n|jS(NcSs&t|dkr|d dS|SdS(Nis...(R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt
charsAsStr
ss	W:(%s,%s)sW:(%s)(RR-RRaRmRR=R?(RRP((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
s
	(N(	RRRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR-
s.6#cBsDeZdZeejdZddZedZ	dZ
RS(s
    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})")
    s[A-Z]icCs3tt|jt|tr|sAtjdtddn||_||_	y+t
j|j|j	|_
|j|_Wqt
jk
rtjd|tddqXnIt|tjr||_
t||_|_||_	ntdt||_d|j|_t|_t|_dS(sThe 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.s0null string passed to Regex; use Empty() insteadRis$invalid pattern (%s) passed to RegexsCRegex may only be constructed with a string or a compiled RE objects	Expected N(RR%RRsRRRRtpatterntflagsR|RHRFt
sre_constantsterrortcompiledREtypeRuRRRRyRRxRRs(RRQRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
s.			


		cCs|jj||}|s6t|||j|n|j}|j}t|j}|rx|D]}||||eZdZddeededZedZdZRS(s
    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']]
    c	sttj|j}|sGtjdtddtn|dkr\|}n4|j}|stjdtddtn|_	t
|_|d_|_
t
|_|_|_|_|_|rTtjtjB_dtjj	tj
d|dk	rDt|pGdf_nPd_dtjj	tj
d|dk	rt|pdf_t
j
d	krjd
djfdtt
j
d	dd
Dd7_n|r*jdtj|7_n|rhjdtj|7_tjjd_njdtjj
7_y+tjjj_j_Wn4tj k
rtjdjtddnXt!_"dj"_#t$_%t&_'dS(Ns$quoteChar cannot be the empty stringRis'endQuoteChar cannot be the empty stringis%s(?:[^%s%s]Rrs%s(?:[^%s\n\r%s]is|(?:s)|(?:c3s<|]2}dtjj| tj|fVqdS(s%s[^%s]N(R|RGtendQuoteCharRE(RR(R(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	/sit)s|(?:%s)s|(?:%s.)s(.)s)*%ss$invalid pattern (%s) passed to Regexs	Expected ((RR#RRRRRtSyntaxErrorRt	quoteCharRtquoteCharLentfirstQuoteCharRXtendQuoteCharLentescChartescQuotetunquoteResultstconvertWhitespaceEscapesR|t	MULTILINEtDOTALLRRRGRERQRRtescCharReplacePatternRHRFRSRTRRRyRRxRRs(RR[R_R`t	multilineRaRXRb((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRsf		
					(	%E
	c	CsT|||jkr(|jj||p+d}|sOt|||j|n|j}|j}|jrJ||j	|j
!}t|trJd|kr|j
ridd6dd6dd6dd	6}x/|jD]\}}|j||}qWn|jr tj|jd
|}n|jrG|j|j|j}qGqJn||fS(Ns\s	s\ts
s\nss\fs
s\rs\g<1>(R]R|R%RRRyRLRMRaR\R^RsRRbRRR_RReR`RX(	RRERRR!R}tws_maptwslittwschar((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRGs*.	
		!cCs]ytt|jSWntk
r*nX|jdkrVd|j|jf|_n|jS(Ns.quoted string, starting with %s ending with %s(RR#RRaRmRR[RX(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRjs
N(	RRRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR#
sA#cBs5eZdZddddZedZdZRS(s
    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']
    iicCstt|jt|_||_|dkr@tdn||_|dkra||_n	t	|_|dkr||_||_nt
||_d|j|_|jdk|_
t|_dS(Nisfcannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permittedis	Expected (RRRRRptnotCharsRRBRCR$RRRyRsRx(RRjRIRJRK((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs 					cCs|||jkr.t|||j|n|}|d7}|j}t||jt|}x*||kr|||kr|d7}qfW|||jkrt|||j|n||||!fS(Ni(RjRRyRIRCRRB(RRERRR5tnotcharstmaxlen((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
	cCsytt|jSWntk
r*nX|jdkryt|jdkrfd|jd |_qyd|j|_n|jS(Nis
!W:(%s...)s!W:(%s)(RRRRaRmRRRj(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
(RRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRvscBsXeZdZidd6dd6dd6dd6d	d
6Zddd
d
dZedZRS(s
    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.
    sRss	ss
ss
sss 	
iicsttj|_jdjfdjDdjdjD_t_	dj_
|_|dkr|_n	t
_|dkr|_|_ndS(NRrc3s$|]}|jkr|VqdS(N(t
matchWhite(RR(R(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	scss|]}tj|VqdS(N(R,t	whiteStrs(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	ss	Expected i(RR,RRmRRRqRRRsRyRBRCR$(RtwsRIRJRK((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs	)				cCs|||jkr.t|||j|n|}|d7}||j}t|t|}x-||kr|||jkr|d7}qcW|||jkrt|||j|n||||!fS(Ni(RmRRyRCRIRRB(RRERRR5R6((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs

"(RRRRnRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR,s
t_PositionTokencBseZdZRS(cCs8tt|j|jj|_t|_t|_	dS(N(
RRpRR^RRRRsRRx(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs	(RRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRpscBs,eZdZdZdZedZRS(sb
    Token to advance to a specific column of input text; useful for tabular report scraping.
    cCs tt|j||_dS(N(RRRR7(Rtcolno((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCst|||jkrt|}|jrB|j||}nxE||kr||jrt|||jkr|d7}qEWn|S(Ni(R7RRuRtisspace(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs	7cCs^t||}||jkr6t||d|n||j|}|||!}||fS(NsText not in expected column(R7R(RRERRtthiscoltnewlocR}((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
(RRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs			cBs#eZdZdZedZRS(s
    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']    

    cCs tt|jd|_dS(NsExpected start of line(RRRRy(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR&scCs;t||dkr|gfSt|||j|dS(Ni(R7RRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR*s
(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs	cBs#eZdZdZedZRS(sU
    Matches if current position is at the end of a line within the parse string
    cCs<tt|j|jtjjddd|_dS(Ns
RrsExpected end of line(RRRRR"RfRRy(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR3scCs|t|krK||dkr0|ddfSt|||j|n8|t|krk|dgfSt|||j|dS(Ns
i(RRRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR8s(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR/s	cBs#eZdZdZedZRS(sM
    Matches if current position is at the beginning of the parse string
    cCs tt|jd|_dS(NsExpected start of text(RR(RRy(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRGscCsL|dkrB||j|dkrBt|||j|qBn|gfS(Ni(RRRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRKs(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR(Cs	cBs#eZdZdZedZRS(sG
    Matches if current position is at the end of the parse string
    cCs tt|jd|_dS(NsExpected end of text(RR'RRy(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRVscCs|t|kr-t|||j|nT|t|krM|dgfS|t|kri|gfSt|||j|dS(Ni(RRRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRZs
(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR'Rs	cBs&eZdZedZedZRS(sp
    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.
    cCs/tt|jt||_d|_dS(NsNot at the start of a word(RR/RRt	wordCharsRy(RRu((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRlscCs^|dkrT||d|jks6|||jkrTt|||j|qTn|gfS(Nii(RuRRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqs
(RRRRTRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR/dscBs&eZdZedZedZRS(sZ
    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.
    cCs8tt|jt||_t|_d|_dS(NsNot at the end of a word(RR.RRRuRRpRy(RRu((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs	cCsvt|}|dkrl||krl|||jksN||d|jkrlt|||j|qln|gfS(Nii(RRuRRy(RRERRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs(RRRRTRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR.xscBsqeZdZedZdZdZdZdZdZ	dZ
edZgd	Zd
Z
RS(s^
    Abstract subclass of ParserElement, for combining and post-processing parsed tokens.
    cCstt|j|t|tr4t|}nt|tr[tj|g|_	nt|t
jrt|}td|Drt
tj|}nt||_	n3yt||_	Wntk
r|g|_	nXt|_dS(Ncss|]}t|tVqdS(N(RsR(RRF((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	s(RRRRsRRRR"RitexprsRtIterabletallRRRR}(RRvR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
cCs|j|S(N(Rv(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCs|jj|d|_|S(N(RvRRRm(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs	cCsPt|_g|jD]}|j^q|_x|jD]}|jq8W|S(s~Extends C{leaveWhitespace} defined in base class, and also invokes C{leaveWhitespace} on
           all contained expressions.(RRpRvRR(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
	%cCst|trb||jkrtt|j|x(|jD]}|j|jdq>Wqn>tt|j|x%|jD]}|j|jdqW|S(Ni(RsR)RuRRRRv(RR	R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCsfytt|jSWntk
r*nX|jdkr_d|jjt|j	f|_n|jS(Ns%s:(%s)(
RRRRaRmRR^RRRv(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
%cCswtt|jx|jD]}|jqWt|jdkr`|jd}t||jr|jr|jdkr|j
r|j|jdg|_d|_|j|jO_|j
|j
O_
n|jd}t||jr`|jr`|jdkr`|j
r`|jd |j|_d|_|j|jO_|j
|j
O_
q`ndt||_|S(Niiiis	Expected (RRRRvRRsR^RkRnRRvRmRsRxRRy(RRR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs0


	


	cCstt|j||}|S(N(RRR(RRRR}((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCs@||g}x|jD]}|j|qW|jgdS(N(RvRR(RRttmpR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCs>tt|j}g|jD]}|j^q|_|S(N(RRRRv(RR}R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs%(RRRRRRRRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs						
	"cBsWeZdZdefdYZedZedZdZdZ	dZ
RS(s

    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")
    RcBseZdZRS(cOs3ttj|j||d|_|jdS(Nt-(RRRRRR(RRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
s	(RRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
scCsltt|j||td|jD|_|j|jdj|jdj|_t	|_
dS(Ncss|]}|jVqdS(N(Rs(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	
si(RRRRxRvRsRRqRpRR}(RRvR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
s
c	Cs?|jdj|||dt\}}t}x|jdD]}t|tjr`t}q<n|ry|j|||\}}Wqtk
rqtk
r}d|_
tj|qtk
rt|t
||j|qXn|j|||\}}|s$|jr<||7}q<q<W||fS(NiRi(RvRRRsRRRR!RRt
__traceback__RRRRyR(	RRERRt
resultlistt	errorStopRt
exprtokensR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
s((
	
%cCs.t|tr!tj|}n|j|S(N(RsRR"RiR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR5
scCs@||g}x+|jD] }|j||jsPqqWdS(N(RvRRs(RRtsubRecCheckListR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR:
s

	cCsVt|dr|jS|jdkrOddjd|jDd|_n|jS(NRt{Rcss|]}t|VqdS(N(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	F
st}(RRRmRRRv(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRA
s
*(RRRRRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs		cBsAeZdZedZedZdZdZdZ	RS(s
    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']]
    cCsNtt|j|||jrAtd|jD|_n	t|_dS(Ncss|]}|jVqdS(N(Rs(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	\
s(RRRRvR4RsR(RRvR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRY
s	cCsd}d}g}x|jD]}y|j||}Wntk
rw}	d|	_|	j|kr|	}|	j}qqtk
rt||krt|t||j|}t|}qqX|j	||fqW|rh|j
ddxn|D]c\}
}y|j|||SWqtk
r`}	d|	_|	j|kra|	}|	j}qaqXqWn|dk	r|j|_|nt||d|dS(NiRcSs	|dS(Ni((tx((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqu
Rrs no defined alternatives to match(
RRvRRR{RRRRyRtsortRR(RRERRt	maxExcLoctmaxExceptionRRtloc2Rt_((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR`
s<	
		cCs.t|tr!tj|}n|j|S(N(RsRR"RiR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__ixor__
scCsVt|dr|jS|jdkrOddjd|jDd|_n|jS(NRRs ^ css|]}t|VqdS(N(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	
sR(RRRmRRRv(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
s
*cCs3||g}x|jD]}|j|qWdS(N(RvR(RRRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
s(
RRRRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRK
s
&			cBsAeZdZedZedZdZdZdZ	RS(s
    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']]
    cCsNtt|j|||jrAtd|jD|_n	t|_dS(Ncss|]}|jVqdS(N(Rs(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	
s(RRRRvR4RsR(RRvR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
s	c	Csd}d}x|jD]}y|j|||}|SWqtk
ro}|j|kr|}|j}qqtk
rt||krt|t||j|}t|}qqXqW|dk	r|j|_|nt||d|dS(Nis no defined alternatives to match(	RRvRRRRRRyR(	RRERRRRRR}R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
s$
	cCs.t|tr!tj|}n|j|S(N(RsRR"RiR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__ior__
scCsVt|dr|jS|jdkrOddjd|jDd|_n|jS(NRRs | css|]}t|VqdS(N(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	
sR(RRRmRRRv(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
s
*cCs3||g}x|jD]}|j|qWdS(N(RvR(RRRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
s(
RRRRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR
s			cBs8eZdZedZedZdZdZRS(sm
    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
    cCsKtt|j||td|jD|_t|_t|_dS(Ncss|]}|jVqdS(N(Rs(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	s(	RR
RRxRvRsRRptinitExprGroups(RRvR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs	cCs4|jrLtd|jD|_g|jD]}t|tr/|j^q/}g|jD]%}|jr]t|tr]|^q]}|||_g|jD]}t|t	r|j^q|_
g|jD]}t|tr|j^q|_g|jD]$}t|tt	tfs|^q|_
|j
|j7_
t|_n|}|j
}|j}	g}
t}x|r_||	|j
|j}g}
x|D]}y|j||}Wntk
r|
j|qX|
j|jjt||||kr|j|q||	kr|	j|qqWt|
t|krut}ququW|rdjd|D}t||d|n|
g|jD]*}t|tr|j|	kr|^q7}
g}x6|
D].}|j|||\}}|j|qWt|tg}||fS(Ncss3|])}t|trt|j|fVqdS(N(RsRRRF(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	ss, css|]}t|VqdS(N(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	=ss*Missing one or more required elements (%s)(RRRvtopt1mapRsRRFRst	optionalsR0tmultioptionalsRt
multirequiredtrequiredRRRRRRRtremoveRRRtsumR (RRERRRtopt1topt2ttmpLocttmpReqdttmpOptt
matchOrdertkeepMatchingttmpExprstfailedtmissingR|R;tfinalResults((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRsP	.5
117

	

"
>
cCsVt|dr|jS|jdkrOddjd|jDd|_n|jS(NRRs & css|]}t|VqdS(N(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	PsR(RRRmRRRv(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRKs
*cCs3||g}x|jD]}|j|qWdS(N(RvR(RRRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRTs(RRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR

s
51		cBs_eZdZedZedZdZdZdZ	dZ
gdZdZRS(	sa
    Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens.
    cCstt|j|t|trattjtrItj|}qatjt	|}n||_
d|_|dk	r|j
|_
|j|_|j|j|j|_|j|_|j|_|jj|jndS(N(RRRRsRt
issubclassR"RiR*RRFRRmRxRsRRqRpRoR}RuR(RRFR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR^s		cCsG|jdk	r+|jj|||dtStd||j|dS(NRRr(RFRRRRRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRpscCs>t|_|jj|_|jdk	r:|jjn|S(N(RRpRFRRR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRvs
	cCst|trc||jkrtt|j||jdk	r`|jj|jdq`qn?tt|j||jdk	r|jj|jdn|S(Ni(RsR)RuRRRRFR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR}s cCs6tt|j|jdk	r2|jjn|S(N(RRRRFR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCsV||kr"t||gn||g}|jdk	rR|jj|ndS(N(R$RFRR(RRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
cCsA||g}|jdk	r0|jj|n|jgdS(N(RFRRR(RRRy((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCsuytt|jSWntk
r*nX|jdkrn|jdk	rnd|jjt	|jf|_n|jS(Ns%s:(%s)(
RRRRaRmRRFR^RR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
%(
RRRRRRRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRZs				cBs#eZdZdZedZRS(s
    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']]
    cCs#tt|j|t|_dS(N(RRRRRs(RRF((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCs|jj|||gfS(N(RFR(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs	cBs,eZdZdZedZdZRS(s
    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::
        
    cCsBtt|j|t|_t|_dt|j|_	dS(NsFound unwanted token, (
RRRRRpRRsRRFRy(RRF((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs		cCs:|jj||r0t|||j|n|gfS(N(RFRRRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCsIt|dr|jS|jdkrBdt|jd|_n|jS(NRs~{R(RRRmRRRF(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
(RRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
	t_MultipleMatchcBs eZddZedZRS(cCsftt|j|t|_|}t|trFtj|}n|dk	rY|nd|_
dS(N(RRRRRoRsRR"RiRt	not_ender(RRFtstopOntender((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs	cCs|jj}|j}|jdk	}|r9|jj}n|rO|||n||||dt\}}y|j}	xo|r|||n|	r|||}
n|}
|||
|\}}|s|jr~||7}q~q~WWnt	t
fk
rnX||fS(NR(RFRRRRRRRuRRR(RRERRtself_expr_parsetself_skip_ignorablestcheck_endert
try_not_enderRthasIgnoreExprsRt	tmptokens((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs,	N(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscBseZdZdZRS(s
    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()
    cCsIt|dr|jS|jdkrBdt|jd|_n|jS(NRRs}...(RRRmRRRF(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR!s
(RRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscBs/eZdZddZedZdZRS(sw
    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}
    cCs)tt|j|d|t|_dS(NR(RR0RRRs(RRFR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR6scCsEy tt|j|||SWnttfk
r@|gfSXdS(N(RR0RRR(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR:s cCsIt|dr|jS|jdkrBdt|jd|_n|jS(NRRs]...(RRRmRRRF(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR@s
N(RRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR0*st
_NullTokencBs eZdZeZdZRS(cCstS(N(R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRJscCsdS(NRr((R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRMs(RRRR>R(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRIs	cBs/eZdZedZedZdZRS(sa
    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)
    cCsAtt|j|dt|jj|_||_t|_dS(NR(	RRRRRFRoRRRs(RRFR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRts	cCsy(|jj|||dt\}}Wnottfk
r|jtk	r|jjrt|jg}|j||jj ['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...)
    RrcCsQtt|j||r)|jn||_t|_||_t|_dS(N(	RRRRtadjacentRRpt
joinStringR}(RRFRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRrs
			cCs6|jrtj||ntt|j||S(N(RR"RRR(RR	((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR|s	cCse|j}|2|tdj|j|jgd|j7}|jr]|jr]|gS|SdS(NRrR(RR RRRRzRnR(RRERRtretToks((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs1(RRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRas
	cBs eZdZdZdZRS(s
    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']]
    cCs#tt|j|t|_dS(N(RRRRRo(RRF((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCs|gS(N((RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs(RRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs
	cBs eZdZdZdZRS(sW
    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.
    cCs#tt|j|t|_dS(N(RR	RRRo(RRF((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCsTx9t|D]+\}}t|dkr1q
n|d}t|trct|dj}nt|dkrtd|||nX|S(ss
    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)
s< ['aa', 'bb', 'cc']
        delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE']
    s [Rs]...N(RRR0RR)(RFtdelimtcombinetdlName((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR>9s
,!cstfd}|dkrBttjd}n|j}|jd|j|dt|jdt	dS(s:
    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|p5tt>gS(Ni(RRRA(RRNRpR(t	arrayExprRF(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytcountFieldParseAction_s
-cSst|dS(Ni(Ro(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqdRrtarrayLenR~s(len) s...N(
R
RR-RPRzRRRRR(RFtintExprR((RRFsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR:Ls	
cCsMg}x@|D]8}t|tr8|jt|q
|j|q
W|S(N(RsRRRR(tLR}R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRks
csFtfd}|j|dtjdt|S(s*
    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.
    csc|rTt|dkr'|d>q_t|j}td|D>nt>dS(Niicss|]}t|VqdS(N(R(Rttt((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	s(RRRRR(RRNRpttflat(trep(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytcopyTokenToRepeatersR~s(prev) (R
RRRR(RFR((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRMts

	
cs\t|j}|Kfd}|j|dtjdt|S(sS
    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.
    cs8t|jfd}j|dtdS(Ncs7t|j}|kr3tdddndS(NRri(RRR(RRNRpttheseTokens(tmatchTokens(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytmustMatchTheseTokenssR~(RRRzR(RRNRpR(R(RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRsR~s(prev) (R
RRRRR(RFte2R((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRLs	
cCsUx$dD]}|j|t|}qW|jdd}|jdd}t|S(Ns\^-]s
s\ns	s\t(Rt_bslashR(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyREs

c
sD|r!d}d}tnd}d}tg}t|tr]|j}n7t|tjr~t|}ntj	dt
dd|stSd}x|t|d	krV||}xt
||d	D]f\}}	||	|r
|||d	=Pq|||	r|||d	=|j||	|	}PqqW|d	7}qW|r|ryt|td
j|krtdd
jd|Djd
j|Stdjd|Djd
j|SWqtk
rtj	dt
ddqXntfd|Djd
j|S(s
    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,(Rtb((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrcSs|jj|jS(N(R,R)(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrcSs
||kS(N((RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrcSs
|j|S(N(R)(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrs6Invalid argument to oneOf, expected string or iterableRiiiRrs[%s]css|]}t|VqdS(N(RE(Rtsym((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	ss | t|css|]}tj|VqdS(N(R|RG(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	ss7Exception creating Regex for oneOf, building MatchFirstc3s|]}|VqdS(N((RR(tparseElementClass(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	s(RRRsRRRRwRRRRRRRRRR%RRaR(
tstrsR+tuseRegextisequaltmaskstsymbolsRtcurRR	((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRQsL						

!
!33
	cCsttt||S(s
    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	R0R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR?s!cCs|tjd}|j}t|_|d||d}|rVd}n	d}|j||j|_|S(s
    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(N((RRRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRq8Rrt_original_startt
_original_endcSs||j|j!S(N(RR(RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRq=RrcSs'||jd|jd!g|(dS(NRR(R(RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytextractText?s(RRzRRR}Ru(RFtasStringt	locMarkertendlocMarkert	matchExprR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRe s		
cCst|jdS(sp
    Helper to undo pyparsing's default grouping of And expressions, even
    if all but one are non-empty.
    cSs|dS(Ni((Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqJRr(R+Rz(RF((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRfEscCsEtjd}t|d|d|jjdS(s
    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(N((RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRq`Rrt
locn_startRtlocn_end(RRzRRR(RFtlocator((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRhLss\[]-*.$+^?()~ RKcCs|ddS(Nii((RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqkRrs\\0?[xX][0-9a-fA-F]+cCs tt|djddS(Nis\0xi(tunichrRotlstrip(RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqlRrs	\\0[0-7]+cCstt|dddS(Niii(RRo(RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqmRrR<s\]s\wRzRRtnegatetbodyRcsOdy-djfdtj|jDSWntk
rJdSXdS(s
    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.)
    cSsKt|ts|Sdjdtt|dt|ddDS(NRrcss|]}t|VqdS(N(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	sii(RsR RRtord(tp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrRrc3s|]}|VqdS(N((Rtpart(t	_expanded(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	sN(Rt_reBracketExprRRRa(R((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR]rs
	-
csfd}|S(st
    Helper method for defining parse actions that require matching at a specific
    column in the input text.
    cs2t||kr.t||dndS(Nsmatched token not at column %d(R7R(R@tlocnRJ(R(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt	verifyCols((RR((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRKscs
fdS(s
    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(N((RRNRp(treplStr(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRr((R((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRZscCs|ddd!S(s
    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"]
    iii((RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRXscsafd}y"tdtdj}Wntk
rSt}nX||_|S(sG
    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']
    cs g|D]}|^qS(N((RRNRpttokn(RRO(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRsRR^(R`RRaRu(RORRRd((RROsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRks 	
	cCst|jS(N(RR,(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrcCst|jS(N(Rtlower(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrcCs<t|tr+|}t|d|}n	|j}tttd}|rtjj	t
}td|dtt
t|td|tddtgjdj	d	td
}ndjdtD}tjj	t
t|B}td|dtt
t|j	tttd|tddtgjdj	d
td
}ttd|d
}|jddj|jddjjjd|}|jddj|jddjjjd|}||_||_||fS(sRInternal helper to construct opening and closing tag expressions, given a tag nameR+s_-:Rttagt=t/RRAcSs|ddkS(NiR((RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrR Rrcss!|]}|dkr|VqdS(R N((RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys	scSs|ddkS(NiR((RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrsRLs(RsRRRR-R2R1R<RRzRXR)R	R0RRRRRRTRWR@Rt_LRttitleRRR(ttagStrtxmltresnamettagAttrNamettagAttrValuetopenTagtprintablesLessRAbracktcloseTag((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt	_makeTagss"	o{AA		cCs
t|tS(s 
    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
    (RR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRIscCs
t|tS(s
    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}
    (RR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRJscsT|r|n|jgD]\}}||f^q#fd}|S(s<
    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 csx~D]v\}}||kr8t||d|n|tjkr|||krt||d||||fqqWdS(Nsno matching attribute s+attribute '%s' has value '%s', must be '%s'(RRct ANY_VALUE(RRNRtattrNamet attrValue(tattrs(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRRs   (R(RtattrDictRRR((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRcs 2  %cCs'|rd|nd}ti||6S(s 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 s%s:classtclass(Rc(t classnamet namespacet classattr((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRi\s t(RYcCs<t}||||B}xt|D]\}}|d d \}} } } | dkrdd|nd|} | dkr|d kst|dkrtdn|\} }ntj| }| tjkr| dkr t||t |t |}q| dkrx|d k rQt|||t |t ||}qt||t |t |}q| dkrt|| |||t || |||}qtdn+| tj kr| dkr)t |t st |}nt|j|t ||}q| dkr|d k rpt|||t |t ||}qt||t |t |}q| dkrt|| |||t || |||}qtdn td | r |j| n||j| |BK}|}q(W||K}|S( s 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]]] iis%s terms %s%s termis@if numterms=3, opExpr must be a tuple or list of two expressionsis6operator must be unary (1), binary (2), or ternary (3)s2operator must indicate right or left associativityN(N(R RRRRRRRtLEFTR RRtRIGHTRsRRFRz(tbaseExprtopListtlpartrparR}tlastExprRtoperDeftopExprtaritytrightLeftAssocRttermNametopExpr1topExpr2tthisExprR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRgsR;    '  /'   $  /'     s4"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*t"s string enclosed in double quotess4'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*t's string enclosed in single quotess*quotedString using single or double quotestusunicode string literalcCs!||krtdn|d krt|trt|trt|dkrt|dkr|d k rtt|t||tj ddj d}q|t j t||tj j d}q|d k r9tt|t |t |ttj ddj d}qttt |t |ttj ddj d}qtdnt}|d k r|tt|t||B|Bt|K}n.|tt|t||Bt|K}|jd ||f|S( s~ 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']] s.opening and closing strings cannot be the sameiRKcSs|djS(Ni(R(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRq9RrcSs|djS(Ni(R(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRq<RrcSs|djS(Ni(R(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqBRrcSs|djS(Ni(R(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqFRrsOopening and closing arguments must be strings if no content expression is givensnested %s%s expressionN(RRRsRRRRRR"RfRzRARRR RR)R0R(topenertclosertcontentRR}((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRNs4:  $  $    5.c s5fd}fd}fd}ttjdj}ttj|jd}tj|jd}tj|jd} |rtt||t|t|t|| } n0tt|t|t|t|} |j t t| jdS( s 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']]]]]]] css|t|krdSt||}|dkro|dkrZt||dnt||dndS(Nisillegal nestingsnot a peer entry(RR7RR(RRNRptcurCol(t indentStack(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytcheckPeerIndentscsEt||}|dkr/j|nt||ddS(Nisnot a subentry(R7RR(RRNRpR+(R,(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytcheckSubIndentscsn|t|krdSt||}oH|dkoH|dks`t||dnjdS(Niisnot an unindent(RR7RR(RRNRpR+(R,(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt checkUnindents &s tINDENTRrtUNINDENTsindented block( RRRRR RzRRRRR( tblockStatementExprR,R$R-R.R/R7R0tPEERtUNDENTtsmExpr((R,sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRdQsN"8 $s#[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]s[\0xa1-\0xbf\0xd7\0xf7]s_:sany tagsgt lt amp nbsp quot aposs><& "'s &(?PRs);scommon HTML entitycCstj|jS(sRHelper parser action to replace common HTML entities with their special characters(t_htmlEntityMapRtentity(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRYss/\*(?:[^*]|\*(?!/))*s*/sC style commentss HTML comments.*s rest of lines//(?:\\\n|[^\n])*s // commentsC++ style comments#.*sPython style comments t commaItemRcBseZdZeeZeeZee j dj eZ ee j dj eedZedj dj eZej edej ej dZejdeeeed jeBj d Zejeed j d j eZed j dj eZeeBeBjZedj dj eZeededj dZedj dZedj dZ e de dj dZ!ee de d8dee de d9j dZ"e"j#ddej d Z$e%e!e$Be"Bj d!j d!Z&ed"j d#Z'e(d$d%Z)e(d&d'Z*ed(j d)Z+ed*j d+Z,ed,j d-Z-e.je/jBZ0e(d.Z1e%e2e3d/e4ee5d0d/ee6d1jj d2Z7e8ee9j:e7Bd3d4j d5Z;e(ed6Z<e(ed7Z=RS(:s 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')] tintegers hex integeris[+-]?\d+ssigned integerRtfractioncCs|d|dS(Nii((Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrRzs"fraction or mixed integer-fractions [+-]?\d+\.\d*s real numbers+[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)s$real number with scientific notations[+-]?\d+\.?\d*([eE][+-]?\d+)?tfnumberRt identifiersK(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}s IPv4 addresss[0-9a-fA-F]{1,4}t hex_integerRisfull IPv6 addressiis::sshort IPv6 addresscCstd|DdkS(Ncss'|]}tjj|rdVqdS(iN(Rlt _ipv6_partR(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys si(R(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrs::ffff:smixed IPv6 addresss IPv6 addresss:[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}s MAC addresss%Y-%m-%dcsfd}|S(s 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)] csPytj|djSWn+tk rK}t||t|nXdS(Ni(RtstrptimetdateRRRu(RRNRptve(tfmt(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytcvt_fns((RBRC((RBsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt convertToDatess%Y-%m-%dT%H:%M:%S.%fcsfd}|S(s 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)] csJytj|dSWn+tk rE}t||t|nXdS(Ni(RR?RRRu(RRNRpRA(RB(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRCs((RBRC((RBsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytconvertToDatetimess7(?P\d{4})(?:-(?P\d\d)(?:-(?P\d\d))?)?s ISO8601 dates(?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)?sISO8601 datetimes2[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}tUUIDcCstjj|dS(s 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' i(Rlt_html_stripperR{(RRNR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt stripHTMLTagss RR<s R8RRrscomma separated listcCst|jS(N(RR,(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrcCst|jS(N(RR(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRr(ii(ii(>RRRRkRotconvertToIntegertfloattconvertToFloatR-RPRRzR9RBR=R%tsigned_integerR:RRRt mixed_integerRtrealtsci_realRtnumberR;R2R1R<t ipv4_addressR>t_full_ipv6_addresst_short_ipv6_addressRt_mixed_ipv6_addressRt ipv6_addresst mac_addressR#RDREt iso8601_datetiso8601_datetimetuuidR5R4RGRHRRRRTR,t _commasepitemR>RWRtcomma_separated_listRbR@(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRlsL  '/-  ;&J+t__main__tselecttfroms_$RRtcolumnsRttablestcommandsK # '*' 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 s] 100 -100 +100 3.14159 6.02e23 1e-12 s 100 FF s6 12345678-1234-5678-1234-567812345678 (Rt __version__t__versionTime__t __author__RtweakrefRRRRxRR|RSRR8RRRRt_threadRt ImportErrort threadingRRt ordereddictRt__all__Rt version_infoRQRtmaxsizeR$RuRtchrRRRRR2treversedRRR4RxRIRJR_tmaxinttxrangeRt __builtin__RtfnameRR`RRRRRRtascii_uppercasetascii_lowercaseR2RPRBR1RRt printableRTRaRRRR!R$RR tMutableMappingtregisterR7RHRERGRKRMROReR"R*R RRRRiRRRRjR-R%R#RR,RpRRRR(R'R/R.RRRRR RR RRRR0RRRR&R RR+RRR R)RR`RR>R:RRMRLRERRQR?ReRfRhRRARGRFR_R^Rzt _escapedPunct_escapedHexChart_escapedOctChartUNICODEt _singleChart _charRangeRRR]RKRZRXRkRbR@R RIRJRcR RiRRRRRgRSR<R\RWRaRNRdR3RUR5R4RRR6RR9RYR6RCRR[R=R;RDRVRRZR8RlRt selectTokent fromTokentidentt columnNametcolumnNameListt columnSpect tableNamet tableNameListt simpleSQLR"RPR;R=RYRF(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt=s              *         8      @ & A=IG3pLOD|M &# @sQ,A ,    I # %  !4@    ,   ?  #   k%Z r  (, #8+    $     PK@N#]XMZuu*site-packages/pkg_resources/_vendor/six.pynu["""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) PK@N#]c+̓̓1site-packages/pkg_resources/_vendor/pyparsing.pyonu[ fci@sdZdZdZdZddlZddlmZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlmZyddlmZWn!ek rddlmZnXydd l mZWn?ek r=ydd lmZWnek r9eZnXnXd d d d ddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdgdhdidjdkdldmdndodpdqdrgiZee jds ZedtdskZere jZ e!Z"e#Z$e!Z%e&e'e(e)e*ee+e,e-e.e/g Z0nre j1Z e2Z3duZ%gZ0ddl4Z4xEdvj5D]7Z6ye0j7e8e4e6Wne9k rZq$nXq$We:dwe3dxDZ;dyZ<dze=fd{YZ>ej?ej@ZAd|ZBeBd}ZCeAeBZDe#d~ZEdjFdejGDZHd!eIfdYZJd#eJfdYZKd%eJfdYZLd'eLfdYZMd*eIfdYZNde=fdYZOd&e=fdYZPe jQjRePdZSdZTdZUdZVdZWdZXdZYddZZd(e=fdYZ[d0e[fdYZ\de\fdYZ]de\fdYZ^de\fdYZ_e_Z`e_e[_ade\fdYZbd e_fdYZcd ebfdYZddpe\fdYZed3e\fdYZfd+e\fdYZgd)e\fdYZhd e\fdYZid2e\fdYZjde\fdYZkdekfdYZldekfdYZmdekfdYZnd.ekfdYZod-ekfdYZpd5ekfdYZqd4ekfdYZrd$e[fdYZsd esfdYZtd esfdYZudesfdYZvdesfdYZwd"e[fdYZxdexfdYZydexfdYZzdexfdYZ{de{fdYZ|d6e{fdYZ}de=fdYZ~e~ZdexfdYZd,exfdYZdexfdYZdefdYZd1exfdYZdefdYZdefdYZdefdYZd/efdYZde=fdYZdZdedZedZdZdZdZdZeedZdZedZdZdZe]jdGZemjdMZenjdLZeojdeZepjddZefeEdddjdZegdjdZegdjdZeeBeBefeHddddxBegde jBZeeedeZe_dedjdee|eeBjddZdZdZdZdZdZedZedZdZdZdZdZe=e_ddZe>Ze=e_e=e_ededdZeZeegddjdZeegddjdZeegddegddBjdZee`dejjdZddeejdZedZedZedZeefeAeDdjd\ZZeedj5dZegddjFejdjdZdZeegddjdZegdjdZegd jjd Zegd jd ZeegddeBjd ZeZegdjdZee|efeHddeefde_denjjdZeeejeBddjd>ZdrfdYZedkrecdZecdZefeAeDdZeeddejeZeeejdZdeBZeeddejeZeeejdZededeedZejdejjdejjdejjd ddlZejjeejejjd!ndS("sS 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 s2.1.10s07 Oct 2016 01:31 UTCs*Paul McGuire iN(tref(tdatetime(tRLock(t OrderedDicttAndtCaselessKeywordtCaselessLiteralt CharsNotIntCombinetDicttEachtEmptyt FollowedBytForwardt GoToColumntGrouptKeywordtLineEndt LineStarttLiteralt MatchFirsttNoMatchtNotAnyt OneOrMoretOnlyOncetOptionaltOrtParseBaseExceptiontParseElementEnhancetParseExceptiontParseExpressiontParseFatalExceptiont ParseResultstParseSyntaxExceptiont ParserElementt QuotedStringtRecursiveGrammarExceptiontRegextSkipTot StringEndt StringStarttSuppresstTokentTokenConvertertWhitetWordtWordEndt WordStartt ZeroOrMoret alphanumstalphast alphas8bitt anyCloseTagt anyOpenTagt cStyleCommenttcoltcommaSeparatedListtcommonHTMLEntityt countedArraytcppStyleCommenttdblQuotedStringtdblSlashCommentt delimitedListtdictOftdowncaseTokenstemptythexnumst htmlCommenttjavaStyleCommenttlinetlineEndt lineStarttlinenot makeHTMLTagst makeXMLTagstmatchOnlyAtColtmatchPreviousExprtmatchPreviousLiteralt nestedExprtnullDebugActiontnumstoneOftopAssoctoperatorPrecedencet printablestpunc8bittpythonStyleCommentt quotedStringt removeQuotestreplaceHTMLEntityt replaceWitht restOfLinetsglQuotedStringtsranget stringEndt stringStartttraceParseActiont unicodeStringt upcaseTokenst withAttributet indentedBlocktoriginalTextFortungroupt infixNotationt locatedExprt withClasst CloseMatchttokenMaptpyparsing_commoniicCs}t|tr|Syt|SWnUtk rxt|jtjd}td}|jd|j |SXdS(sDrop-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 | ... >. txmlcharrefreplaces&#\d+;cSs#dtt|ddd!dS(Ns\uiii(thextint(tt((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyttN( t isinstancetunicodetstrtUnicodeEncodeErrortencodetsystgetdefaultencodingR%tsetParseActionttransformString(tobjtrett xmlcharref((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_ustrs  s6sum len sorted reversed list tuple set any all min maxccs|] }|VqdS(N((t.0ty((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys sicCsRd}ddjD}x/t||D]\}}|j||}q,W|S(s/Escape &, <, >, ", ', etc. in a string of data.s&><"'css|]}d|dVqdS(t&t;N((Rts((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys ssamp gt lt quot apos(tsplittziptreplace(tdatat from_symbolst to_symbolstfrom_tto_((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt _xml_escapes t _ConstantscBseZRS((t__name__t __module__(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRst 0123456789t ABCDEFabcdefi\Rrccs$|]}|tjkr|VqdS(N(tstringt whitespace(Rtc((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys scBs_eZdZdd d dZedZdZdZdZ ddZ d Z RS( s7base exception class for all parsing runtime exceptionsicCs[||_|dkr*||_d|_n||_||_||_|||f|_dS(NRr(tloctNonetmsgtpstrt parserElementtargs(tselfRRRtelem((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__init__s       cCs||j|j|j|jS(s internal factory method to simplify creating one type of ParseException from another - avoids having __init__ signature conflicts among subclasses (RRRR(tclstpe((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_from_exceptionscCsm|dkrt|j|jS|dkr>t|j|jS|dkr]t|j|jSt|dS(ssupported 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 RHR7tcolumnREN(R7R(RHRRR7REtAttributeError(Rtaname((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt __getattr__s   cCs d|j|j|j|jfS(Ns"%s (at char %d), (line:%d, col:%d)(RRRHR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__str__scCs t|S(N(R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__repr__ss>!} ('-' operator) indicates that parsing is to stop immediately because an unbacktrackable syntax error has been found(RRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR!scBs eZdZdZdZRS(sZexception thrown by L{ParserElement.validate} if the grammar could be improperly recursivecCs ||_dS(N(tparseElementTrace(RtparseElementList((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCs d|jS(NsRecursiveGrammarException: %s(R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s(RRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR$s t_ParseResultsWithOffsetcBs,eZdZdZdZdZRS(cCs||f|_dS(N(ttup(Rtp1tp2((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR$scCs |j|S(N(R(Rti((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt __getitem__&scCst|jdS(Ni(treprR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR(scCs|jd|f|_dS(Ni(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt setOffset*s(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR#s   cBseZdZd-d-eedZd-d-eeedZdZedZ dZ dZ dZ dZ e Zd Zd Zd Zd Zd ZereZeZeZn-eZeZeZdZdZdZdZdZd-dZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'ddZ(d Z)d!Z*d"Z+d-e,ded#Z-d$Z.d%Z/dd&ed'Z0d(Z1d)Z2d*Z3d+Z4d,Z5RS(.sI 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 cCs/t||r|Stj|}t|_|S(N(Rstobjectt__new__tTruet_ParseResults__doinit(RttoklisttnametasListtmodaltretobj((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRTs  cCs|jrt|_d|_d|_i|_||_||_|dkrTg}n||trp||_ n-||t rt||_ n |g|_ t |_ n|dk r|r|sd|j|s(R(R((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt _itervaluesscsfdjDS(Nc3s|]}||fVqdS(N((RR(R(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys s(R(R((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt _iteritemsscCst|jS(sVReturns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).(RR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytkeysscCst|jS(sXReturns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).(Rt itervalues(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytvaluesscCst|jS(sfReturns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).(Rt iteritems(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCs t|jS(sSince keys() returns an iterator, this method is helpful in bypassing code that looks for the existence of any defined results names.(tboolR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pythaskeysscOs|sdg}nxI|jD];\}}|dkrJ|d|f}qtd|qWt|dtst|dks|d|kr|d}||}||=|S|d}|SdS(s 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'] itdefaultis-pop() got an unexpected keyword argument '%s'iN(RRRsRoR(RRtkwargsRRtindexR}t defaultvalue((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytpops"     cCs||kr||S|SdS(si 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 N((Rtkeyt defaultValue((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs cCsw|jj||x]|jjD]L\}}x=t|D]/\}\}}t||||k|| ['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(RtinsertRRRR(RRtinsStrRRRRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR2scCs|jj|dS(s 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(Rtappend(Rtitem((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRFs cCs0t|tr||7}n|jj|dS(s 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(RsR Rtextend(Rtitemseq((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRTs  cCs|j2|jjdS(s7 Clear all elements and results names. N(RRtclear(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRfscCsy ||SWntk r dSX||jkr}||jkrR|j|ddStg|j|D]}|d^qcSndSdS(NRrii(RRRR (RRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRms  +cCs|j}||7}|S(N(R(RtotherR}((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__add__{s  c s|jrt|jfd}|jj}g|D]<\}}|D])}|t|d||df^qMq=}xJ|D]?\}}|||st](RR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRsRrcCsog}xb|jD]W}|r2|r2|j|nt|trT||j7}q|jt|qW|S(N(RRRsR t _asStringListR(RtseptoutR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs cCs5g|jD]'}t|tr+|jn|^q S(s 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'] (RRsR R(Rtres((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscsGtr|j}n |j}fdtfd|DS(s 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"} csMt|trE|jr%|jSg|D]}|^q,Sn|SdS(N(RsR RtasDict(R|R(ttoItem(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs    c3s'|]\}}||fVqdS(N((RRR(R(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys s(tPY_3RRR(Rtitem_fn((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs    cCsPt|j}|jj|_|j|_|jj|j|j|_|S(sA Returns a new copy of a C{ParseResults} object. (R RRRRRR R(RR}((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs   c Csd}g}td|jjD}|d}|sPd}d}d}nd } |d k rk|} n|jr|j} n| s|rdSd} n|||d| dg7}x t|jD]\} } t| trI| |kr|| j || |o|d k||g7}q|| j d |o6|d k||g7}qd } | |krh|| } n| s|rzqqd} nt t | } |||d| d| d| dg 7}qW|||d| dg7}dj |S( s (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names. s css2|](\}}|D]}|d|fVqqdS(iN((RRRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys s s RrtITEMtsgss %s%s- %s: s icss|]}t|tVqdS(N(RsR (Rtvv((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys sss %s%s[%d]: %s%s%sRr( RRRRtsortedRRsR tdumpRtanyRR( RR$tdepthtfullRtNLRRRRR1((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR3Ps,  B?cOstj|j||dS(s 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(tpprintR(RRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR8}scCsC|j|jj|jdk r-|jp0d|j|jffS(N(RRRRRRR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt __getstate__s  cCsm|d|_|d\|_}}|_i|_|jj||dk r`t||_n d|_dS(Nii(RRRRR RRR(RtstateR/t inAccumNames((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt __setstate__s   cCs|j|j|j|jfS(N(RRRR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__getnewargs__scCs tt|t|jS(N(RRRR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRsN(6RRRRRRRsRRRRRRRt __nonzero__RRRRRRRRRRRRRRRRRRRRR RRRRRRRRRR!R-R0R3R8R9R<R=R(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR -sh& '              4             # =  %-   cCsW|}d|ko#t|knr@||ddkr@dS||jdd|S(sReturns 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. iis (Rtrfind(RtstrgR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR7s cCs|jdd|dS(sReturns 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. s ii(tcount(RR@((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRHs cCsR|jdd|}|jd|}|dkrB||d|!S||dSdS(sfReturns the line of text containing loc within a string, counting newlines as line separators. s iiN(R?tfind(RR@tlastCRtnextCR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyREs  cCsAdt|dt|dt||t||fGHdS(NsMatch s at loc s(%d,%d)(RRHR7(tinstringRtexpr((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_defaultStartDebugActionscCs'dt|dt|jGHdS(NsMatched s -> (RRuR(REtstartloctendlocRFttoks((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_defaultSuccessDebugActionscCsdt|GHdS(NsException raised:(R(RERRFtexc((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_defaultExceptionDebugActionscGsdS(sG'Do-nothing' debug action, to suppress debugging output during parsing.N((R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyROsics tkrfdSdgtgtd dkrVdd}ddntj}tjd}|d dd }|d|d |ffd }d }y"tdtdj}Wntk rt }nX||_|S(Ncs |S(N((RtlRp(tfunc(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRriiiicSsJtdkrdnd}tjd| |d|}|j|jfgS( Niiiiitlimiti(iii(tsystem_versiont tracebackt extract_stacktfilenameRH(RPR t frame_summary((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRSscSs2tj|d|}|d}|j|jfgS(NRPi(RRt extract_tbRTRH(ttbRPtframesRU((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRVs iRPiicsxy&|d}td<|SWqtk rdrInAz:tjd}|dddd ksnWd~Xdkrdcd7Rt __class__(ii( tsingleArgBuiltinsRRQRRRSRVtgetattrRt ExceptionRu(ROR[RSt LINE_DIFFt this_lineR]t func_name((RVRZRORPR[R\sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt _trim_aritys*          cBseZdZdZeZedZedZedZ dZ dZ edZ e dZd Zd Zd Zd Zd ZdZe dZdZe e dZdZdZdefdYZedFk rdefdYZndefdYZiZe Z!ddgZ"e e dZ#eZ$edZ%eZ&eddZ'edZ(e)edZ*d Z+e)d!Z,e)ed"Z-d#Z.d$Z/d%Z0d&Z1d'Z2d(Z3d)Z4d*Z5d+Z6d,Z7d-Z8d.Z9d/Z:dFd0Z;d1Z<d2Z=d3Z>d4Z?d5Z@d6ZAe d7ZBd8ZCd9ZDd:ZEd;ZFgd<ZGed=ZHd>ZId?ZJd@ZKdAZLdBZMe dCZNe dDe e edEZORS(Gs)Abstract base level parser element class.s cCs |t_dS(s 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"tDEFAULT_WHITE_CHARS(tchars((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetDefaultWhitespaceChars=s cCs |t_dS(s 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"t_literalStringClass(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytinlineLiteralsUsingLscCst|_d|_d|_d|_||_t|_t j |_ t|_ t |_t |_t|_t |_t |_t|_d|_t|_d|_d|_t|_t |_dS(NRr(NNN(Rt parseActionRt failActiontstrReprt resultsNamet saveAsListRtskipWhitespaceR"Rft whiteCharstcopyDefaultWhiteCharsRtmayReturnEmptytkeepTabst ignoreExprstdebugt streamlinedt mayIndexErrorterrmsgt modalResultst debugActionstret callPreparset callDuringTry(Rtsavelist((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRas(                   cCsEtj|}|j|_|j|_|jrAtj|_n|S(s$ 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") (RRkRuRrR"RfRq(Rtcpy((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRxs    cCs>||_d|j|_t|dr:|j|j_n|S(sf 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) s Expected t exception(RRyRRR(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetNames  cCsE|j}|jdr.|d }t}n||_| |_|S(sP 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") t*i(RtendswithRRnRz(RRtlistAllMatchestnewself((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetResultsNames     csa|r9|jttfd}|_||_n$t|jdr]|jj|_n|S(sMethod to invoke the Python pdb debugger when this element is about to be parsed. Set C{breakFlag} to True to enable, False to disable. cs)ddl}|j||||S(Ni(tpdbt set_trace(RERt doActionst callPreParseR(t _parseMethod(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytbreakers  t_originalParseMethod(t_parseRRR(Rt breakFlagR((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetBreaks   cOs7tttt||_|jdt|_|S(s  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] R~(RtmapReRkRRR~(RtfnsR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRzs"cOsF|jtttt|7_|jp<|jdt|_|S(s Add parse action to expression's list of parse actions. See L{I{setParseAction}}. See examples in L{I{copy}}. R~(RkRRReR~RR(RRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytaddParseActions$cs|jdd|jdtr*tntx3|D]+fd}|jj|q7W|jp~|jdt|_|S(sAdd 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) tmessagesfailed user-defined conditiontfatalcs7tt|||s3||ndS(N(RRe(RRNRp(texc_typetfnR(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytpasR~(RRRRRkRR~(RRRR((RRRsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt addConditions cCs ||_|S(s 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.(Rl(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt setFailActions cCsnt}xa|rit}xN|jD]C}y)x"|j||\}}t}q+WWqtk raqXqWq W|S(N(RRRuRR(RRERt exprsFoundtetdummy((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt_skipIgnorables#s   cCsp|jr|j||}n|jrl|j}t|}x-||krh|||krh|d7}q?Wn|S(Ni(RuRRpRqR(RRERtwttinstrlen((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytpreParse0s    cCs |gfS(N((RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt parseImpl<scCs|S(N((RRERt tokenlist((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt postParse?sc Cs|j}|s|jr,|jdr?|jd|||n|rc|jrc|j||}n|}|}yUy|j|||\}}Wn/tk rt|t||j |nXWqt k r(} |jdr|jd|||| n|jr"|j|||| nqXn|rP|jrP|j||}n|}|}|j sw|t|kry|j|||\}}Wqtk rt|t||j |qXn|j|||\}}|j |||}t ||jd|jd|j} |jrf|s7|jrf|ryrxk|jD]`} | ||| }|dk rJt ||jd|jot|t tfd|j} qJqJWWqct k r} |jdr|jd|||| nqcXqfxn|jD]`} | ||| }|dk rt ||jd|joMt|t tfd|j} qqWn|r|jdr|jd||||| qn|| fS(NiiRRi(RvRlR{R}RRRRRRyRRxRR RnRoRzRkR~RRsR( RRERRRt debuggingtpreloct tokensStartttokensterrt retTokensR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt _parseNoCacheCsp   &    %$       #cCsNy|j||dtdSWn)tk rIt|||j|nXdS(NRi(RRRRRy(RRER((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyttryParses cCs7y|j||Wnttfk r.tSXtSdS(N(RRRRR(RRER((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt canParseNexts t_UnboundedCachecBseZdZRS(csit|_fd}fd}fd}tj|||_tj|||_tj|||_dS(Ncsj|S(N(R(RR(tcachet not_in_cache(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscs||}) - 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 iN( R"RRwt streamlineRuRtt expandtabsRRR R'Rtverbose_stacktrace(RREtparseAllRRRtseRL((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt parseString#s$      ccs|js|jnx|jD]}|jq W|jsRt|j}nt|}d}|j}|j}t j d} yx||kra| |kray.|||} ||| dt \} } Wnt k r| d}qX| |krT| d7} | | | fV|rK|||} | |kr>| }qQ|d7}q^| }q| d}qWWn(t k r}t jrq|nXdS(s 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 iRiN(RwRRuRtRRRRRR"RRRRR(RREt maxMatchestoverlapRRRt preparseFntparseFntmatchesRtnextLocRtnextlocRL((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt scanStringUsB               c Cs%g}d}t|_yx|j|D]}\}}}|j|||!|rt|trs||j7}qt|tr||7}q|j|n|}q(W|j||g|D]}|r|^q}djt t t |SWn(t k r }t jrq!|nXdS(sf 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. iRrN(RRtRRRsR RRRRRt_flattenRR"R( RRERtlastERpRRtoRL((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR{s(     cCsey6tg|j||D]\}}}|^qSWn(tk r`}tjrWqa|nXdS(s~ 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'] N(R RRR"R(RRERRpRRRL((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt searchStrings 6 c csfd}d}xJ|j|d|D]3\}}}|||!V|rO|dVn|}q"W||VdS(s[ 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', ''] iRN(R( RREtmaxsplittincludeSeparatorstsplitstlastRpRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs %   cCsdt|tr!tj|}nt|tsTtjdt|tdddSt ||gS(s 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', '!'] s4Cannot combine element of type %s with ParserElementt stackleveliN( RsRR"RitwarningstwarnRt SyntaxWarningRR(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s  cCs\t|tr!tj|}nt|tsTtjdt|tdddS||S(s] Implementation of + operator when left operand is not a C{L{ParserElement}} s4Cannot combine element of type %s with ParserElementRiN( RsRR"RiRRRRR(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs cCsmt|tr!tj|}nt|tsTtjdt|tdddSt |t j |gS(sQ Implementation of - operator, returns C{L{And}} with error stop s4Cannot combine element of type %s with ParserElementRiN( RsRR"RiRRRRRRt _ErrorStop(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__sub__s cCs\t|tr!tj|}nt|tsTtjdt|tdddS||S(s] Implementation of - operator when left operand is not a C{L{ParserElement}} s4Cannot combine element of type %s with ParserElementRiN( RsRR"RiRRRRR(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__rsub__ s csEt|tr|d}}n-t|tr7|d d }|dd kr_d|df}nt|dtr|dd kr|ddkrtS|ddkrtS|dtSqLt|dtrt|dtr|\}}||8}qLtdt|dt|dntdt||dkrgtdn|dkrtdn||kodknrtdn|rfd |r |dkr|}qt g||}qA|}n(|dkr.}nt g|}|S( s 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} iiis7cannot multiply 'ParserElement' and ('%s','%s') objectss0cannot multiply 'ParserElement' and '%s' objectss/cannot multiply ParserElement by negative values@second tuple value must be greater or equal to first tuple values+cannot multiply ParserElement by 0 or (0,0)cs2|dkr$t|dStSdS(Ni(R(tn(tmakeOptionalListR(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR]s N(NN( RsRottupleRR0RRRt ValueErrorR(RR t minElementst optElementsR}((RRsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__mul__,sD#  &  )      cCs |j|S(N(R(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__rmul__pscCsdt|tr!tj|}nt|tsTtjdt|tdddSt ||gS(sI Implementation of | operator - returns C{L{MatchFirst}} s4Cannot combine element of type %s with ParserElementRiN( RsRR"RiRRRRRR(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__or__ss cCs\t|tr!tj|}nt|tsTtjdt|tdddS||BS(s] Implementation of | operator when left operand is not a C{L{ParserElement}} s4Cannot combine element of type %s with ParserElementRiN( RsRR"RiRRRRR(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__ror__s cCsdt|tr!tj|}nt|tsTtjdt|tdddSt ||gS(sA Implementation of ^ operator - returns C{L{Or}} s4Cannot combine element of type %s with ParserElementRiN( RsRR"RiRRRRRR(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__xor__s cCs\t|tr!tj|}nt|tsTtjdt|tdddS||AS(s] Implementation of ^ operator when left operand is not a C{L{ParserElement}} s4Cannot combine element of type %s with ParserElementRiN( RsRR"RiRRRRR(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__rxor__s cCsdt|tr!tj|}nt|tsTtjdt|tdddSt ||gS(sC Implementation of & operator - returns C{L{Each}} s4Cannot combine element of type %s with ParserElementRiN( RsRR"RiRRRRRR (RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__and__s cCs\t|tr!tj|}nt|tsTtjdt|tdddS||@S(s] Implementation of & operator when left operand is not a C{L{ParserElement}} s4Cannot combine element of type %s with ParserElementRiN( RsRR"RiRRRRR(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__rand__s cCs t|S(sE Implementation of ~ operator - returns C{L{NotAny}} (R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt __invert__scCs'|dk r|j|S|jSdS(s  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(RRR(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__call__s  cCs t|S(s Suppresses the output of this C{ParserElement}; useful to keep punctuation from cluttering up returned output. (R)(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsuppressscCs t|_|S(s 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. (RRp(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytleaveWhitespaces cCst|_||_t|_|S(s8 Overrides the default whitespace chars (RRpRqRRr(RRg((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetWhitespaceCharss   cCs t|_|S(s 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. (RRt(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt parseWithTabss cCsrt|trt|}nt|trR||jkrn|jj|qnn|jjt|j|S(s 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'] (RsRR)RuRR(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytignores cCs1|p t|pt|ptf|_t|_|S(sT Enable display of debugging messages while doing pattern matching. (RGRKRMR{RRv(Rt startActiont successActiontexceptionAction((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetDebugActions s    cCs)|r|jtttn t|_|S(s 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...)"}. (RRGRKRMRRv(Rtflag((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetDebugs# cCs|jS(N(R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR@scCs t|S(N(R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRCscCst|_d|_|S(N(RRwRRm(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRFs  cCsdS(N((RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytcheckRecursionKscCs|jgdS(sj Check defined expressions for valid structure, check for infinite recursive definitions. N(R(Rt validateTrace((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytvalidateNscCsy|j}Wn5tk rGt|d}|j}WdQXnXy|j||SWn(tk r}tjr}q|nXdS(s 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. trN(treadRtopenRRR"R(Rtfile_or_filenameRt file_contentstfRL((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt parseFileTs  cCsdt|tr1||kp0t|t|kSt|trM|j|Stt||kSdS(N(RsR"tvarsRRtsuper(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__eq__hs " cCs ||k S(N((RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__ne__pscCstt|S(N(thashtid(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__hash__sscCs ||kS(N((RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__req__vscCs ||k S(N((RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__rne__yscCs:y!|jt|d|tSWntk r5tSXdS(s 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") RN(RRRRR(Rt testStringR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR|s  t#cCsyt|tr6tttj|jj}nt|trTt|}ng}g}t } x|D]} |d k r|j | t s|r| r|j | qmn| sqmndj|| g} g}yQ| jdd} |j| d|} | j | jd|| o%| } Wntk r} t| trPdnd}d| kr| j t| j| | j dt| j| dd |n| j d| jd || j d t| | o|} | } n<tk r*}| j d t|| o|} |} nX|rX|rG| j dndj| GHn|j | | fqmW| |fS( s3 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'.) s s\nRR6s(FATAL)Rrt it^sFAIL: sFAIL-EXCEPTION: N(RsRRRRuRtrstript splitlinesRRRRRRRRRR3RRRERR7Ra(RttestsRtcommenttfullDumpt printResultst failureTestst allResultstcommentstsuccessRpRtresultRRRL((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytrunTestssNW' +  ,    N(PRRRRfRRt staticmethodRhRjRRRRRRRzRRRRRRRRRRRRRRRRRRRRRRRRRt_MAX_INTRR{RRR RRRRRRRRRRRRRRRRRRRRRRRRRR R R RRRRR"(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR"8s      &   H     " 2G +   D      )            cBseZdZdZRS(sT Abstract C{ParserElement} subclass, for defining atomic matching patterns. cCstt|jdtdS(NR(R R*RR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s(RRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR* scBseZdZdZRS(s, An empty token, will always match. cCs2tt|jd|_t|_t|_dS(NR (R R RRRRsRRx(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s  (RRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR  scBs#eZdZdZedZRS(s( A token that will never match. cCs;tt|jd|_t|_t|_d|_dS(NRsUnmatchable token( R RRRRRsRRxRy(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR* s    cCst|||j|dS(N(RRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR1 s(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR& s cBs#eZdZdZedZRS(s 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}. cCstt|j||_t||_y|d|_Wn0tk rntj dt ddt |_ nXdt |j|_d|j|_t|_t|_dS(Nis2null string passed to Literal; use Empty() insteadRis"%s"s Expected (R RRtmatchRtmatchLentfirstMatchCharRRRRR R^RRRyRRsRx(Rt matchString((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRC s      cCsg|||jkrK|jdks7|j|j|rK||j|jfSt|||j|dS(Ni(R'R&t startswithR%RRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRV s$(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR5 s  cBsKeZdZedZdedZedZ dZ e dZ RS(s\ 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}. s_$cCstt|j|dkr+tj}n||_t||_y|d|_Wn't k r}t j dt ddnXd|j|_ d|j |_t|_t|_||_|r|j|_|j}nt||_dS(Nis2null string passed to Keyword; use Empty() insteadRis"%s"s Expected (R RRRtDEFAULT_KEYWORD_CHARSR%RR&R'RRRRRRyRRsRxtcaselesstuppert caselessmatchRt identChars(RR(R.R+((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRq s&        cCsb|jr||||j!j|jkrF|t||jkse|||jj|jkrF|dks||dj|jkrF||j|jfSn|||jkrF|jdks|j|j|rF|t||jks|||j|jkrF|dks2||d|jkrF||j|jfSt |||j |dS(Nii( R+R&R,R-RR.R%R'R)RRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s #9)$3#cCs%tt|j}tj|_|S(N(R RRR*R.(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s cCs |t_dS(s,Overrides the default Keyword chars N(RR*(Rg((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytsetDefaultKeywordChars sN( RRRR1R*RRRRRRR#R/(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR^ s    cBs#eZdZdZedZRS(sl 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}.) cCsItt|j|j||_d|j|_d|j|_dS(Ns'%s's Expected (R RRR,t returnStringRRy(RR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s cCsS||||j!j|jkr7||j|jfSt|||j|dS(N(R&R,R%R0RRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s#(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s  cBs&eZdZddZedZRS(s Caseless version of L{Keyword}. Example:: OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] (Contrast with example for L{CaselessLiteral}.) cCs#tt|j||dtdS(NR+(R RRR(RR(R.((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR scCs||||j!j|jkrp|t||jks\|||jj|jkrp||j|jfSt|||j|dS(N(R&R,R-RR.R%RRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s#9N(RRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s cBs&eZdZddZedZRS(sx 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']}) icCs]tt|j||_||_||_d|j|jf|_t|_t|_ dS(Ns&Expected %r (with up to %d mismatches)( R RjRRt match_stringt maxMismatchesRyRRxRs(RR1R2((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s    cCs|}t|}|t|j}||kr|j}d}g} |j} xtt|||!|jD]J\}} | \} } | | kro| j|t| | krPqqoqoW|d}t|||!g}|j|d<| |d<||fSnt|||j|dS(Niitoriginalt mismatches( RR1R2RRRR RRy(RRERRtstartRtmaxlocR1tmatch_stringlocR4R2ts_mtsrctmattresults((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s(    ,        (RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRj s cBs>eZdZddddeddZedZdZRS(s 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=",") iicstt|jrcdjfd|D}|rcdjfd|D}qcn||_t||_|r||_t||_n||_t||_|dk|_ |dkrt dn||_ |dkr||_ n t |_ |dkr)||_ ||_ nt||_d|j|_t|_||_d|j|jkr}|dkr}|dkr}|dkr}|j|jkrd t|j|_net|jdkrd tj|jt|jf|_n%d t|jt|jf|_|jrDd |jd |_nytj|j|_Wq}tk ryd|_q}XndS( NRrc3s!|]}|kr|VqdS(N((RR(t excludeChars(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys 7 sc3s!|]}|kr|VqdS(N((RR(R<(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys 9 siisZcannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitteds Expected Rs[%s]+s%s[%s]*s [%s][%s]*s\b(R R-RRt initCharsOrigRt initCharst bodyCharsOrigt bodyCharst maxSpecifiedRtminLentmaxLenR$RRRyRRxt asKeywordt_escapeRegexRangeCharstreStringRR|tescapetcompileRaR(RR>R@tmintmaxtexactRDR<((R<sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR4 sT%             :   c Cs|jr[|jj||}|s?t|||j|n|j}||jfS|||jkrt|||j|n|}|d7}t|}|j}||j }t ||}x*||kr|||kr|d7}qWt } |||j krt } n|jrG||krG|||krGt } n|jr|dkrp||d|ks||kr|||krt } qn| rt|||j|n||||!fS(Nii(R|R%RRytendtgroupR>RR@RCRIRRBRRARD( RRERRR!R5Rt bodycharsR6tthrowException((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRj s6       %  < cCsytt|jSWntk r*nX|jdkrd}|j|jkr}d||j||jf|_qd||j|_n|jS(NcSs&t|dkr|d dS|SdS(Nis...(R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt charsAsStr s s W:(%s,%s)sW:(%s)(R R-RRaRmRR=R?(RRP((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s  (N( RRRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR- s.6 #cBsDeZdZeejdZddZedZ dZ RS(s 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})") s[A-Z]icCs3tt|jt|tr|sAtjdtddn||_||_ y+t j |j|j |_ |j|_ Wqt jk rtjd|tddqXnIt|tjr||_ t||_|_ ||_ n tdt||_d|j|_t|_t|_dS(sThe 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.s0null string passed to Regex; use Empty() insteadRis$invalid pattern (%s) passed to RegexsCRegex may only be constructed with a string or a compiled RE objects Expected N(R R%RRsRRRRtpatterntflagsR|RHRFt sre_constantsterrortcompiledREtypeRuRRRRyRRxRRs(RRQRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s.          cCs|jj||}|s6t|||j|n|j}|j}t|j}|rx|D]}||||eZdZddeededZedZdZRS(s 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']] c sttj|j}|sGtjdtddtn|dkr\|}n4|j}|stjdtddtn|_ t |_ |d_ |_ t |_|_|_|_|_|rTtjtjB_dtjj tj d|dk rDt|pGdf_nPd_dtjj tj d|dk rt|pdf_t j d krjd d jfd tt j d dd Dd7_n|r*jdtj|7_n|rhjdtj|7_tjjd_njdtjj 7_y+tjjj_j_Wn4tj k rtjdjtddnXt!_"dj"_#t$_%t&_'dS(Ns$quoteChar cannot be the empty stringRis'endQuoteChar cannot be the empty stringis %s(?:[^%s%s]Rrs%s(?:[^%s\n\r%s]is|(?:s)|(?:c3s<|]2}dtjj| tj|fVqdS(s%s[^%s]N(R|RGt endQuoteCharRE(RR(R(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys / sit)s|(?:%s)s|(?:%s.)s(.)s)*%ss$invalid pattern (%s) passed to Regexs Expected ((R R#RRRRRt SyntaxErrorRt quoteCharRt quoteCharLentfirstQuoteCharRXtendQuoteCharLentescChartescQuotetunquoteResultstconvertWhitespaceEscapesR|t MULTILINEtDOTALLRRRGRERQRRtescCharReplacePatternRHRFRSRTRRRyRRxRRs(RR[R_R`t multilineRaRXRb((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR sf             ( %E  c CsT|||jkr(|jj||p+d}|sOt|||j|n|j}|j}|jrJ||j |j !}t |t rJd|kr|j ridd6dd6dd6dd 6}x/|jD]\}}|j||}qWn|jr tj|jd |}n|jrG|j|j|j}qGqJn||fS( Ns\s s\ts s\ns s\fs s\rs\g<1>(R]R|R%RRRyRLRMRaR\R^RsRRbRRR_RReR`RX( RRERRR!R}tws_maptwslittwschar((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRG s*.      !cCs]ytt|jSWntk r*nX|jdkrVd|j|jf|_n|jS(Ns.quoted string, starting with %s ending with %s(R R#RRaRmRR[RX(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRj s N( RRRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR# sA #cBs5eZdZddddZedZdZRS(s 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'] iicCstt|jt|_||_|dkr@tdn||_|dkra||_n t |_|dkr||_||_nt ||_ d|j |_ |jdk|_ t|_dS(Nisfcannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permittedis Expected (R RRRRptnotCharsRRBRCR$RRRyRsRx(RRjRIRJRK((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s           cCs|||jkr.t|||j|n|}|d7}|j}t||jt|}x*||kr|||kr|d7}qfW|||jkrt|||j|n||||!fS(Ni(RjRRyRIRCRRB(RRERRR5tnotcharstmaxlen((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s  cCsytt|jSWntk r*nX|jdkryt|jdkrfd|jd |_qyd|j|_n|jS(Nis !W:(%s...)s!W:(%s)(R RRRaRmRRRj(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s (RRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRv s cBsXeZdZidd6dd6dd6dd6d d 6Zd d d d dZedZRS(s 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. sRss ss ss ss s iicsttj|_jdjfdjDdjdjD_t_ dj_ |_ |dkr|_ n t _ |dkr|_ |_ ndS(NRrc3s$|]}|jkr|VqdS(N(t matchWhite(RR(R(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys scss|]}tj|VqdS(N(R,t whiteStrs(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys ss Expected i(R R,RRmRRRqRRRsRyRBRCR$(RtwsRIRJRK((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s )       cCs|||jkr.t|||j|n|}|d7}||j}t|t|}x-||kr|||jkr|d7}qcW|||jkrt|||j|n||||!fS(Ni(RmRRyRCRIRRB(RRERRR5R6((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s  "(RRRRnRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR, s t_PositionTokencBseZdZRS(cCs8tt|j|jj|_t|_t|_ dS(N( R RpRR^RRRRsRRx(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s (RRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRp scBs,eZdZdZdZedZRS(sb Token to advance to a specific column of input text; useful for tabular report scraping. cCs tt|j||_dS(N(R RRR7(Rtcolno((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR scCst|||jkrt|}|jrB|j||}nxE||kr||jrt|||jkr|d7}qEWn|S(Ni(R7RRuRtisspace(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s  7cCs^t||}||jkr6t||d|n||j|}|||!}||fS(NsText not in expected column(R7R(RRERRtthiscoltnewlocR}((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s  (RRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s  cBs#eZdZdZedZRS(s 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'] cCs tt|jd|_dS(NsExpected start of line(R RRRy(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR& scCs;t||dkr|gfSt|||j|dS(Ni(R7RRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR* s (RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s cBs#eZdZdZedZRS(sU Matches if current position is at the end of a line within the parse string cCs<tt|j|jtjjddd|_dS(Ns RrsExpected end of line(R RRRR"RfRRy(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR3 scCs|t|krK||dkr0|ddfSt|||j|n8|t|krk|dgfSt|||j|dS(Ns i(RRRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR8 s(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR/ s cBs#eZdZdZedZRS(sM Matches if current position is at the beginning of the parse string cCs tt|jd|_dS(NsExpected start of text(R R(RRy(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRG scCsL|dkrB||j|dkrBt|||j|qBn|gfS(Ni(RRRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRK s (RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR(C s cBs#eZdZdZedZRS(sG Matches if current position is at the end of the parse string cCs tt|jd|_dS(NsExpected end of text(R R'RRy(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRV scCs|t|kr-t|||j|nT|t|krM|dgfS|t|kri|gfSt|||j|dS(Ni(RRRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRZ s (RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR'R s cBs&eZdZedZedZRS(sp 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. cCs/tt|jt||_d|_dS(NsNot at the start of a word(R R/RRt wordCharsRy(RRu((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRl scCs^|dkrT||d|jks6|||jkrTt|||j|qTn|gfS(Nii(RuRRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRq s  (RRRRTRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR/d s cBs&eZdZedZedZRS(sZ 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. cCs8tt|jt||_t|_d|_dS(NsNot at the end of a word(R R.RRRuRRpRy(RRu((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s cCsvt|}|dkrl||krl|||jksN||d|jkrlt|||j|qln|gfS(Nii(RRuRRy(RRERRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s  (RRRRTRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR.x s cBsqeZdZedZdZdZdZdZdZ dZ edZ gd Z d Z RS( s^ Abstract subclass of ParserElement, for combining and post-processing parsed tokens. cCstt|j|t|tr4t|}nt|tr[tj|g|_ nt|t j rt|}t d|Drt tj|}nt||_ n3yt||_ Wntk r|g|_ nXt|_dS(Ncss|]}t|tVqdS(N(RsR(RRF((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys s(R RRRsRRRR"RitexprsRtIterabletallRRRR}(RRvR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s  cCs |j|S(N(Rv(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR scCs|jj|d|_|S(N(RvRRRm(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s cCsPt|_g|jD]}|j^q|_x|jD]}|jq8W|S(s~Extends C{leaveWhitespace} defined in base class, and also invokes C{leaveWhitespace} on all contained expressions.(RRpRvRR(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s  %cCst|trb||jkrtt|j|x(|jD]}|j|jdq>Wqn>tt|j|x%|jD]}|j|jdqW|S(Ni(RsR)RuR RRRv(RR R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR scCsfytt|jSWntk r*nX|jdkr_d|jjt|j f|_n|jS(Ns%s:(%s)( R RRRaRmRR^RRRv(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s %cCswtt|jx|jD]}|jqWt|jdkr`|jd}t||jr|j r|jdkr|j r|j|jdg|_d|_ |j |j O_ |j |j O_ n|jd}t||jr`|j r`|jdkr`|j r`|jd |j|_d|_ |j |j O_ |j |j O_ q`ndt||_|S(Niiiis Expected (R RRRvRRsR^RkRnRRvRmRsRxRRy(RRR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s0        cCstt|j||}|S(N(R RR(RRRR}((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR scCs@||g}x|jD]}|j|qW|jgdS(N(RvRR(RRttmpR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR scCs>tt|j}g|jD]}|j^q|_|S(N(R RRRv(RR}R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s%(RRRRRRRRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s    "  cBsWeZdZdefdYZedZedZdZdZ dZ RS(s  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") RcBseZdZRS(cOs3ttj|j||d|_|jdS(Nt-(R RRRRR(RRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s (RRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR scCsltt|j||td|jD|_|j|jdj|jdj|_t |_ dS(Ncss|]}|jVqdS(N(Rs(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys  si( R RRRxRvRsRRqRpRR}(RRvR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s c Cs?|jdj|||dt\}}t}x|jdD]}t|tjr`t}q<n|ry|j|||\}}Wqtk rqtk r}d|_ tj |qt k rt|t ||j|qXn|j|||\}}|s$|jr<||7}q<q<W||fS(NiRi(RvRRRsRRRR!RRt __traceback__RRRRyR( RRERRt resultlistt errorStopRt exprtokensR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s((   %cCs.t|tr!tj|}n|j|S(N(RsRR"RiR(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR5 scCs@||g}x+|jD] }|j||jsPqqWdS(N(RvRRs(RRtsubRecCheckListR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR: s   cCsVt|dr|jS|jdkrOddjd|jDd|_n|jS(NRt{Rcss|]}t|VqdS(N(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys F st}(RRRmRRRv(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRA s *( RRRR RRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s    cBsAeZdZedZedZdZdZdZ RS(s 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']] cCsNtt|j|||jrAtd|jD|_n t|_dS(Ncss|]}|jVqdS(N(Rs(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys \ s(R RRRvR4RsR(RRvR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRY s c Csd}d}g}x|jD]}y|j||}Wntk rw} d| _| j|kr| }| j}qqtk rt||krt|t||j|}t|}qqX|j ||fqW|rh|j ddxn|D]c\} }y|j |||SWqtk r`} d| _| j|kra| }| j}qaqXqWn|dk r|j|_ |nt||d|dS(NiRcSs |d S(Ni((tx((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqu Rrs no defined alternatives to match( RRvRRR{RRRRyRtsortRR( RRERRt maxExcLoct maxExceptionRRtloc2Rt_((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR` s<      cCs.t|tr!tj|}n|j|S(N(RsRR"RiR(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__ixor__ scCsVt|dr|jS|jdkrOddjd|jDd|_n|jS(NRRs ^ css|]}t|VqdS(N(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys sR(RRRmRRRv(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s *cCs3||g}x|jD]}|j|qWdS(N(RvR(RRRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s( RRRRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRK s    &  cBsAeZdZedZedZdZdZdZ RS(s 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']] cCsNtt|j|||jrAtd|jD|_n t|_dS(Ncss|]}|jVqdS(N(Rs(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys s(R RRRvR4RsR(RRvR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s c Csd}d}x|jD]}y|j|||}|SWqtk ro}|j|kr|}|j}qqtk rt||krt|t||j|}t|}qqXqW|dk r|j|_|nt||d|dS(Nis no defined alternatives to match( RRvRRRRRRyR( RRERRRRRR}R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s$    cCs.t|tr!tj|}n|j|S(N(RsRR"RiR(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt__ior__ scCsVt|dr|jS|jdkrOddjd|jDd|_n|jS(NRRs | css|]}t|VqdS(N(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys sR(RRRmRRRv(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s *cCs3||g}x|jD]}|j|qWdS(N(RvR(RRRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s( RRRRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s     cBs8eZdZedZedZdZdZRS(sm 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 cCsKtt|j||td|jD|_t|_t|_dS(Ncss|]}|jVqdS(N(Rs(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys s( R R RRxRvRsRRptinitExprGroups(RRvR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs cCs4|jrLtd|jD|_g|jD]}t|tr/|j^q/}g|jD]%}|jr]t|t r]|^q]}|||_g|jD]}t|t r|j^q|_ g|jD]}t|t r|j^q|_ g|jD]$}t|tt t fs|^q|_ |j |j 7_ t|_n|}|j }|j} g} t} x| r_|| |j |j } g} x| D]}y|j||}Wntk r| j|qX| j|jjt||||kr|j|q|| kr| j|qqWt| t| krut} ququW|rdjd|D}t||d|n| g|jD]*}t|tr|j| kr|^q7} g}x6| D].}|j|||\}}|j|qWt|tg}||fS(Ncss3|])}t|trt|j|fVqdS(N(RsRRRF(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys ss, css|]}t|VqdS(N(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys =ss*Missing one or more required elements (%s)(RRRvtopt1mapRsRRFRst optionalsR0tmultioptionalsRt multirequiredtrequiredRRRRRRRtremoveRRRtsumR (RRERRRtopt1topt2ttmpLocttmpReqdttmpOptt matchOrdert keepMatchingttmpExprstfailedtmissingR|R;t finalResults((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRsP .5 117      "   > cCsVt|dr|jS|jdkrOddjd|jDd|_n|jS(NRRs & css|]}t|VqdS(N(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys PsR(RRRmRRRv(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRKs *cCs3||g}x|jD]}|j|qWdS(N(RvR(RRRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRTs(RRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s 5  1 cBs_eZdZedZedZdZdZdZ dZ gdZ dZ RS( sa Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. cCstt|j|t|trattjtrItj|}qatjt |}n||_ d|_ |dk r|j |_ |j|_|j|j|j|_|j|_|j|_|jj|jndS(N(R RRRsRt issubclassR"RiR*RRFRRmRxRsRRqRpRoR}RuR(RRFR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR^s        cCsG|jdk r+|jj|||dtStd||j|dS(NRRr(RFRRRRRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRpscCs>t|_|jj|_|jdk r:|jjn|S(N(RRpRFRRR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRvs  cCst|trc||jkrtt|j||jdk r`|jj|jdq`qn?tt|j||jdk r|jj|jdn|S(Ni(RsR)RuR RRRFR(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR}s cCs6tt|j|jdk r2|jjn|S(N(R RRRFR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCsV||kr"t||gn||g}|jdk rR|jj|ndS(N(R$RFRR(RRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs  cCsA||g}|jdk r0|jj|n|jgdS(N(RFRRR(RRRy((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCsuytt|jSWntk r*nX|jdkrn|jdk rnd|jjt |jf|_n|jS(Ns%s:(%s)( R RRRaRmRRFR^RR(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs %( RRRRRRRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRZs      cBs#eZdZdZedZRS(s 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']] cCs#tt|j|t|_dS(N(R R RRRs(RRF((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCs|jj|||gfS(N(RFR(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR s cBs,eZdZdZedZdZRS(s 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:: cCsBtt|j|t|_t|_dt|j|_ dS(NsFound unwanted token, ( R RRRRpRRsRRFRy(RRF((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs  cCs:|jj||r0t|||j|n|gfS(N(RFRRRy(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCsIt|dr|jS|jdkrBdt|jd|_n|jS(NRs~{R(RRRmRRRF(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs (RRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs   t_MultipleMatchcBs eZddZedZRS(cCsftt|j|t|_|}t|trFtj|}n|dk rY|nd|_ dS(N( R RRRRoRsRR"RiRt not_ender(RRFtstopOntender((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs  c Cs|jj}|j}|jdk }|r9|jj}n|rO|||n||||dt\}}y|j } xo|r|||n| r|||} n|} ||| |\}} | s| jr~|| 7}q~q~WWnt t fk rnX||fS(NR( RFRRRRRRRuRRR( RRERRtself_expr_parsetself_skip_ignorablest check_endert try_not_enderRthasIgnoreExprsRt tmptokens((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs,   N(RRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs cBseZdZdZRS(s 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() cCsIt|dr|jS|jdkrBdt|jd|_n|jS(NRRs}...(RRRmRRRF(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR!s (RRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscBs/eZdZddZedZdZRS(sw 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} cCs)tt|j|d|t|_dS(NR(R R0RRRs(RRFR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR6scCsEy tt|j|||SWnttfk r@|gfSXdS(N(R R0RRR(RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR:s cCsIt|dr|jS|jdkrBdt|jd|_n|jS(NRRs]...(RRRmRRRF(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR@s N(RRRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR0*s   t _NullTokencBs eZdZeZdZRS(cCstS(N(R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRJscCsdS(NRr((R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRMs(RRRR>R(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRIs cBs/eZdZedZedZdZRS(sa 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) cCsAtt|j|dt|jj|_||_t|_dS(NR( R RRRRFRoRRRs(RRFR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRts cCsy(|jj|||dt\}}Wnottfk r|jtk r|jjrt|jg}|j||jj ['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...) RrcCsQtt|j||r)|jn||_t|_||_t|_dS(N( R RRRtadjacentRRpt joinStringR}(RRFRR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRrs    cCs6|jrtj||ntt|j||S(N(RR"RR R(RR ((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR|s cCse|j}|2|tdj|j|jgd|j7}|jr]|jr]|gS|SdS(NRrR(RR RRRRzRnR(RRERRtretToks((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs  1(RRRRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRas cBs eZdZdZdZRS(s 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']] cCs#tt|j|t|_dS(N(R RRRRo(RRF((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCs|gS(N((RRERR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs(RRRRR(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRs  cBs eZdZdZdZRS(sW 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. cCs#tt|j|t|_dS(N(R R RRRo(RRF((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRscCsTx9t|D]+\}}t|dkr1q n|d}t|trct|dj}nt|dkrtd|||nX|S(ss 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) s< ['aa', 'bb', 'cc'] delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] s [Rs]...N(RRR0RR)(RFtdelimtcombinetdlName((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR>9s ,!cstfd}|dkrBttjd}n |j}|jd|j|dt|jdt dS(s: 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|p5tt>gS(Ni(RRRA(RRNRpR(t arrayExprRF(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytcountFieldParseAction_s -cSst|dS(Ni(Ro(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqdRrtarrayLenR~s(len) s...N( R RR-RPRzRRRRR(RFtintExprR((RRFsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR:Ls    cCsMg}x@|D]8}t|tr8|jt|q |j|q W|S(N(RsRRRR(tLR}R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRks  csFtfd}|j|dtjdt|S(s* 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. csc|rTt|dkr'|d>q_t|j}td|D>n t>dS(Niicss|]}t|VqdS(N(R(Rttt((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys s(RRRRR (RRNRpttflat(trep(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytcopyTokenToRepeaters R~s(prev) (R RRRR(RFR((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRMts  cs\t|j}|Kfd}|j|dtjdt|S(sS 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. cs8t|jfd}j|dtdS(Ncs7t|j}|kr3tdddndS(NRri(RRR(RRNRpt theseTokens(t matchTokens(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytmustMatchTheseTokenss R~(RRRzR(RRNRpR(R(RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRsR~s(prev) (R RRRRR(RFte2R((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRLs   cCsUx$dD]}|j|t|}qW|jdd}|jdd}t|S(Ns\^-]s s\ns s\t(Rt_bslashR(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyREs  c sD|r!d}d}tnd}d}tg}t|tr]|j}n7t|tjr~t|}ntj dt dd|st Sd}x|t |d krV||}xt ||d D]f\}} || |r |||d =Pq||| r|||d =|j|| | }PqqW|d 7}qW| r|ryt |t d j|krtd d jd |Djd j|Stdjd|Djd j|SWqtk rtj dt ddqXntfd|Djd j|S(s 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,(R tb((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrcSs|jj|jS(N(R,R)(R R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrcSs ||kS(N((R R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrcSs |j|S(N(R)(R R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrs6Invalid argument to oneOf, expected string or iterableRiiiRrs[%s]css|]}t|VqdS(N(RE(Rtsym((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys ss | t|css|]}tj|VqdS(N(R|RG(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys ss7Exception creating Regex for oneOf, building MatchFirstc3s|]}|VqdS(N((RR(tparseElementClass(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys s(RRRsRRRRwRRRRRRRRRR%RRaR( tstrsR+tuseRegextisequaltmaskstsymbolsRtcurRR ((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRQsL        ! !33  cCsttt||S(s 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 R0R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR?s!cCs|tjd}|j}t|_|d||d}|rVd}n d}|j||j|_|S(s 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(N((RRRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRq8Rrt_original_startt _original_endcSs||j|j!S(N(RR(RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRq=RrcSs'||jd|jd!g|(dS(NRR(R(RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt extractText?s(R RzRRR}Ru(RFtasStringt locMarkert endlocMarkert matchExprR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRe s      cCst|jdS(sp Helper to undo pyparsing's default grouping of And expressions, even if all but one are non-empty. cSs|dS(Ni((Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqJRr(R+Rz(RF((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRfEscCsEtjd}t|d|d|jjdS(s 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(N((RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRq`Rrt locn_startRtlocn_end(R RzRRR(RFtlocator((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRhLss\[]-*.$+^?()~ RKcCs |ddS(Nii((RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqkRrs\\0?[xX][0-9a-fA-F]+cCs tt|djddS(Nis\0xi(tunichrRotlstrip(RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqlRrs \\0[0-7]+cCstt|dddS(Niii(RRo(RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqmRrR<s\]s\wRzRRtnegatetbodyRcsOdy-djfdtj|jDSWntk rJdSXdS(s 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.) cSsKt|ts|Sdjdtt|dt|ddDS(NRrcss|]}t|VqdS(N(R(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys sii(RsR RRtord(tp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrRrc3s|]}|VqdS(N((Rtpart(t _expanded(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys sN(Rt_reBracketExprRRRa(R((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyR]rs  - csfd}|S(st Helper method for defining parse actions that require matching at a specific column in the input text. cs2t||kr.t||dndS(Nsmatched token not at column %d(R7R(R@tlocnRJ(R(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt verifyCols((RR((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRKscs fdS(s 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(N((RRNRp(treplStr(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRr((R((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRZs cCs|ddd!S(s 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"] iii((RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRXs csafd}y"tdtdj}Wntk rSt}nX||_|S(sG 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'] cs g|D]}|^qS(N((RRNRpttokn(RRO(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRsRR^(R`RRaRu(RORRRd((RROsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRks    cCst|jS(N(RR,(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrcCst|jS(N(Rtlower(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrcCs<t|tr+|}t|d| }n |j}tttd}|rtjj t }t d|dt t t|t d|tddtgjdj d t d }nd jd tD}tjj t t|B}t d|dt t t|j ttt d|tddtgjdj d t d }ttd|d }|jdd j|jddjjjd|}|jdd j|jddjjjd|}||_||_||fS(sRInternal helper to construct opening and closing tag expressions, given a tag nameR+s_-:Rttagt=t/RRAcSs|ddkS(NiR((RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrR Rrcss!|]}|dkr|VqdS(R N((RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys scSs|ddkS(NiR((RRNRp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrsRLs(RsRRRR-R2R1R<RRzRXR)R R0RRRRRRTRWR@Rt_LRttitleRRR(ttagStrtxmltresnamet tagAttrNamet tagAttrValuetopenTagtprintablesLessRAbracktcloseTag((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt _makeTagss" o{AA  cCs t|tS(s  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 (R R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRIscCs t|tS(s 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} (R R(R((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRJscsT|r|n |jgD]\}}||f^q#fd}|S(s< 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 csx~D]v\}}||kr8t||d|n|tjkr|||krt||d||||fqqWdS(Nsno matching attribute s+attribute '%s' has value '%s', must be '%s'(RRct ANY_VALUE(RRNRtattrNamet attrValue(tattrs(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRRs   (R(RtattrDictRRR((RsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRcs 2  %cCs'|rd|nd}ti||6S(s 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 s%s:classtclass(Rc(t classnamet namespacet classattr((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRi\s t(RYcCs<t}||||B}xt|D]\}}|d d \}} } } | dkrdd|nd|} | dkr|d kst|dkrtdn|\} }ntj| }| tjkr| dkr t||t |t |}q| dkrx|d k rQt|||t |t ||}qt||t |t |}q| dkrt|| |||t || |||}qtdn+| tj kr| dkr)t |t st |}nt|j|t ||}q| dkr|d k rpt|||t |t ||}qt||t |t |}q| dkrt|| |||t || |||}qtdn td | r |j| n||j| |BK}|}q(W||K}|S( s 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]]] iis%s terms %s%s termis@if numterms=3, opExpr must be a tuple or list of two expressionsis6operator must be unary (1), binary (2), or ternary (3)s2operator must indicate right or left associativityN(N(R RRRRRRRtLEFTR RRtRIGHTRsRRFRz(tbaseExprtopListtlpartrparR}tlastExprRtoperDeftopExprtaritytrightLeftAssocRttermNametopExpr1topExpr2tthisExprR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRgsR;    '  /'   $  /'     s4"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*t"s string enclosed in double quotess4'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*t's string enclosed in single quotess*quotedString using single or double quotestusunicode string literalcCs!||krtdn|d krt|trt|trt|dkrt|dkr|d k rtt|t||tj ddj d}q|t j t||tj j d}q|d k r9tt|t |t |ttj ddj d}qttt |t |ttj ddj d}qtdnt}|d k r|tt|t||B|Bt|K}n.|tt|t||Bt|K}|jd ||f|S( s~ 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']] s.opening and closing strings cannot be the sameiRKcSs|djS(Ni(R(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRq9RrcSs|djS(Ni(R(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRq<RrcSs|djS(Ni(R(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqBRrcSs|djS(Ni(R(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqFRrsOopening and closing arguments must be strings if no content expression is givensnested %s%s expressionN(RRRsRRRRRR"RfRzRARRR RR)R0R(topenertclosertcontentRR}((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRNs4:  $  $    5.c s5fd}fd}fd}ttjdj}ttj|jd}tj|jd}tj|jd} |rtt||t|t|t|| } n0tt|t|t|t|} |j t t| jdS( s 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']]]]]]] css|t|krdSt||}|dkro|dkrZt||dnt||dndS(Nisillegal nestingsnot a peer entry(RR7RR(RRNRptcurCol(t indentStack(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytcheckPeerIndentscsEt||}|dkr/j|nt||ddS(Nisnot a subentry(R7RR(RRNRpR+(R,(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytcheckSubIndentscsn|t|krdSt||}oH|dkoH|dks`t||dnjdS(Niisnot an unindent(RR7RR(RRNRpR+(R,(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt checkUnindents &s tINDENTRrtUNINDENTsindented block( RRRRR RzRRRRR( tblockStatementExprR,R$R-R.R/R7R0tPEERtUNDENTtsmExpr((R,sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRdQsN"8 $s#[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]s[\0xa1-\0xbf\0xd7\0xf7]s_:sany tagsgt lt amp nbsp quot aposs><& "'s &(?PRs);scommon HTML entitycCstj|jS(sRHelper parser action to replace common HTML entities with their special characters(t_htmlEntityMapRtentity(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRYss/\*(?:[^*]|\*(?!/))*s*/sC style commentss HTML comments.*s rest of lines//(?:\\\n|[^\n])*s // commentsC++ style comments#.*sPython style comments t commaItemRcBseZdZeeZeeZee j dj eZ ee j dj eedZedj dj eZej edej ej dZejdeeeed jeBj d Zejeed j d j eZed j dj eZeeBeBjZedj dj eZeededj dZedj dZedj dZ e de dj dZ!ee de d8dee de d9j dZ"e"j#ddej d Z$e%e!e$Be"Bj d!j d!Z&ed"j d#Z'e(d$d%Z)e(d&d'Z*ed(j d)Z+ed*j d+Z,ed,j d-Z-e.je/jBZ0e(d.Z1e%e2e3d/e4ee5d0d/ee6d1jj d2Z7e8ee9j:e7Bd3d4j d5Z;e(ed6Z<e(ed7Z=RS(:s 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')] tintegers hex integeris[+-]?\d+ssigned integerRtfractioncCs|d|dS(Nii((Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrRzs"fraction or mixed integer-fractions [+-]?\d+\.\d*s real numbers+[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)s$real number with scientific notations[+-]?\d+\.?\d*([eE][+-]?\d+)?tfnumberRt identifiersK(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}s IPv4 addresss[0-9a-fA-F]{1,4}t hex_integerRisfull IPv6 addressiis::sshort IPv6 addresscCstd|DdkS(Ncss'|]}tjj|rdVqdS(iN(Rlt _ipv6_partR(RR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pys si(R(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrs::ffff:smixed IPv6 addresss IPv6 addresss:[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}s MAC addresss%Y-%m-%dcsfd}|S(s 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)] csPytj|djSWn+tk rK}t||t|nXdS(Ni(RtstrptimetdateRRRu(RRNRptve(tfmt(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytcvt_fns((RBRC((RBsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt convertToDatess%Y-%m-%dT%H:%M:%S.%fcsfd}|S(s 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)] csJytj|dSWn+tk rE}t||t|nXdS(Ni(RR?RRRu(RRNRpRA(RB(sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRCs((RBRC((RBsC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pytconvertToDatetimess7(?P\d{4})(?:-(?P\d\d)(?:-(?P\d\d))?)?s ISO8601 dates(?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)?sISO8601 datetimes2[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}tUUIDcCstjj|dS(s 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' i(Rlt_html_stripperR{(RRNR((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt stripHTMLTagss RR<s R8RRrscomma separated listcCst|jS(N(RR,(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRrcCst|jS(N(RR(Rp((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRqRr(ii(ii(>RRRRkRotconvertToIntegertfloattconvertToFloatR-RPRRzR9RBR=R%tsigned_integerR:RRRt mixed_integerRtrealtsci_realRtnumberR;R2R1R<t ipv4_addressR>t_full_ipv6_addresst_short_ipv6_addressRt_mixed_ipv6_addressRt ipv6_addresst mac_addressR#RDREt iso8601_datetiso8601_datetimetuuidR5R4RGRHRRRRTR,t _commasepitemR>RWRtcomma_separated_listRbR@(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyRlsL  '/-  ;&J+t__main__tselecttfroms_$RRtcolumnsRttablestcommandsK # '*' 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 s] 100 -100 +100 3.14159 6.02e23 1e-12 s 100 FF s6 12345678-1234-5678-1234-567812345678 (Rt __version__t__versionTime__t __author__RtweakrefRRRRxRR|RSRR8RRRRt_threadRt ImportErrort threadingRRt ordereddictRt__all__Rt version_infoRQRtmaxsizeR$RuRtchrRRRRR2treversedRRR4RxRIRJR_tmaxinttxrangeRt __builtin__RtfnameRR`RRRRRRtascii_uppercasetascii_lowercaseR2RPRBR1RRt printableRTRaRRRR!R$RR tMutableMappingtregisterR7RHRERGRKRMROReR"R*R RRRRiRRRRjR-R%R#RR,RpRRRR(R'R/R.RRRRR RR RRRR0RRRR&R RR+RRR R)RR`RR>R:RRMRLRERRQR?ReRfRhRRARGRFR_R^Rzt _escapedPunct_escapedHexChart_escapedOctChartUNICODEt _singleChart _charRangeRRR]RKRZRXRkRbR@R RIRJRcR RiRRRRRgRSR<R\RWRaRNRdR3RUR5R4RRR6RR9RYR6RCRR[R=R;RDRVRRZR8RlRt selectTokent fromTokentidentt columnNametcolumnNameListt columnSpect tableNamet tableNameListt simpleSQLR"RPR;R=RYRF(((sC/usr/lib/python2.7/site-packages/pkg_resources/_vendor/pyparsing.pyt=s              *         8      @ & A=IG3pLOD|M &# @sQ,A ,    I # %  !4@    ,   ?  #   k%Z r  (, #8+    $     PK@N#]/site-packages/pkg_resources/_vendor/__init__.pynu[PK@N#]C&fWfW.site-packages/pkg_resources/_vendor/appdirs.pynu[#!/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))) PK@N#]] dQdQ/site-packages/pkg_resources/_vendor/appdirs.pyonu[ fc@s@dZd,ZdjeeeZddlZddlZejddkZ e r^eZ nej j drddl Z e j ddZej d rd Zqej d rd Zqd Zn ej ZdddedZdddedZdddedZdddedZdddedZdddedZdefdYZdZdZdZdZed kr!yddlZ eZ!Wq!e"k ryddl#m$Z$eZ!Wqe"k ryddl%Z&eZ!Wqe"k reZ!qXqXq!Xne'dkr<dZ(dZ)d-Z*d$GHee(e)d%d&Z+x&e*D]Z,d'e,e-e+e,fGHq`Wd(GHee(e)Z+x&e*D]Z,d'e,e-e+e,fGHqWd)GHee(Z+x&e*D]Z,d'e,e-e+e,fGHqWd*GHee(d+eZ+x)e*D]Z,d'e,e-e+e,fGHqWndS(.syUtilities for determining application-specific dirs. See for details and usage. iiit.iNitjavatWindowstwin32tMactdarwintlinux2cCs6tdkr|dkr!|}n|r-dp0d}tjjt|}|r|tk rxtjj|||}qtjj||}qn{tdkrtjjd}|rtjj||}qn<tj dtjjd}|rtjj||}n|r2|r2tjj||}n|S( sJReturn 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/". Rt CSIDL_APPDATAtCSIDL_LOCAL_APPDATARs~/Library/Application Support/t XDG_DATA_HOMEs~/.local/shareN( tsystemtNonetostpathtnormpatht_get_win_foldertFalsetjoint expandusertgetenv(tappnamet appauthortversiontroamingtconstR ((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt user_data_dir-s&      cCstdkr|d kr!|}ntjjtd}|r|tk rftjj|||}q~tjj||}qntdkrtjjd}|rtjj||}qntj dtj jddg}g|j tj D]$}tjj|j tj ^q}|rs|rEtjj||}ng|D]}tj j||g^qL}n|rtj j|}n |d}|S|r|rtjj||}n|S( siReturn 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. RtCSIDL_COMMON_APPDATARs/Library/Application Supportt XDG_DATA_DIRSs/usr/local/shares /usr/shareiN(R R R R RRRRRRtpathseptsplittrstriptsep(RRRt multipathR txtpathlist((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt site_data_dirds4      =.  cCstdkr$t||d|}n<tjdtjjd}|r`tjj||}n|r|rtjj||}n|S(sReturn 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/". RRtXDG_CONFIG_HOMEs ~/.config(RRN(R RR R RR RR(RRRRR ((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pytuser_config_dirs  cCs tdkrBt||}|r|rtjj||}qntjdd}g|jtjD]$}tjj|j tj ^qg}|r|rtjj||}ng|D]}tj j||g^q}n|rtjj|}n |d}|S(sReturn 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. RRtXDG_CONFIG_DIRSs/etc/xdgi(RR( R R#R R RRRRRRR(RRRR R R!R"((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pytsite_config_dirs  =. cCsBtdkr|dkr!|}ntjjtd}|r|tk rftjj|||}ntjj||}|rtjj|d}qqn{tdkrtjjd}|rtjj||}qn<tj dtjjd}|rtjj||}n|r>|r>tjj||}n|S( sReturn 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. RRtCacheRs~/Library/CachestXDG_CACHE_HOMEs~/.cacheN( R R R R RRRRRR(RRRtopinionR ((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pytuser_cache_dirs(!      cCstdkr0tjjtjjd|}n{tdkrut|||}t}|rtjj|d}qn6t|||}t}|rtjj|d}n|r|rtjj||}n|S(sReturn 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. Rs~/Library/LogsRtLogstlog(R R R RRRRR+(RRRR*R ((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt user_log_dir:s     tAppDirscBs}eZdZddeedZedZedZedZ edZ edZ edZ RS( s1Convenience wrapper for getting application dirs.cCs1||_||_||_||_||_dS(N(RRRRR (tselfRRRRR ((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt__init__os     cCs%t|j|jd|jd|jS(NRR(RRRRR(R0((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyRwscCs%t|j|jd|jd|jS(NRR (R#RRRR (R0((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyR#|scCs%t|j|jd|jd|jS(NRR(R%RRRR(R0((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyR%scCs%t|j|jd|jd|jS(NRR (R'RRRR (R0((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyR'scCst|j|jd|jS(NR(R+RRR(R0((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyR+scCst|j|jd|jS(NR(R.RRR(R0((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyR.sN( t__name__t __module__t__doc__R RR1tpropertyRR#R%R'R+R.(((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyR/ms  cCs\ddl}idd6dd6dd6|}|j|jd }|j||\}}|S( sThis 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. iNtAppDataRsCommon AppDataRs Local AppDataRs@Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders(t_winregtOpenKeytHKEY_CURRENT_USERt QueryValueEx(t csidl_nameR7tshell_folder_nametkeytdirttype((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt_get_win_folder_from_registrys  cCsddlm}m}|jdt||dd}yt|}t}x*|D]"}t|dkrSt}PqSqSW|ryddl }|j |}Wqt k rqXnWnt k rnX|S(Ni(tshellcontshellii( twin32com.shellRARBtSHGetFolderPathtgetattrtunicodeRtordtTruetwin32apitGetShortPathNamet ImportErrort UnicodeError(R;RARBR>t has_high_chartcRI((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt_get_win_folder_with_pywin32s$!      cCsddl}idd6dd6dd6|}|jd}|jjjd|dd |t}x*|D]"}t|d krft}PqfqfW|r|jd}|jj j |j |dr|}qn|j S( NiiRi#RiRiii( tctypestcreate_unicode_buffertwindlltshell32tSHGetFolderPathWR RRGRHtkernel32tGetShortPathNameWtvalue(R;RPt csidl_consttbufRMRNtbuf2((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt_get_win_folder_with_ctypess$   c Cs=ddl}ddlm}ddlm}|jjd}|jd|}|jj }|j dt |j |d|j j||jj|jjd}t}x*|D]"} t| dkrt}PqqW|r9|jd|}|jj } tj|||r9|jj|jjd}q9n|S(Ni(tjna(RiRNsi(tarraytcom.sunR\tcom.sun.jna.platformRtWinDeftMAX_PATHtzerostShell32tINSTANCERDR REtShlObjtSHGFP_TYPE_CURRENTtNativettoStringttostringRRRGRHtKernel32tkernalRJ( R;R]R\Rtbuf_sizeRYRBR>RMRNtkernel((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt_get_win_folder_with_jnas&  +!  '(RRt__main__tMyAppt MyCompanyRR#R%R'R+R.s%-- app dirs (with optional 'version')Rs1.0s%s: %ss) -- app dirs (without optional 'version')s+ -- app dirs (without optional 'appauthor')s( -- app dirs (with disabled 'appauthor')R(iii(RR#R%R'R+R.(.R4t__version_info__Rtmaptstrt __version__tsysR t version_infotPY3RFtplatformt startswithtjava_vertos_nameR R RRR#R%R'RHR+R.tobjectR/R@ROR[RnRCtwin32comRRKRPRRt com.sun.jnatcomR2RRtpropstdirstpropRE(((sA/usr/lib/python2.7/site-packages/pkg_resources/_vendor/appdirs.pyt s~        7B(393+                   PK@N#]D\M0site-packages/pkg_resources/_vendor/__init__.pycnu[ fc@sdS(N((((sB/usr/lib/python2.7/site-packages/pkg_resources/_vendor/__init__.pyttPK@N#]%,,*site-packages/pkg_resources/py31compat.pyonu[ fc@sddlZddlZddlZedZejd kpzd ejkoYd knpzd ejkoxd knZerenejZdS(iNcCsJytj|Wn2tk rE}| s<|jtjkrFqFnXdS(N(tostmakedirstOSErrorterrnotEEXIST(tpathtexist_oktexc((s</usr/lib/python2.7/site-packages/pkg_resources/py31compat.pyt _makedirs_31s iiiiii(iii(ii(iii(ii(iii(RRtsystFalseRt version_infotneeds_makedirsR(((s</usr/lib/python2.7/site-packages/pkg_resources/py31compat.pyts    PK@N#]g g} } /site-packages/pkg_resources/extern/__init__.pyonu[ fc@s<ddlZdddYZd ZeeejdS( iNtVendorImportercBsJeZdZdddZedZddZdZdZ RS(s A PEP 302 meta path importer for finding optionally-vendored or otherwise naturally-installed packages from root_name. cCs7||_t||_|p-|jdd|_dS(Ntexternt_vendor(t root_nametsettvendored_namestreplacet vendor_pkg(tselfRRR((sA/usr/lib/python2.7/site-packages/pkg_resources/extern/__init__.pyt__init__ s ccs|jdVdVdS(sL Search first the vendor package then as a natural package. t.tN(R(R((sA/usr/lib/python2.7/site-packages/pkg_resources/extern/__init__.pyt search_paths cCsL|j|jd\}}}|r)dStt|j|jsHdS|S(s Return self when fullname starts with root_name and the target module is one vendored through this importer. R N(t partitionRtanytmapt startswithR(Rtfullnametpathtroottbasettarget((sA/usr/lib/python2.7/site-packages/pkg_resources/extern/__init__.pyt find_modules cCs|j|jd\}}}x|jD]l}yR||}t|tj|}|tj|s DPK@N#]uy .site-packages/pkg_resources/extern/__init__.pynu[import sys class VendorImporter: """ A PEP 302 meta path importer for finding optionally-vendored or otherwise naturally-installed packages from root_name. """ def __init__(self, root_name, vendored_names=(), vendor_pkg=None): self.root_name = root_name self.vendored_names = set(vendored_names) self.vendor_pkg = vendor_pkg or root_name.replace('extern', '_vendor') @property def search_path(self): """ Search first the vendor package then as a natural package. """ yield self.vendor_pkg + '.' yield '' def find_module(self, fullname, path=None): """ Return self when fullname starts with root_name and the target module is one vendored through this importer. """ root, base, target = fullname.partition(self.root_name + '.') if root: return if not any(map(target.startswith, self.vendored_names)): return return self def load_module(self, fullname): """ Iterate over the search path to locate and load fullname. """ root, base, target = fullname.partition(self.root_name + '.') for prefix in self.search_path: try: extant = prefix + target __import__(extant) mod = sys.modules[extant] sys.modules[fullname] = mod # mysterious hack: # Remove the reference to the extant package/module # on later Python versions to cause relative imports # in the vendor package to resolve the same modules # as those going through this importer. if sys.version_info > (3, 3): del sys.modules[extant] return mod except ImportError: pass else: raise ImportError( "The '{target}' package is required; " "normally this is bundled with this package so if you get " "this warning, consult the packager of your " "distribution.".format(**locals()) ) def install(self): """ Install this importer into sys.meta_path if not already present. """ if self not in sys.meta_path: sys.meta_path.append(self) names = 'packaging', 'pyparsing', 'six', 'appdirs' VendorImporter(__name__, names).install() PK@N#]g g} } /site-packages/pkg_resources/extern/__init__.pycnu[ fc@s<ddlZdddYZd ZeeejdS( iNtVendorImportercBsJeZdZdddZedZddZdZdZ RS(s A PEP 302 meta path importer for finding optionally-vendored or otherwise naturally-installed packages from root_name. cCs7||_t||_|p-|jdd|_dS(Ntexternt_vendor(t root_nametsettvendored_namestreplacet vendor_pkg(tselfRRR((sA/usr/lib/python2.7/site-packages/pkg_resources/extern/__init__.pyt__init__ s ccs|jdVdVdS(sL Search first the vendor package then as a natural package. t.tN(R(R((sA/usr/lib/python2.7/site-packages/pkg_resources/extern/__init__.pyt search_paths cCsL|j|jd\}}}|r)dStt|j|jsHdS|S(s Return self when fullname starts with root_name and the target module is one vendored through this importer. R N(t partitionRtanytmapt startswithR(Rtfullnametpathtroottbasettarget((sA/usr/lib/python2.7/site-packages/pkg_resources/extern/__init__.pyt find_modules cCs|j|jd\}}}x|jD]l}yR||}t|tj|}|tj|s DPK@N#]CNP'site-packages/pkg_resources/__init__.pynu[# coding: utf-8 """ Package resource API -------------------- A resource is a logical file contained within a package, or a logical subdirectory thereof. The package resource API expects resource names to have their path parts separated with ``/``, *not* whatever the local path separator is. Do not use os.path operations to manipulate resource names being passed into the API. The package resource API is designed to work with normal filesystem packages, .egg files, and unpacked .egg files. It can also work in a limited way with .zip files and with custom PEP 302 loaders that support the ``get_data()`` method. """ from __future__ import absolute_import import sys import os import io import time import re import types import zipfile import zipimport import warnings import stat import functools import pkgutil import operator import platform import collections import plistlib import email.parser import errno import tempfile import textwrap import itertools import inspect from pkgutil import get_importer try: import _imp except ImportError: # Python 3.2 compatibility import imp as _imp from pkg_resources.extern import six from pkg_resources.extern.six.moves import urllib, map, filter # capture these to bypass sandboxing from os import utime try: from os import mkdir, rename, unlink WRITE_SUPPORT = True except ImportError: # no write support, probably under GAE WRITE_SUPPORT = False from os import open as os_open from os.path import isdir, split try: import importlib.machinery as importlib_machinery # access attribute to force import under delayed import mechanisms. importlib_machinery.__name__ except ImportError: importlib_machinery = None from . import py31compat from pkg_resources.extern import appdirs from pkg_resources.extern import packaging __import__('pkg_resources.extern.packaging.version') __import__('pkg_resources.extern.packaging.specifiers') __import__('pkg_resources.extern.packaging.requirements') __import__('pkg_resources.extern.packaging.markers') if (3, 0) < sys.version_info < (3, 3): raise RuntimeError("Python 3.3 or later is required") if six.PY2: # Those builtin exceptions are only defined in Python 3 PermissionError = None NotADirectoryError = None # declare some globals that will be defined later to # satisfy the linters. require = None working_set = None add_activation_listener = None resources_stream = None cleanup_resources = None resource_dir = None resource_stream = None set_extraction_path = None resource_isdir = None resource_string = None iter_entry_points = None resource_listdir = None resource_filename = None resource_exists = None _distribution_finders = None _namespace_handlers = None _namespace_packages = None class PEP440Warning(RuntimeWarning): """ Used when there is an issue with a version or specifier not complying with PEP 440. """ def parse_version(v): try: return packaging.version.Version(v) except packaging.version.InvalidVersion: return packaging.version.LegacyVersion(v) _state_vars = {} def _declare_state(vartype, **kw): globals().update(kw) _state_vars.update(dict.fromkeys(kw, vartype)) def __getstate__(): state = {} g = globals() for k, v in _state_vars.items(): state[k] = g['_sget_' + v](g[k]) return state def __setstate__(state): g = globals() for k, v in state.items(): g['_sset_' + _state_vars[k]](k, g[k], v) return state def _sget_dict(val): return val.copy() def _sset_dict(key, ob, state): ob.clear() ob.update(state) def _sget_object(val): return val.__getstate__() def _sset_object(key, ob, state): ob.__setstate__(state) _sget_none = _sset_none = lambda *args: None def get_supported_platform(): """Return this platform's maximum compatible version. distutils.util.get_platform() normally reports the minimum version of Mac OS X that would be required to *use* extensions produced by distutils. But what we want when checking compatibility is to know the version of Mac OS X that we are *running*. To allow usage of packages that explicitly require a newer version of Mac OS X, we must also know the current version of the OS. If this condition occurs for any other platform with a version in its platform strings, this function should be extended accordingly. """ plat = get_build_platform() m = macosVersionString.match(plat) if m is not None and sys.platform == "darwin": try: plat = 'macosx-%s-%s' % ('.'.join(_macosx_vers()[:2]), m.group(3)) except ValueError: # not Mac OS X pass return plat __all__ = [ # Basic resource access and distribution/entry point discovery 'require', 'run_script', 'get_provider', 'get_distribution', 'load_entry_point', 'get_entry_map', 'get_entry_info', 'iter_entry_points', 'resource_string', 'resource_stream', 'resource_filename', 'resource_listdir', 'resource_exists', 'resource_isdir', # Environmental control 'declare_namespace', 'working_set', 'add_activation_listener', 'find_distributions', 'set_extraction_path', 'cleanup_resources', 'get_default_cache', # Primary implementation classes 'Environment', 'WorkingSet', 'ResourceManager', 'Distribution', 'Requirement', 'EntryPoint', # Exceptions 'ResolutionError', 'VersionConflict', 'DistributionNotFound', 'UnknownExtra', 'ExtractionError', # Warnings 'PEP440Warning', # Parsing functions and string utilities 'parse_requirements', 'parse_version', 'safe_name', 'safe_version', 'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections', 'safe_extra', 'to_filename', 'invalid_marker', 'evaluate_marker', # filesystem utilities 'ensure_directory', 'normalize_path', # Distribution "precedence" constants 'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST', 'DEVELOP_DIST', # "Provider" interfaces, implementations, and registration/lookup APIs 'IMetadataProvider', 'IResourceProvider', 'FileMetadata', 'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider', 'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider', 'register_finder', 'register_namespace_handler', 'register_loader_type', 'fixup_namespace_packages', 'get_importer', # Deprecated/backward compatibility only 'run_main', 'AvailableDistributions', ] class ResolutionError(Exception): """Abstract base for dependency resolution errors""" def __repr__(self): return self.__class__.__name__ + repr(self.args) class VersionConflict(ResolutionError): """ An already-installed version conflicts with the requested version. Should be initialized with the installed Distribution and the requested Requirement. """ _template = "{self.dist} is installed but {self.req} is required" @property def dist(self): return self.args[0] @property def req(self): return self.args[1] def report(self): return self._template.format(**locals()) def with_context(self, required_by): """ If required_by is non-empty, return a version of self that is a ContextualVersionConflict. """ if not required_by: return self args = self.args + (required_by,) return ContextualVersionConflict(*args) class ContextualVersionConflict(VersionConflict): """ A VersionConflict that accepts a third parameter, the set of the requirements that required the installed Distribution. """ _template = VersionConflict._template + ' by {self.required_by}' @property def required_by(self): return self.args[2] class DistributionNotFound(ResolutionError): """A requested distribution was not found""" _template = ("The '{self.req}' distribution was not found " "and is required by {self.requirers_str}") @property def req(self): return self.args[0] @property def requirers(self): return self.args[1] @property def requirers_str(self): if not self.requirers: return 'the application' return ', '.join(self.requirers) def report(self): return self._template.format(**locals()) def __str__(self): return self.report() class UnknownExtra(ResolutionError): """Distribution doesn't have an "extra feature" of the given name""" _provider_factories = {} PY_MAJOR = sys.version[:3] EGG_DIST = 3 BINARY_DIST = 2 SOURCE_DIST = 1 CHECKOUT_DIST = 0 DEVELOP_DIST = -1 def register_loader_type(loader_type, provider_factory): """Register `provider_factory` to make providers for `loader_type` `loader_type` is the type or class of a PEP 302 ``module.__loader__``, and `provider_factory` is a function that, passed a *module* object, returns an ``IResourceProvider`` for that module. """ _provider_factories[loader_type] = provider_factory def get_provider(moduleOrReq): """Return an IResourceProvider for the named module or requirement""" if isinstance(moduleOrReq, Requirement): return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0] try: module = sys.modules[moduleOrReq] except KeyError: __import__(moduleOrReq) module = sys.modules[moduleOrReq] loader = getattr(module, '__loader__', None) return _find_adapter(_provider_factories, loader)(module) def _macosx_vers(_cache=[]): if not _cache: version = platform.mac_ver()[0] # fallback for MacPorts if version == '': plist = '/System/Library/CoreServices/SystemVersion.plist' if os.path.exists(plist): if hasattr(plistlib, 'readPlist'): plist_content = plistlib.readPlist(plist) if 'ProductVersion' in plist_content: version = plist_content['ProductVersion'] _cache.append(version.split('.')) return _cache[0] def _macosx_arch(machine): return {'PowerPC': 'ppc', 'Power_Macintosh': 'ppc'}.get(machine, machine) def get_build_platform(): """Return this platform's string for platform-specific distributions XXX Currently this is the same as ``distutils.util.get_platform()``, but it needs some hacks for Linux and Mac OS X. """ try: # Python 2.7 or >=3.2 from sysconfig import get_platform except ImportError: from distutils.util import get_platform plat = get_platform() if sys.platform == "darwin" and not plat.startswith('macosx-'): try: version = _macosx_vers() machine = os.uname()[4].replace(" ", "_") return "macosx-%d.%d-%s" % ( int(version[0]), int(version[1]), _macosx_arch(machine), ) except ValueError: # if someone is running a non-Mac darwin system, this will fall # through to the default implementation pass return plat macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)") darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)") # XXX backward compat get_platform = get_build_platform def compatible_platforms(provided, required): """Can code for the `provided` platform run on the `required` platform? Returns true if either platform is ``None``, or the platforms are equal. XXX Needs compatibility checks for Linux and other unixy OSes. """ if provided is None or required is None or provided == required: # easy case return True # Mac OS X special cases reqMac = macosVersionString.match(required) if reqMac: provMac = macosVersionString.match(provided) # is this a Mac package? if not provMac: # this is backwards compatibility for packages built before # setuptools 0.6. All packages built after this point will # use the new macosx designation. provDarwin = darwinVersionString.match(provided) if provDarwin: dversion = int(provDarwin.group(1)) macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2)) if dversion == 7 and macosversion >= "10.3" or \ dversion == 8 and macosversion >= "10.4": return True # egg isn't macosx or legacy darwin return False # are they the same major version and machine type? if provMac.group(1) != reqMac.group(1) or \ provMac.group(3) != reqMac.group(3): return False # is the required OS major update >= the provided one? if int(provMac.group(2)) > int(reqMac.group(2)): return False return True # XXX Linux and other platforms' special cases should go here return False def run_script(dist_spec, script_name): """Locate distribution `dist_spec` and run its `script_name` script""" ns = sys._getframe(1).f_globals name = ns['__name__'] ns.clear() ns['__name__'] = name require(dist_spec)[0].run_script(script_name, ns) # backward compatibility run_main = run_script def get_distribution(dist): """Return a current distribution object for a Requirement or string""" if isinstance(dist, six.string_types): dist = Requirement.parse(dist) if isinstance(dist, Requirement): dist = get_provider(dist) if not isinstance(dist, Distribution): raise TypeError("Expected string, Requirement, or Distribution", dist) return dist def load_entry_point(dist, group, name): """Return `name` entry point of `group` for `dist` or raise ImportError""" return get_distribution(dist).load_entry_point(group, name) def get_entry_map(dist, group=None): """Return the entry point map for `group`, or the full entry map""" return get_distribution(dist).get_entry_map(group) def get_entry_info(dist, group, name): """Return the EntryPoint object for `group`+`name`, or ``None``""" return get_distribution(dist).get_entry_info(group, name) class IMetadataProvider: def has_metadata(name): """Does the package's distribution contain the named metadata?""" def get_metadata(name): """The named metadata resource as a string""" def get_metadata_lines(name): """Yield named metadata resource as list of non-blank non-comment lines Leading and trailing whitespace is stripped from each line, and lines with ``#`` as the first non-blank character are omitted.""" def metadata_isdir(name): """Is the named metadata a directory? (like ``os.path.isdir()``)""" def metadata_listdir(name): """List of metadata names in the directory (like ``os.listdir()``)""" def run_script(script_name, namespace): """Execute the named script in the supplied namespace dictionary""" class IResourceProvider(IMetadataProvider): """An object that provides access to package resources""" def get_resource_filename(manager, resource_name): """Return a true filesystem path for `resource_name` `manager` must be an ``IResourceManager``""" def get_resource_stream(manager, resource_name): """Return a readable file-like object for `resource_name` `manager` must be an ``IResourceManager``""" def get_resource_string(manager, resource_name): """Return a string containing the contents of `resource_name` `manager` must be an ``IResourceManager``""" def has_resource(resource_name): """Does the package contain the named resource?""" def resource_isdir(resource_name): """Is the named resource a directory? (like ``os.path.isdir()``)""" def resource_listdir(resource_name): """List of resource names in the directory (like ``os.listdir()``)""" class WorkingSet(object): """A collection of active distributions on sys.path (or a similar list)""" def __init__(self, entries=None): """Create working set from list of path entries (default=sys.path)""" self.entries = [] self.entry_keys = {} self.by_key = {} self.callbacks = [] if entries is None: entries = sys.path for entry in entries: self.add_entry(entry) @classmethod def _build_master(cls): """ Prepare the master working set. """ ws = cls() try: from __main__ import __requires__ except ImportError: # The main program does not list any requirements return ws # ensure the requirements are met try: ws.require(__requires__) except VersionConflict: return cls._build_from_requirements(__requires__) return ws @classmethod def _build_from_requirements(cls, req_spec): """ Build a working set from a requirement spec. Rewrites sys.path. """ # try it without defaults already on sys.path # by starting with an empty path ws = cls([]) reqs = parse_requirements(req_spec) dists = ws.resolve(reqs, Environment()) for dist in dists: ws.add(dist) # add any missing entries from sys.path for entry in sys.path: if entry not in ws.entries: ws.add_entry(entry) # then copy back to sys.path sys.path[:] = ws.entries return ws def add_entry(self, entry): """Add a path item to ``.entries``, finding any distributions on it ``find_distributions(entry, True)`` is used to find distributions corresponding to the path entry, and they are added. `entry` is always appended to ``.entries``, even if it is already present. (This is because ``sys.path`` can contain the same value more than once, and the ``.entries`` of the ``sys.path`` WorkingSet should always equal ``sys.path``.) """ self.entry_keys.setdefault(entry, []) self.entries.append(entry) for dist in find_distributions(entry, True): self.add(dist, entry, False) def __contains__(self, dist): """True if `dist` is the active distribution for its project""" return self.by_key.get(dist.key) == dist def find(self, req): """Find a distribution matching requirement `req` If there is an active distribution for the requested project, this returns it as long as it meets the version requirement specified by `req`. But, if there is an active distribution for the project and it does *not* meet the `req` requirement, ``VersionConflict`` is raised. If there is no active distribution for the requested project, ``None`` is returned. """ dist = self.by_key.get(req.key) if dist is not None and dist not in req: # XXX add more info raise VersionConflict(dist, req) return dist def iter_entry_points(self, group, name=None): """Yield entry point objects from `group` matching `name` If `name` is None, yields all entry points in `group` from all distributions in the working set, otherwise only ones matching both `group` and `name` are yielded (in distribution order). """ for dist in self: entries = dist.get_entry_map(group) if name is None: for ep in entries.values(): yield ep elif name in entries: yield entries[name] def run_script(self, requires, script_name): """Locate distribution for `requires` and run `script_name` script""" ns = sys._getframe(1).f_globals name = ns['__name__'] ns.clear() ns['__name__'] = name self.require(requires)[0].run_script(script_name, ns) def __iter__(self): """Yield distributions for non-duplicate projects in the working set The yield order is the order in which the items' path entries were added to the working set. """ seen = {} for item in self.entries: if item not in self.entry_keys: # workaround a cache issue continue for key in self.entry_keys[item]: if key not in seen: seen[key] = 1 yield self.by_key[key] def add(self, dist, entry=None, insert=True, replace=False): """Add `dist` to working set, associated with `entry` If `entry` is unspecified, it defaults to the ``.location`` of `dist`. On exit from this routine, `entry` is added to the end of the working set's ``.entries`` (if it wasn't already present). `dist` is only added to the working set if it's for a project that doesn't already have a distribution in the set, unless `replace=True`. If it's added, any callbacks registered with the ``subscribe()`` method will be called. """ if insert: dist.insert_on(self.entries, entry, replace=replace) if entry is None: entry = dist.location keys = self.entry_keys.setdefault(entry, []) keys2 = self.entry_keys.setdefault(dist.location, []) if not replace and dist.key in self.by_key: # ignore hidden distros return self.by_key[dist.key] = dist if dist.key not in keys: keys.append(dist.key) if dist.key not in keys2: keys2.append(dist.key) self._added_new(dist) def resolve(self, requirements, env=None, installer=None, replace_conflicting=False, extras=None): """List all distributions needed to (recursively) meet `requirements` `requirements` must be a sequence of ``Requirement`` objects. `env`, if supplied, should be an ``Environment`` instance. If not supplied, it defaults to all distributions available within any entry or distribution in the working set. `installer`, if supplied, will be invoked with each requirement that cannot be met by an already-installed distribution; it should return a ``Distribution`` or ``None``. Unless `replace_conflicting=True`, raises a VersionConflict exception if any requirements are found on the path that have the correct name but the wrong version. Otherwise, if an `installer` is supplied it will be invoked to obtain the correct version of the requirement and activate it. `extras` is a list of the extras to be used with these requirements. This is important because extra requirements may look like `my_req; extra = "my_extra"`, which would otherwise be interpreted as a purely optional requirement. Instead, we want to be able to assert that these requirements are truly required. """ # set up the stack requirements = list(requirements)[::-1] # set of processed requirements processed = {} # key -> dist best = {} to_activate = [] req_extras = _ReqExtras() # Mapping of requirement to set of distributions that required it; # useful for reporting info about conflicts. required_by = collections.defaultdict(set) while requirements: # process dependencies breadth-first req = requirements.pop(0) if req in processed: # Ignore cyclic or redundant dependencies continue if not req_extras.markers_pass(req, extras): continue dist = best.get(req.key) if dist is None: # Find the best distribution and add it to the map dist = self.by_key.get(req.key) if dist is None or (dist not in req and replace_conflicting): ws = self if env is None: if dist is None: env = Environment(self.entries) else: # Use an empty environment and workingset to avoid # any further conflicts with the conflicting # distribution env = Environment([]) ws = WorkingSet([]) dist = best[req.key] = env.best_match( req, ws, installer, replace_conflicting=replace_conflicting ) if dist is None: requirers = required_by.get(req, None) raise DistributionNotFound(req, requirers) to_activate.append(dist) if dist not in req: # Oops, the "best" so far conflicts with a dependency dependent_req = required_by[req] raise VersionConflict(dist, req).with_context(dependent_req) # push the new requirements onto the stack new_requirements = dist.requires(req.extras)[::-1] requirements.extend(new_requirements) # Register the new requirements needed by req for new_requirement in new_requirements: required_by[new_requirement].add(req.project_name) req_extras[new_requirement] = req.extras processed[req] = True # return list of distros to activate return to_activate def find_plugins( self, plugin_env, full_env=None, installer=None, fallback=True): """Find all activatable distributions in `plugin_env` Example usage:: distributions, errors = working_set.find_plugins( Environment(plugin_dirlist) ) # add plugins+libs to sys.path map(working_set.add, distributions) # display errors print('Could not load', errors) The `plugin_env` should be an ``Environment`` instance that contains only distributions that are in the project's "plugin directory" or directories. The `full_env`, if supplied, should be an ``Environment`` contains all currently-available distributions. If `full_env` is not supplied, one is created automatically from the ``WorkingSet`` this method is called on, which will typically mean that every directory on ``sys.path`` will be scanned for distributions. `installer` is a standard installer callback as used by the ``resolve()`` method. The `fallback` flag indicates whether we should attempt to resolve older versions of a plugin if the newest version cannot be resolved. This method returns a 2-tuple: (`distributions`, `error_info`), where `distributions` is a list of the distributions found in `plugin_env` that were loadable, along with any other distributions that are needed to resolve their dependencies. `error_info` is a dictionary mapping unloadable plugin distributions to an exception instance describing the error that occurred. Usually this will be a ``DistributionNotFound`` or ``VersionConflict`` instance. """ plugin_projects = list(plugin_env) # scan project names in alphabetic order plugin_projects.sort() error_info = {} distributions = {} if full_env is None: env = Environment(self.entries) env += plugin_env else: env = full_env + plugin_env shadow_set = self.__class__([]) # put all our entries in shadow_set list(map(shadow_set.add, self)) for project_name in plugin_projects: for dist in plugin_env[project_name]: req = [dist.as_requirement()] try: resolvees = shadow_set.resolve(req, env, installer) except ResolutionError as v: # save error info error_info[dist] = v if fallback: # try the next older version of project continue else: # give up on this project, keep going break else: list(map(shadow_set.add, resolvees)) distributions.update(dict.fromkeys(resolvees)) # success, no need to try any more versions of this project break distributions = list(distributions) distributions.sort() return distributions, error_info def require(self, *requirements): """Ensure that distributions matching `requirements` are activated `requirements` must be a string or a (possibly-nested) sequence thereof, specifying the distributions and versions required. The return value is a sequence of the distributions that needed to be activated to fulfill the requirements; all relevant distributions are included, even if they were already activated in this working set. """ needed = self.resolve(parse_requirements(requirements)) for dist in needed: self.add(dist) return needed def subscribe(self, callback, existing=True): """Invoke `callback` for all distributions If `existing=True` (default), call on all existing ones, as well. """ if callback in self.callbacks: return self.callbacks.append(callback) if not existing: return for dist in self: callback(dist) def _added_new(self, dist): for callback in self.callbacks: callback(dist) def __getstate__(self): return ( self.entries[:], self.entry_keys.copy(), self.by_key.copy(), self.callbacks[:] ) def __setstate__(self, e_k_b_c): entries, keys, by_key, callbacks = e_k_b_c self.entries = entries[:] self.entry_keys = keys.copy() self.by_key = by_key.copy() self.callbacks = callbacks[:] class _ReqExtras(dict): """ Map each requirement to the extras that demanded it. """ def markers_pass(self, req, extras=None): """ Evaluate markers for req against each extra that demanded it. Return False if the req has a marker and fails evaluation. Otherwise, return True. """ extra_evals = ( req.marker.evaluate({'extra': extra}) for extra in self.get(req, ()) + (extras or (None,)) ) return not req.marker or any(extra_evals) class Environment(object): """Searchable snapshot of distributions on a search path""" def __init__( self, search_path=None, platform=get_supported_platform(), python=PY_MAJOR): """Snapshot distributions available on a search path Any distributions found on `search_path` are added to the environment. `search_path` should be a sequence of ``sys.path`` items. If not supplied, ``sys.path`` is used. `platform` is an optional string specifying the name of the platform that platform-specific distributions must be compatible with. If unspecified, it defaults to the current platform. `python` is an optional string naming the desired version of Python (e.g. ``'3.3'``); it defaults to the current version. You may explicitly set `platform` (and/or `python`) to ``None`` if you wish to map *all* distributions, not just those compatible with the running platform or Python version. """ self._distmap = {} self.platform = platform self.python = python self.scan(search_path) def can_add(self, dist): """Is distribution `dist` acceptable for this environment? The distribution must match the platform and python version requirements specified when this environment was created, or False is returned. """ py_compat = ( self.python is None or dist.py_version is None or dist.py_version == self.python ) return py_compat and compatible_platforms(dist.platform, self.platform) def remove(self, dist): """Remove `dist` from the environment""" self._distmap[dist.key].remove(dist) def scan(self, search_path=None): """Scan `search_path` for distributions usable in this environment Any distributions found are added to the environment. `search_path` should be a sequence of ``sys.path`` items. If not supplied, ``sys.path`` is used. Only distributions conforming to the platform/python version defined at initialization are added. """ if search_path is None: search_path = sys.path for item in search_path: for dist in find_distributions(item): self.add(dist) def __getitem__(self, project_name): """Return a newest-to-oldest list of distributions for `project_name` Uses case-insensitive `project_name` comparison, assuming all the project's distributions use their project's name converted to all lowercase as their key. """ distribution_key = project_name.lower() return self._distmap.get(distribution_key, []) def add(self, dist): """Add `dist` if we ``can_add()`` it and it has not already been added """ if self.can_add(dist) and dist.has_version(): dists = self._distmap.setdefault(dist.key, []) if dist not in dists: dists.append(dist) dists.sort(key=operator.attrgetter('hashcmp'), reverse=True) def best_match( self, req, working_set, installer=None, replace_conflicting=False): """Find distribution best matching `req` and usable on `working_set` This calls the ``find(req)`` method of the `working_set` to see if a suitable distribution is already active. (This may raise ``VersionConflict`` if an unsuitable version of the project is already active in the specified `working_set`.) If a suitable distribution isn't active, this method returns the newest distribution in the environment that meets the ``Requirement`` in `req`. If no suitable distribution is found, and `installer` is supplied, then the result of calling the environment's ``obtain(req, installer)`` method will be returned. """ try: dist = working_set.find(req) except VersionConflict: if not replace_conflicting: raise dist = None if dist is not None: return dist for dist in self[req.key]: if dist in req: return dist # try to download/install return self.obtain(req, installer) def obtain(self, requirement, installer=None): """Obtain a distribution matching `requirement` (e.g. via download) Obtain a distro that matches requirement (e.g. via download). In the base ``Environment`` class, this routine just returns ``installer(requirement)``, unless `installer` is None, in which case None is returned instead. This method is a hook that allows subclasses to attempt other ways of obtaining a distribution before falling back to the `installer` argument.""" if installer is not None: return installer(requirement) def __iter__(self): """Yield the unique project names of the available distributions""" for key in self._distmap.keys(): if self[key]: yield key def __iadd__(self, other): """In-place addition of a distribution or environment""" if isinstance(other, Distribution): self.add(other) elif isinstance(other, Environment): for project in other: for dist in other[project]: self.add(dist) else: raise TypeError("Can't add %r to environment" % (other,)) return self def __add__(self, other): """Add an environment or distribution to an environment""" new = self.__class__([], platform=None, python=None) for env in self, other: new += env return new # XXX backward compatibility AvailableDistributions = Environment class ExtractionError(RuntimeError): """An error occurred extracting a resource The following attributes are available from instances of this exception: manager The resource manager that raised this exception cache_path The base directory for resource extraction original_error The exception instance that caused extraction to fail """ class ResourceManager: """Manage resource extraction and packages""" extraction_path = None def __init__(self): self.cached_files = {} def resource_exists(self, package_or_requirement, resource_name): """Does the named resource exist?""" return get_provider(package_or_requirement).has_resource(resource_name) def resource_isdir(self, package_or_requirement, resource_name): """Is the named resource an existing directory?""" return get_provider(package_or_requirement).resource_isdir( resource_name ) def resource_filename(self, package_or_requirement, resource_name): """Return a true filesystem path for specified resource""" return get_provider(package_or_requirement).get_resource_filename( self, resource_name ) def resource_stream(self, package_or_requirement, resource_name): """Return a readable file-like object for specified resource""" return get_provider(package_or_requirement).get_resource_stream( self, resource_name ) def resource_string(self, package_or_requirement, resource_name): """Return specified resource as a string""" return get_provider(package_or_requirement).get_resource_string( self, resource_name ) def resource_listdir(self, package_or_requirement, resource_name): """List the contents of the named resource directory""" return get_provider(package_or_requirement).resource_listdir( resource_name ) def extraction_error(self): """Give an error message for problems extracting file(s)""" old_exc = sys.exc_info()[1] cache_path = self.extraction_path or get_default_cache() tmpl = textwrap.dedent(""" Can't extract file(s) to egg cache The following error occurred while trying to extract file(s) to the Python egg cache: {old_exc} The Python egg cache directory is currently set to: {cache_path} Perhaps your account does not have write access to this directory? You can change the cache directory by setting the PYTHON_EGG_CACHE environment variable to point to an accessible directory. """).lstrip() err = ExtractionError(tmpl.format(**locals())) err.manager = self err.cache_path = cache_path err.original_error = old_exc raise err def get_cache_path(self, archive_name, names=()): """Return absolute location in cache for `archive_name` and `names` The parent directory of the resulting path will be created if it does not already exist. `archive_name` should be the base filename of the enclosing egg (which may not be the name of the enclosing zipfile!), including its ".egg" extension. `names`, if provided, should be a sequence of path name parts "under" the egg's extraction location. This method should only be called by resource providers that need to obtain an extraction location, and only for names they intend to extract, as it tracks the generated names for possible cleanup later. """ extract_path = self.extraction_path or get_default_cache() target_path = os.path.join(extract_path, archive_name + '-tmp', *names) try: _bypass_ensure_directory(target_path) except Exception: self.extraction_error() self._warn_unsafe_extraction_path(extract_path) self.cached_files[target_path] = 1 return target_path @staticmethod def _warn_unsafe_extraction_path(path): """ If the default extraction path is overridden and set to an insecure location, such as /tmp, it opens up an opportunity for an attacker to replace an extracted file with an unauthorized payload. Warn the user if a known insecure location is used. See Distribute #375 for more details. """ if os.name == 'nt' and not path.startswith(os.environ['windir']): # On Windows, permissions are generally restrictive by default # and temp directories are not writable by other users, so # bypass the warning. return mode = os.stat(path).st_mode if mode & stat.S_IWOTH or mode & stat.S_IWGRP: msg = ( "%s is writable by group/others and vulnerable to attack " "when " "used with get_resource_filename. Consider a more secure " "location (set with .set_extraction_path or the " "PYTHON_EGG_CACHE environment variable)." % path ) warnings.warn(msg, UserWarning) def postprocess(self, tempname, filename): """Perform any platform-specific postprocessing of `tempname` This is where Mac header rewrites should be done; other platforms don't have anything special they should do. Resource providers should call this method ONLY after successfully extracting a compressed resource. They must NOT call it on resources that are already in the filesystem. `tempname` is the current (temporary) name of the file, and `filename` is the name it will be renamed to by the caller after this routine returns. """ if os.name == 'posix': # Make the resource executable mode = ((os.stat(tempname).st_mode) | 0o555) & 0o7777 os.chmod(tempname, mode) def set_extraction_path(self, path): """Set the base path where resources will be extracted to, if needed. If you do not call this routine before any extractions take place, the path defaults to the return value of ``get_default_cache()``. (Which is based on the ``PYTHON_EGG_CACHE`` environment variable, with various platform-specific fallbacks. See that routine's documentation for more details.) Resources are extracted to subdirectories of this path based upon information given by the ``IResourceProvider``. You may set this to a temporary directory, but then you must call ``cleanup_resources()`` to delete the extracted files when done. There is no guarantee that ``cleanup_resources()`` will be able to remove all extracted files. (Note: you may not change the extraction path for a given resource manager once resources have been extracted, unless you first call ``cleanup_resources()``.) """ if self.cached_files: raise ValueError( "Can't change extraction path, files already extracted" ) self.extraction_path = path def cleanup_resources(self, force=False): """ Delete all extracted resource files and directories, returning a list of the file and directory names that could not be successfully removed. This function does not have any concurrency protection, so it should generally only be called when the extraction path is a temporary directory exclusive to a single process. This method is not automatically called; you must call it explicitly or register it as an ``atexit`` function if you wish to ensure cleanup of a temporary directory used for extractions. """ # XXX def get_default_cache(): """ Return the ``PYTHON_EGG_CACHE`` environment variable or a platform-relevant user cache dir for an app named "Python-Eggs". """ return ( os.environ.get('PYTHON_EGG_CACHE') or appdirs.user_cache_dir(appname='Python-Eggs') ) def safe_name(name): """Convert an arbitrary string to a standard distribution name Any runs of non-alphanumeric/. characters are replaced with a single '-'. """ return re.sub('[^A-Za-z0-9.]+', '-', name) def safe_version(version): """ Convert an arbitrary string to a standard version string """ try: # normalize the version return str(packaging.version.Version(version)) except packaging.version.InvalidVersion: version = version.replace(' ', '.') return re.sub('[^A-Za-z0-9.]+', '-', version) def safe_extra(extra): """Convert an arbitrary string to a standard 'extra' name Any runs of non-alphanumeric characters are replaced with a single '_', and the result is always lowercased. """ return re.sub('[^A-Za-z0-9.-]+', '_', extra).lower() def to_filename(name): """Convert a project or version name to its filename-escaped form Any '-' characters are currently replaced with '_'. """ return name.replace('-', '_') def invalid_marker(text): """ Validate text as a PEP 508 environment marker; return an exception if invalid or False otherwise. """ try: evaluate_marker(text) except SyntaxError as e: e.filename = None e.lineno = None return e return False def evaluate_marker(text, extra=None): """ Evaluate a PEP 508 environment marker. Return a boolean indicating the marker result in this environment. Raise SyntaxError if marker is invalid. This implementation uses the 'pyparsing' module. """ try: marker = packaging.markers.Marker(text) return marker.evaluate() except packaging.markers.InvalidMarker as e: raise SyntaxError(e) class NullProvider: """Try to implement resources and metadata for arbitrary PEP 302 loaders""" egg_name = None egg_info = None loader = None def __init__(self, module): self.loader = getattr(module, '__loader__', None) self.module_path = os.path.dirname(getattr(module, '__file__', '')) def get_resource_filename(self, manager, resource_name): return self._fn(self.module_path, resource_name) def get_resource_stream(self, manager, resource_name): return io.BytesIO(self.get_resource_string(manager, resource_name)) def get_resource_string(self, manager, resource_name): return self._get(self._fn(self.module_path, resource_name)) def has_resource(self, resource_name): return self._has(self._fn(self.module_path, resource_name)) def has_metadata(self, name): return self.egg_info and self._has(self._fn(self.egg_info, name)) def get_metadata(self, name): if not self.egg_info: return "" value = self._get(self._fn(self.egg_info, name)) return value.decode('utf-8') if six.PY3 else value def get_metadata_lines(self, name): return yield_lines(self.get_metadata(name)) def resource_isdir(self, resource_name): return self._isdir(self._fn(self.module_path, resource_name)) def metadata_isdir(self, name): return self.egg_info and self._isdir(self._fn(self.egg_info, name)) def resource_listdir(self, resource_name): return self._listdir(self._fn(self.module_path, resource_name)) def metadata_listdir(self, name): if self.egg_info: return self._listdir(self._fn(self.egg_info, name)) return [] def run_script(self, script_name, namespace): script = 'scripts/' + script_name if not self.has_metadata(script): raise ResolutionError( "Script {script!r} not found in metadata at {self.egg_info!r}" .format(**locals()), ) script_text = self.get_metadata(script).replace('\r\n', '\n') script_text = script_text.replace('\r', '\n') script_filename = self._fn(self.egg_info, script) namespace['__file__'] = script_filename if os.path.exists(script_filename): source = open(script_filename).read() code = compile(source, script_filename, 'exec') exec(code, namespace, namespace) else: from linecache import cache cache[script_filename] = ( len(script_text), 0, script_text.split('\n'), script_filename ) script_code = compile(script_text, script_filename, 'exec') exec(script_code, namespace, namespace) def _has(self, path): raise NotImplementedError( "Can't perform this operation for unregistered loader type" ) def _isdir(self, path): raise NotImplementedError( "Can't perform this operation for unregistered loader type" ) def _listdir(self, path): raise NotImplementedError( "Can't perform this operation for unregistered loader type" ) def _fn(self, base, resource_name): if resource_name: return os.path.join(base, *resource_name.split('/')) return base def _get(self, path): if hasattr(self.loader, 'get_data'): return self.loader.get_data(path) raise NotImplementedError( "Can't perform this operation for loaders without 'get_data()'" ) register_loader_type(object, NullProvider) class EggProvider(NullProvider): """Provider based on a virtual filesystem""" def __init__(self, module): NullProvider.__init__(self, module) self._setup_prefix() def _setup_prefix(self): # we assume here that our metadata may be nested inside a "basket" # of multiple eggs; that's why we use module_path instead of .archive path = self.module_path old = None while path != old: if _is_egg_path(path): self.egg_name = os.path.basename(path) self.egg_info = os.path.join(path, 'EGG-INFO') self.egg_root = path break old = path path, base = os.path.split(path) class DefaultProvider(EggProvider): """Provides access to package resources in the filesystem""" def _has(self, path): return os.path.exists(path) def _isdir(self, path): return os.path.isdir(path) def _listdir(self, path): return os.listdir(path) def get_resource_stream(self, manager, resource_name): return open(self._fn(self.module_path, resource_name), 'rb') def _get(self, path): with open(path, 'rb') as stream: return stream.read() @classmethod def _register(cls): loader_cls = getattr( importlib_machinery, 'SourceFileLoader', type(None), ) register_loader_type(loader_cls, cls) DefaultProvider._register() class EmptyProvider(NullProvider): """Provider that returns nothing for all requests""" module_path = None _isdir = _has = lambda self, path: False def _get(self, path): return '' def _listdir(self, path): return [] def __init__(self): pass empty_provider = EmptyProvider() class ZipManifests(dict): """ zip manifest builder """ @classmethod def build(cls, path): """ Build a dictionary similar to the zipimport directory caches, except instead of tuples, store ZipInfo objects. Use a platform-specific path separator (os.sep) for the path keys for compatibility with pypy on Windows. """ with zipfile.ZipFile(path) as zfile: items = ( ( name.replace('/', os.sep), zfile.getinfo(name), ) for name in zfile.namelist() ) return dict(items) load = build class MemoizedZipManifests(ZipManifests): """ Memoized zipfile manifests. """ manifest_mod = collections.namedtuple('manifest_mod', 'manifest mtime') def load(self, path): """ Load a manifest at path or return a suitable manifest already loaded. """ path = os.path.normpath(path) mtime = os.stat(path).st_mtime if path not in self or self[path].mtime != mtime: manifest = self.build(path) self[path] = self.manifest_mod(manifest, mtime) return self[path].manifest class ZipProvider(EggProvider): """Resource support for zips and eggs""" eagers = None _zip_manifests = MemoizedZipManifests() def __init__(self, module): EggProvider.__init__(self, module) self.zip_pre = self.loader.archive + os.sep def _zipinfo_name(self, fspath): # Convert a virtual filename (full path to file) into a zipfile subpath # usable with the zipimport directory cache for our target archive fspath = fspath.rstrip(os.sep) if fspath == self.loader.archive: return '' if fspath.startswith(self.zip_pre): return fspath[len(self.zip_pre):] raise AssertionError( "%s is not a subpath of %s" % (fspath, self.zip_pre) ) def _parts(self, zip_path): # Convert a zipfile subpath into an egg-relative path part list. # pseudo-fs path fspath = self.zip_pre + zip_path if fspath.startswith(self.egg_root + os.sep): return fspath[len(self.egg_root) + 1:].split(os.sep) raise AssertionError( "%s is not a subpath of %s" % (fspath, self.egg_root) ) @property def zipinfo(self): return self._zip_manifests.load(self.loader.archive) def get_resource_filename(self, manager, resource_name): if not self.egg_name: raise NotImplementedError( "resource_filename() only supported for .egg, not .zip" ) # no need to lock for extraction, since we use temp names zip_path = self._resource_to_zip(resource_name) eagers = self._get_eager_resources() if '/'.join(self._parts(zip_path)) in eagers: for name in eagers: self._extract_resource(manager, self._eager_to_zip(name)) return self._extract_resource(manager, zip_path) @staticmethod def _get_date_and_size(zip_stat): size = zip_stat.file_size # ymdhms+wday, yday, dst date_time = zip_stat.date_time + (0, 0, -1) # 1980 offset already done timestamp = time.mktime(date_time) return timestamp, size def _extract_resource(self, manager, zip_path): if zip_path in self._index(): for name in self._index()[zip_path]: last = self._extract_resource( manager, os.path.join(zip_path, name) ) # return the extracted directory name return os.path.dirname(last) timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) if not WRITE_SUPPORT: raise IOError('"os.rename" and "os.unlink" are not supported ' 'on this platform') try: real_path = manager.get_cache_path( self.egg_name, self._parts(zip_path) ) if self._is_current(real_path, zip_path): return real_path outf, tmpnam = _mkstemp( ".$extract", dir=os.path.dirname(real_path), ) os.write(outf, self.loader.get_data(zip_path)) os.close(outf) utime(tmpnam, (timestamp, timestamp)) manager.postprocess(tmpnam, real_path) try: rename(tmpnam, real_path) except os.error: if os.path.isfile(real_path): if self._is_current(real_path, zip_path): # the file became current since it was checked above, # so proceed. return real_path # Windows, del old file and retry elif os.name == 'nt': unlink(real_path) rename(tmpnam, real_path) return real_path raise except os.error: # report a user-friendly error manager.extraction_error() return real_path def _is_current(self, file_path, zip_path): """ Return True if the file_path is current for this zip_path """ timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) if not os.path.isfile(file_path): return False stat = os.stat(file_path) if stat.st_size != size or stat.st_mtime != timestamp: return False # check that the contents match zip_contents = self.loader.get_data(zip_path) with open(file_path, 'rb') as f: file_contents = f.read() return zip_contents == file_contents def _get_eager_resources(self): if self.eagers is None: eagers = [] for name in ('native_libs.txt', 'eager_resources.txt'): if self.has_metadata(name): eagers.extend(self.get_metadata_lines(name)) self.eagers = eagers return self.eagers def _index(self): try: return self._dirindex except AttributeError: ind = {} for path in self.zipinfo: parts = path.split(os.sep) while parts: parent = os.sep.join(parts[:-1]) if parent in ind: ind[parent].append(parts[-1]) break else: ind[parent] = [parts.pop()] self._dirindex = ind return ind def _has(self, fspath): zip_path = self._zipinfo_name(fspath) return zip_path in self.zipinfo or zip_path in self._index() def _isdir(self, fspath): return self._zipinfo_name(fspath) in self._index() def _listdir(self, fspath): return list(self._index().get(self._zipinfo_name(fspath), ())) def _eager_to_zip(self, resource_name): return self._zipinfo_name(self._fn(self.egg_root, resource_name)) def _resource_to_zip(self, resource_name): return self._zipinfo_name(self._fn(self.module_path, resource_name)) register_loader_type(zipimport.zipimporter, ZipProvider) class FileMetadata(EmptyProvider): """Metadata handler for standalone PKG-INFO files Usage:: metadata = FileMetadata("/path/to/PKG-INFO") This provider rejects all data and metadata requests except for PKG-INFO, which is treated as existing, and will be the contents of the file at the provided location. """ def __init__(self, path): self.path = path def has_metadata(self, name): return name == 'PKG-INFO' and os.path.isfile(self.path) def get_metadata(self, name): if name != 'PKG-INFO': raise KeyError("No metadata except PKG-INFO is available") with io.open(self.path, encoding='utf-8', errors="replace") as f: metadata = f.read() self._warn_on_replacement(metadata) return metadata def _warn_on_replacement(self, metadata): # Python 2.7 compat for: replacement_char = '�' replacement_char = b'\xef\xbf\xbd'.decode('utf-8') if replacement_char in metadata: tmpl = "{self.path} could not be properly decoded in UTF-8" msg = tmpl.format(**locals()) warnings.warn(msg) def get_metadata_lines(self, name): return yield_lines(self.get_metadata(name)) class PathMetadata(DefaultProvider): """Metadata provider for egg directories Usage:: # Development eggs: egg_info = "/path/to/PackageName.egg-info" base_dir = os.path.dirname(egg_info) metadata = PathMetadata(base_dir, egg_info) dist_name = os.path.splitext(os.path.basename(egg_info))[0] dist = Distribution(basedir, project_name=dist_name, metadata=metadata) # Unpacked egg directories: egg_path = "/path/to/PackageName-ver-pyver-etc.egg" metadata = PathMetadata(egg_path, os.path.join(egg_path,'EGG-INFO')) dist = Distribution.from_filename(egg_path, metadata=metadata) """ def __init__(self, path, egg_info): self.module_path = path self.egg_info = egg_info class EggMetadata(ZipProvider): """Metadata provider for .egg files""" def __init__(self, importer): """Create a metadata provider from a zipimporter""" self.zip_pre = importer.archive + os.sep self.loader = importer if importer.prefix: self.module_path = os.path.join(importer.archive, importer.prefix) else: self.module_path = importer.archive self._setup_prefix() _declare_state('dict', _distribution_finders={}) def register_finder(importer_type, distribution_finder): """Register `distribution_finder` to find distributions in sys.path items `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item handler), and `distribution_finder` is a callable that, passed a path item and the importer instance, yields ``Distribution`` instances found on that path item. See ``pkg_resources.find_on_path`` for an example.""" _distribution_finders[importer_type] = distribution_finder def find_distributions(path_item, only=False): """Yield distributions accessible via `path_item`""" importer = get_importer(path_item) finder = _find_adapter(_distribution_finders, importer) return finder(importer, path_item, only) def find_eggs_in_zip(importer, path_item, only=False): """ Find eggs in zip files; possibly multiple nested eggs. """ if importer.archive.endswith('.whl'): # wheels are not supported with this finder # they don't have PKG-INFO metadata, and won't ever contain eggs return metadata = EggMetadata(importer) if metadata.has_metadata('PKG-INFO'): yield Distribution.from_filename(path_item, metadata=metadata) if only: # don't yield nested distros return for subitem in metadata.resource_listdir('/'): if _is_egg_path(subitem): subpath = os.path.join(path_item, subitem) dists = find_eggs_in_zip(zipimport.zipimporter(subpath), subpath) for dist in dists: yield dist elif subitem.lower().endswith('.dist-info'): subpath = os.path.join(path_item, subitem) submeta = EggMetadata(zipimport.zipimporter(subpath)) submeta.egg_info = subpath yield Distribution.from_location(path_item, subitem, submeta) register_finder(zipimport.zipimporter, find_eggs_in_zip) def find_nothing(importer, path_item, only=False): return () register_finder(object, find_nothing) def _by_version_descending(names): """ Given a list of filenames, return them in descending order by version number. >>> names = 'bar', 'foo', 'Python-2.7.10.egg', 'Python-2.7.2.egg' >>> _by_version_descending(names) ['Python-2.7.10.egg', 'Python-2.7.2.egg', 'foo', 'bar'] >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.egg' >>> _by_version_descending(names) ['Setuptools-1.2.3.egg', 'Setuptools-1.2.3b1.egg'] >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.post1.egg' >>> _by_version_descending(names) ['Setuptools-1.2.3.post1.egg', 'Setuptools-1.2.3b1.egg'] """ def _by_version(name): """ Parse each component of the filename """ name, ext = os.path.splitext(name) parts = itertools.chain(name.split('-'), [ext]) return [packaging.version.parse(part) for part in parts] return sorted(names, key=_by_version, reverse=True) def find_on_path(importer, path_item, only=False): """Yield distributions accessible on a sys.path directory""" path_item = _normalize_cached(path_item) if _is_unpacked_egg(path_item): yield Distribution.from_filename( path_item, metadata=PathMetadata( path_item, os.path.join(path_item, 'EGG-INFO') ) ) return entries = safe_listdir(path_item) # for performance, before sorting by version, # screen entries for only those that will yield # distributions filtered = ( entry for entry in entries if dist_factory(path_item, entry, only) ) # scan for .egg and .egg-info in directory path_item_entries = _by_version_descending(filtered) for entry in path_item_entries: fullpath = os.path.join(path_item, entry) factory = dist_factory(path_item, entry, only) for dist in factory(fullpath): yield dist def dist_factory(path_item, entry, only): """ Return a dist_factory for a path_item and entry """ lower = entry.lower() is_meta = any(map(lower.endswith, ('.egg-info', '.dist-info'))) return ( distributions_from_metadata if is_meta else find_distributions if not only and _is_egg_path(entry) else resolve_egg_link if not only and lower.endswith('.egg-link') else NoDists() ) class NoDists: """ >>> bool(NoDists()) False >>> list(NoDists()('anything')) [] """ def __bool__(self): return False if six.PY2: __nonzero__ = __bool__ def __call__(self, fullpath): return iter(()) def safe_listdir(path): """ Attempt to list contents of path, but suppress some exceptions. """ try: return os.listdir(path) except (PermissionError, NotADirectoryError): pass except OSError as e: # Ignore the directory if does not exist, not a directory or # permission denied ignorable = ( e.errno in (errno.ENOTDIR, errno.EACCES, errno.ENOENT) # Python 2 on Windows needs to be handled this way :( or getattr(e, "winerror", None) == 267 ) if not ignorable: raise return () def distributions_from_metadata(path): root = os.path.dirname(path) if os.path.isdir(path): if len(os.listdir(path)) == 0: # empty metadata dir; skip return metadata = PathMetadata(root, path) else: metadata = FileMetadata(path) entry = os.path.basename(path) yield Distribution.from_location( root, entry, metadata, precedence=DEVELOP_DIST, ) def non_empty_lines(path): """ Yield non-empty lines from file at path """ with open(path) as f: for line in f: line = line.strip() if line: yield line def resolve_egg_link(path): """ Given a path to an .egg-link, resolve distributions present in the referenced path. """ referenced_paths = non_empty_lines(path) resolved_paths = ( os.path.join(os.path.dirname(path), ref) for ref in referenced_paths ) dist_groups = map(find_distributions, resolved_paths) return next(dist_groups, ()) register_finder(pkgutil.ImpImporter, find_on_path) if hasattr(importlib_machinery, 'FileFinder'): register_finder(importlib_machinery.FileFinder, find_on_path) _declare_state('dict', _namespace_handlers={}) _declare_state('dict', _namespace_packages={}) def register_namespace_handler(importer_type, namespace_handler): """Register `namespace_handler` to declare namespace packages `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item handler), and `namespace_handler` is a callable like this:: def namespace_handler(importer, path_entry, moduleName, module): # return a path_entry to use for child packages Namespace handlers are only called if the importer object has already agreed that it can handle the relevant path item, and they should only return a subpath if the module __path__ does not already contain an equivalent subpath. For an example namespace handler, see ``pkg_resources.file_ns_handler``. """ _namespace_handlers[importer_type] = namespace_handler def _handle_ns(packageName, path_item): """Ensure that named package includes a subpath of path_item (if needed)""" importer = get_importer(path_item) if importer is None: return None loader = importer.find_module(packageName) if loader is None: return None module = sys.modules.get(packageName) if module is None: module = sys.modules[packageName] = types.ModuleType(packageName) module.__path__ = [] _set_parent_ns(packageName) elif not hasattr(module, '__path__'): raise TypeError("Not a package:", packageName) handler = _find_adapter(_namespace_handlers, importer) subpath = handler(importer, path_item, packageName, module) if subpath is not None: path = module.__path__ path.append(subpath) loader.load_module(packageName) _rebuild_mod_path(path, packageName, module) return subpath def _rebuild_mod_path(orig_path, package_name, module): """ Rebuild module.__path__ ensuring that all entries are ordered corresponding to their sys.path order """ sys_path = [_normalize_cached(p) for p in sys.path] def safe_sys_path_index(entry): """ Workaround for #520 and #513. """ try: return sys_path.index(entry) except ValueError: return float('inf') def position_in_sys_path(path): """ Return the ordinal of the path based on its position in sys.path """ path_parts = path.split(os.sep) module_parts = package_name.count('.') + 1 parts = path_parts[:-module_parts] return safe_sys_path_index(_normalize_cached(os.sep.join(parts))) if not isinstance(orig_path, list): # Is this behavior useful when module.__path__ is not a list? return orig_path.sort(key=position_in_sys_path) module.__path__[:] = [_normalize_cached(p) for p in orig_path] def declare_namespace(packageName): """Declare that package 'packageName' is a namespace package""" _imp.acquire_lock() try: if packageName in _namespace_packages: return path, parent = sys.path, None if '.' in packageName: parent = '.'.join(packageName.split('.')[:-1]) declare_namespace(parent) if parent not in _namespace_packages: __import__(parent) try: path = sys.modules[parent].__path__ except AttributeError: raise TypeError("Not a package:", parent) # Track what packages are namespaces, so when new path items are added, # they can be updated _namespace_packages.setdefault(parent, []).append(packageName) _namespace_packages.setdefault(packageName, []) for path_item in path: # Ensure all the parent's path items are reflected in the child, # if they apply _handle_ns(packageName, path_item) finally: _imp.release_lock() def fixup_namespace_packages(path_item, parent=None): """Ensure that previously-declared namespace packages include path_item""" _imp.acquire_lock() try: for package in _namespace_packages.get(parent, ()): subpath = _handle_ns(package, path_item) if subpath: fixup_namespace_packages(subpath, package) finally: _imp.release_lock() def file_ns_handler(importer, path_item, packageName, module): """Compute an ns-package subpath for a filesystem or zipfile importer""" subpath = os.path.join(path_item, packageName.split('.')[-1]) normalized = _normalize_cached(subpath) for item in module.__path__: if _normalize_cached(item) == normalized: break else: # Only return the path if it's not already there return subpath register_namespace_handler(pkgutil.ImpImporter, file_ns_handler) register_namespace_handler(zipimport.zipimporter, file_ns_handler) if hasattr(importlib_machinery, 'FileFinder'): register_namespace_handler(importlib_machinery.FileFinder, file_ns_handler) def null_ns_handler(importer, path_item, packageName, module): return None register_namespace_handler(object, null_ns_handler) def normalize_path(filename): """Normalize a file/dir name for comparison purposes""" return os.path.normcase(os.path.realpath(filename)) def _normalize_cached(filename, _cache={}): try: return _cache[filename] except KeyError: _cache[filename] = result = normalize_path(filename) return result def _is_egg_path(path): """ Determine if given path appears to be an egg. """ return path.lower().endswith('.egg') def _is_unpacked_egg(path): """ Determine if given path appears to be an unpacked egg. """ return ( _is_egg_path(path) and os.path.isfile(os.path.join(path, 'EGG-INFO', 'PKG-INFO')) ) def _set_parent_ns(packageName): parts = packageName.split('.') name = parts.pop() if parts: parent = '.'.join(parts) setattr(sys.modules[parent], name, sys.modules[packageName]) def yield_lines(strs): """Yield non-empty/non-comment lines of a string or sequence""" if isinstance(strs, six.string_types): for s in strs.splitlines(): s = s.strip() # skip blank lines/comments if s and not s.startswith('#'): yield s else: for ss in strs: for s in yield_lines(ss): yield s MODULE = re.compile(r"\w+(\.\w+)*$").match EGG_NAME = re.compile( r""" (?P[^-]+) ( -(?P[^-]+) ( -py(?P[^-]+) ( -(?P.+) )? )? )? """, re.VERBOSE | re.IGNORECASE, ).match class EntryPoint(object): """Object representing an advertised importable object""" def __init__(self, name, module_name, attrs=(), extras=(), dist=None): if not MODULE(module_name): raise ValueError("Invalid module name", module_name) self.name = name self.module_name = module_name self.attrs = tuple(attrs) self.extras = tuple(extras) self.dist = dist def __str__(self): s = "%s = %s" % (self.name, self.module_name) if self.attrs: s += ':' + '.'.join(self.attrs) if self.extras: s += ' [%s]' % ','.join(self.extras) return s def __repr__(self): return "EntryPoint.parse(%r)" % str(self) def load(self, require=True, *args, **kwargs): """ Require packages for this EntryPoint, then resolve it. """ if not require or args or kwargs: warnings.warn( "Parameters to load are deprecated. Call .resolve and " ".require separately.", DeprecationWarning, stacklevel=2, ) if require: self.require(*args, **kwargs) return self.resolve() def resolve(self): """ Resolve the entry point from its module and attrs. """ module = __import__(self.module_name, fromlist=['__name__'], level=0) try: return functools.reduce(getattr, self.attrs, module) except AttributeError as exc: raise ImportError(str(exc)) def require(self, env=None, installer=None): if self.extras and not self.dist: raise UnknownExtra("Can't require() without a distribution", self) # Get the requirements for this entry point with all its extras and # then resolve them. We have to pass `extras` along when resolving so # that the working set knows what extras we want. Otherwise, for # dist-info distributions, the working set will assume that the # requirements for that extra are purely optional and skip over them. reqs = self.dist.requires(self.extras) items = working_set.resolve(reqs, env, installer, extras=self.extras) list(map(working_set.add, items)) pattern = re.compile( r'\s*' r'(?P.+?)\s*' r'=\s*' r'(?P[\w.]+)\s*' r'(:\s*(?P[\w.]+))?\s*' r'(?P\[.*\])?\s*$' ) @classmethod def parse(cls, src, dist=None): """Parse a single entry point from string `src` Entry point syntax follows the form:: name = some.module:some.attr [extra1, extra2] The entry name and module name are required, but the ``:attrs`` and ``[extras]`` parts are optional """ m = cls.pattern.match(src) if not m: msg = "EntryPoint must be in 'name=module:attrs [extras]' format" raise ValueError(msg, src) res = m.groupdict() extras = cls._parse_extras(res['extras']) attrs = res['attr'].split('.') if res['attr'] else () return cls(res['name'], res['module'], attrs, extras, dist) @classmethod def _parse_extras(cls, extras_spec): if not extras_spec: return () req = Requirement.parse('x' + extras_spec) if req.specs: raise ValueError() return req.extras @classmethod def parse_group(cls, group, lines, dist=None): """Parse an entry point group""" if not MODULE(group): raise ValueError("Invalid group name", group) this = {} for line in yield_lines(lines): ep = cls.parse(line, dist) if ep.name in this: raise ValueError("Duplicate entry point", group, ep.name) this[ep.name] = ep return this @classmethod def parse_map(cls, data, dist=None): """Parse a map of entry point groups""" if isinstance(data, dict): data = data.items() else: data = split_sections(data) maps = {} for group, lines in data: if group is None: if not lines: continue raise ValueError("Entry points must be listed in groups") group = group.strip() if group in maps: raise ValueError("Duplicate group name", group) maps[group] = cls.parse_group(group, lines, dist) return maps def _remove_md5_fragment(location): if not location: return '' parsed = urllib.parse.urlparse(location) if parsed[-1].startswith('md5='): return urllib.parse.urlunparse(parsed[:-1] + ('',)) return location def _version_from_file(lines): """ Given an iterable of lines from a Metadata file, return the value of the Version field, if present, or None otherwise. """ def is_version_line(line): return line.lower().startswith('version:') version_lines = filter(is_version_line, lines) line = next(iter(version_lines), '') _, _, value = line.partition(':') return safe_version(value.strip()) or None class Distribution(object): """Wrap an actual or potential sys.path entry w/metadata""" PKG_INFO = 'PKG-INFO' def __init__( self, location=None, metadata=None, project_name=None, version=None, py_version=PY_MAJOR, platform=None, precedence=EGG_DIST): self.project_name = safe_name(project_name or 'Unknown') if version is not None: self._version = safe_version(version) self.py_version = py_version self.platform = platform self.location = location self.precedence = precedence self._provider = metadata or empty_provider @classmethod def from_location(cls, location, basename, metadata=None, **kw): project_name, version, py_version, platform = [None] * 4 basename, ext = os.path.splitext(basename) if ext.lower() in _distributionImpl: cls = _distributionImpl[ext.lower()] match = EGG_NAME(basename) if match: project_name, version, py_version, platform = match.group( 'name', 'ver', 'pyver', 'plat' ) return cls( location, metadata, project_name=project_name, version=version, py_version=py_version, platform=platform, **kw )._reload_version() def _reload_version(self): return self @property def hashcmp(self): return ( self.parsed_version, self.precedence, self.key, _remove_md5_fragment(self.location), self.py_version or '', self.platform or '', ) def __hash__(self): return hash(self.hashcmp) def __lt__(self, other): return self.hashcmp < other.hashcmp def __le__(self, other): return self.hashcmp <= other.hashcmp def __gt__(self, other): return self.hashcmp > other.hashcmp def __ge__(self, other): return self.hashcmp >= other.hashcmp def __eq__(self, other): if not isinstance(other, self.__class__): # It's not a Distribution, so they are not equal return False return self.hashcmp == other.hashcmp def __ne__(self, other): return not self == other # These properties have to be lazy so that we don't have to load any # metadata until/unless it's actually needed. (i.e., some distributions # may not know their name or version without loading PKG-INFO) @property def key(self): try: return self._key except AttributeError: self._key = key = self.project_name.lower() return key @property def parsed_version(self): if not hasattr(self, "_parsed_version"): self._parsed_version = parse_version(self.version) return self._parsed_version def _warn_legacy_version(self): LV = packaging.version.LegacyVersion is_legacy = isinstance(self._parsed_version, LV) if not is_legacy: return # While an empty version is technically a legacy version and # is not a valid PEP 440 version, it's also unlikely to # actually come from someone and instead it is more likely that # it comes from setuptools attempting to parse a filename and # including it in the list. So for that we'll gate this warning # on if the version is anything at all or not. if not self.version: return tmpl = textwrap.dedent(""" '{project_name} ({version})' is being parsed as a legacy, non PEP 440, version. You may find odd behavior and sort order. In particular it will be sorted as less than 0.0. It is recommended to migrate to PEP 440 compatible versions. """).strip().replace('\n', ' ') warnings.warn(tmpl.format(**vars(self)), PEP440Warning) @property def version(self): try: return self._version except AttributeError: version = _version_from_file(self._get_metadata(self.PKG_INFO)) if version is None: tmpl = "Missing 'Version:' header and/or %s file" raise ValueError(tmpl % self.PKG_INFO, self) return version @property def _dep_map(self): """ A map of extra to its list of (direct) requirements for this distribution, including the null extra. """ try: return self.__dep_map except AttributeError: self.__dep_map = self._filter_extras(self._build_dep_map()) return self.__dep_map @staticmethod def _filter_extras(dm): """ Given a mapping of extras to dependencies, strip off environment markers and filter out any dependencies not matching the markers. """ for extra in list(filter(None, dm)): new_extra = extra reqs = dm.pop(extra) new_extra, _, marker = extra.partition(':') fails_marker = marker and ( invalid_marker(marker) or not evaluate_marker(marker) ) if fails_marker: reqs = [] new_extra = safe_extra(new_extra) or None dm.setdefault(new_extra, []).extend(reqs) return dm def _build_dep_map(self): dm = {} for name in 'requires.txt', 'depends.txt': for extra, reqs in split_sections(self._get_metadata(name)): dm.setdefault(extra, []).extend(parse_requirements(reqs)) return dm def requires(self, extras=()): """List of Requirements needed for this distro if `extras` are used""" dm = self._dep_map deps = [] deps.extend(dm.get(None, ())) for ext in extras: try: deps.extend(dm[safe_extra(ext)]) except KeyError: raise UnknownExtra( "%s has no such extra feature %r" % (self, ext) ) return deps def _get_metadata(self, name): if self.has_metadata(name): for line in self.get_metadata_lines(name): yield line def activate(self, path=None, replace=False): """Ensure distribution is importable on `path` (default=sys.path)""" if path is None: path = sys.path self.insert_on(path, replace=replace) if path is sys.path: fixup_namespace_packages(self.location) for pkg in self._get_metadata('namespace_packages.txt'): if pkg in sys.modules: declare_namespace(pkg) def egg_name(self): """Return what this distribution's standard .egg filename should be""" filename = "%s-%s-py%s" % ( to_filename(self.project_name), to_filename(self.version), self.py_version or PY_MAJOR ) if self.platform: filename += '-' + self.platform return filename def __repr__(self): if self.location: return "%s (%s)" % (self, self.location) else: return str(self) def __str__(self): try: version = getattr(self, 'version', None) except ValueError: version = None version = version or "[unknown version]" return "%s %s" % (self.project_name, version) def __getattr__(self, attr): """Delegate all unrecognized public attributes to .metadata provider""" if attr.startswith('_'): raise AttributeError(attr) return getattr(self._provider, attr) @classmethod def from_filename(cls, filename, metadata=None, **kw): return cls.from_location( _normalize_cached(filename), os.path.basename(filename), metadata, **kw ) def as_requirement(self): """Return a ``Requirement`` that matches this distribution exactly""" if isinstance(self.parsed_version, packaging.version.Version): spec = "%s==%s" % (self.project_name, self.parsed_version) else: spec = "%s===%s" % (self.project_name, self.parsed_version) return Requirement.parse(spec) def load_entry_point(self, group, name): """Return the `name` entry point of `group` or raise ImportError""" ep = self.get_entry_info(group, name) if ep is None: raise ImportError("Entry point %r not found" % ((group, name),)) return ep.load() def get_entry_map(self, group=None): """Return the entry point map for `group`, or the full entry map""" try: ep_map = self._ep_map except AttributeError: ep_map = self._ep_map = EntryPoint.parse_map( self._get_metadata('entry_points.txt'), self ) if group is not None: return ep_map.get(group, {}) return ep_map def get_entry_info(self, group, name): """Return the EntryPoint object for `group`+`name`, or ``None``""" return self.get_entry_map(group).get(name) def insert_on(self, path, loc=None, replace=False): """Ensure self.location is on path If replace=False (default): - If location is already in path anywhere, do nothing. - Else: - If it's an egg and its parent directory is on path, insert just ahead of the parent. - Else: add to the end of path. If replace=True: - If location is already on path anywhere (not eggs) or higher priority than its parent (eggs) do nothing. - Else: - If it's an egg and its parent directory is on path, insert just ahead of the parent, removing any lower-priority entries. - Else: add it to the front of path. """ loc = loc or self.location if not loc: return nloc = _normalize_cached(loc) bdir = os.path.dirname(nloc) npath = [(p and _normalize_cached(p) or p) for p in path] for p, item in enumerate(npath): if item == nloc: if replace: break else: # don't modify path (even removing duplicates) if # found and not replace return elif item == bdir and self.precedence == EGG_DIST: # if it's an .egg, give it precedence over its directory # UNLESS it's already been added to sys.path and replace=False if (not replace) and nloc in npath[p:]: return if path is sys.path: self.check_version_conflict() path.insert(p, loc) npath.insert(p, nloc) break else: if path is sys.path: self.check_version_conflict() if replace: path.insert(0, loc) else: path.append(loc) return # p is the spot where we found or inserted loc; now remove duplicates while True: try: np = npath.index(nloc, p + 1) except ValueError: break else: del npath[np], path[np] # ha! p = np return def check_version_conflict(self): if self.key == 'setuptools': # ignore the inevitable setuptools self-conflicts :( return nsp = dict.fromkeys(self._get_metadata('namespace_packages.txt')) loc = normalize_path(self.location) for modname in self._get_metadata('top_level.txt'): if (modname not in sys.modules or modname in nsp or modname in _namespace_packages): continue if modname in ('pkg_resources', 'setuptools', 'site'): continue fn = getattr(sys.modules[modname], '__file__', None) if fn and (normalize_path(fn).startswith(loc) or fn.startswith(self.location)): continue issue_warning( "Module %s was already imported from %s, but %s is being added" " to sys.path" % (modname, fn, self.location), ) def has_version(self): try: self.version except ValueError: issue_warning("Unbuilt egg for " + repr(self)) return False return True def clone(self, **kw): """Copy this distribution, substituting in any changed keyword args""" names = 'project_name version py_version platform location precedence' for attr in names.split(): kw.setdefault(attr, getattr(self, attr, None)) kw.setdefault('metadata', self._provider) return self.__class__(**kw) @property def extras(self): return [dep for dep in self._dep_map if dep] class EggInfoDistribution(Distribution): def _reload_version(self): """ Packages installed by distutils (e.g. numpy or scipy), which uses an old safe_version, and so their version numbers can get mangled when converted to filenames (e.g., 1.11.0.dev0+2329eae to 1.11.0.dev0_2329eae). These distributions will not be parsed properly downstream by Distribution and safe_version, so take an extra step and try to get the version number from the metadata file itself instead of the filename. """ md_version = _version_from_file(self._get_metadata(self.PKG_INFO)) if md_version: self._version = md_version return self class DistInfoDistribution(Distribution): """ Wrap an actual or potential sys.path entry w/metadata, .dist-info style. """ PKG_INFO = 'METADATA' EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])") @property def _parsed_pkg_info(self): """Parse and cache metadata""" try: return self._pkg_info except AttributeError: metadata = self.get_metadata(self.PKG_INFO) self._pkg_info = email.parser.Parser().parsestr(metadata) return self._pkg_info @property def _dep_map(self): try: return self.__dep_map except AttributeError: self.__dep_map = self._compute_dependencies() return self.__dep_map def _compute_dependencies(self): """Recompute this distribution's dependencies.""" dm = self.__dep_map = {None: []} reqs = [] # Including any condition expressions for req in self._parsed_pkg_info.get_all('Requires-Dist') or []: reqs.extend(parse_requirements(req)) def reqs_for_extra(extra): for req in reqs: if not req.marker or req.marker.evaluate({'extra': extra}): yield req common = frozenset(reqs_for_extra(None)) dm[None].extend(common) for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []: s_extra = safe_extra(extra.strip()) dm[s_extra] = list(frozenset(reqs_for_extra(extra)) - common) return dm _distributionImpl = { '.egg': Distribution, '.egg-info': EggInfoDistribution, '.dist-info': DistInfoDistribution, } def issue_warning(*args, **kw): level = 1 g = globals() try: # find the first stack frame that is *not* code in # the pkg_resources module, to use for the warning while sys._getframe(level).f_globals is g: level += 1 except ValueError: pass warnings.warn(stacklevel=level + 1, *args, **kw) class RequirementParseError(ValueError): def __str__(self): return ' '.join(self.args) def parse_requirements(strs): """Yield ``Requirement`` objects for each specification in `strs` `strs` must be a string, or a (possibly-nested) iterable thereof. """ # create a steppable iterator, so we can handle \-continuations lines = iter(yield_lines(strs)) for line in lines: # Drop comments -- a hash without a space may be in a URL. if ' #' in line: line = line[:line.find(' #')] # If there is a line continuation, drop it, and append the next line. if line.endswith('\\'): line = line[:-2].strip() try: line += next(lines) except StopIteration: return yield Requirement(line) class Requirement(packaging.requirements.Requirement): def __init__(self, requirement_string): """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!""" try: super(Requirement, self).__init__(requirement_string) except packaging.requirements.InvalidRequirement as e: raise RequirementParseError(str(e)) self.unsafe_name = self.name project_name = safe_name(self.name) self.project_name, self.key = project_name, project_name.lower() self.specs = [ (spec.operator, spec.version) for spec in self.specifier] self.extras = tuple(map(safe_extra, self.extras)) self.hashCmp = ( self.key, self.specifier, frozenset(self.extras), str(self.marker) if self.marker else None, ) self.__hash = hash(self.hashCmp) def __eq__(self, other): return ( isinstance(other, Requirement) and self.hashCmp == other.hashCmp ) def __ne__(self, other): return not self == other def __contains__(self, item): if isinstance(item, Distribution): if item.key != self.key: return False item = item.version # Allow prereleases always in order to match the previous behavior of # this method. In the future this should be smarter and follow PEP 440 # more accurately. return self.specifier.contains(item, prereleases=True) def __hash__(self): return self.__hash def __repr__(self): return "Requirement.parse(%r)" % str(self) @staticmethod def parse(s): req, = parse_requirements(s) return req def _always_object(classes): """ Ensure object appears in the mro even for old-style classes. """ if object not in classes: return classes + (object,) return classes def _find_adapter(registry, ob): """Return an adapter factory for `ob` from `registry`""" types = _always_object(inspect.getmro(getattr(ob, '__class__', type(ob)))) for t in types: if t in registry: return registry[t] def ensure_directory(path): """Ensure that the parent directory of `path` exists""" dirname = os.path.dirname(path) py31compat.makedirs(dirname, exist_ok=True) def _bypass_ensure_directory(path): """Sandbox-bypassing version of ensure_directory()""" if not WRITE_SUPPORT: raise IOError('"os.mkdir" not supported on this platform.') dirname, filename = split(path) if dirname and filename and not isdir(dirname): _bypass_ensure_directory(dirname) mkdir(dirname, 0o755) def split_sections(s): """Split a string or iterable thereof into (section, content) pairs Each ``section`` is a stripped version of the section header ("[section]") and each ``content`` is a list of stripped lines excluding blank lines and comment-only lines. If there are any such lines before the first section header, they're returned in a first ``section`` of ``None``. """ section = None content = [] for line in yield_lines(s): if line.startswith("["): if line.endswith("]"): if section or content: yield section, content section = line[1:-1].strip() content = [] else: raise ValueError("Invalid section heading", line) else: content.append(line) # wrap up last segment yield section, content def _mkstemp(*args, **kw): old_open = os.open try: # temporarily bypass sandboxing os.open = os_open return tempfile.mkstemp(*args, **kw) finally: # and then put it back os.open = old_open # Silence the PEP440Warning by default, so that end users don't get hit by it # randomly just because they use pkg_resources. We want to append the rule # because we want earlier uses of filterwarnings to take precedence over this # one. warnings.filterwarnings("ignore", category=PEP440Warning, append=True) # from jaraco.functools 1.3 def _call_aside(f, *args, **kwargs): f(*args, **kwargs) return f @_call_aside def _initialize(g=globals()): "Set up global resource manager (deliberately not state-saved)" manager = ResourceManager() g['_manager'] = manager g.update( (name, getattr(manager, name)) for name in dir(manager) if not name.startswith('_') ) @_call_aside def _initialize_master_working_set(): """ Prepare the master working set and make the ``require()`` API available. This function has explicit effects on the global state of pkg_resources. It is intended to be invoked once at the initialization of this module. Invocation by other packages is unsupported and done at their own risk. """ working_set = WorkingSet._build_master() _declare_state('object', working_set=working_set) require = working_set.require iter_entry_points = working_set.iter_entry_points add_activation_listener = working_set.subscribe run_script = working_set.run_script # backward compatibility run_main = run_script # Activate all distributions already on sys.path with replace=False and # ensure that all distributions added to the working set in the future # (e.g. by calling ``require()``) will get activated as well, # with higher priority (replace=True). tuple( dist.activate(replace=False) for dist in working_set ) add_activation_listener( lambda dist: dist.activate(replace=True), existing=False, ) working_set.entries = [] # match order list(map(working_set.add_entry, sys.path)) globals().update(locals()) PK@N#]G}2XX)site-packages/pkg_resources/py31compat.pynu[import os import errno import sys def _makedirs_31(path, exist_ok=False): try: os.makedirs(path) except OSError as exc: if not exist_ok or exc.errno != errno.EEXIST: raise # rely on compatibility behavior until mode considerations # and exists_ok considerations are disentangled. # See https://github.com/pypa/setuptools/pull/1083#issuecomment-315168663 needs_makedirs = ( sys.version_info < (3, 2, 5) or (3, 3) <= sys.version_info < (3, 3, 6) or (3, 4) <= sys.version_info < (3, 4, 1) ) makedirs = _makedirs_31 if needs_makedirs else os.makedirs PK@N#] A(site-packages/pkg_resources/__init__.pycnu[ fcF@@s dZddlmZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlmZyddlZWnek r]ddlZnXddlmZddl m!Z!m"Z"m#Z#ddlm$Z$y&ddlm%Z%m&Z&m'Z'e(Z)Wnek re*Z)nXdd lm+Z,dd l-m.Z.m/Z/yddl0j1Z2e2j3Wnek r3e4Z2nXd d l5m6Z6dd lm7Z7ddlm8Z8e9de9de9de9dddfej:koddfknre;dnej<re4Z=e4Z>ne4Z?e4Z@e4ZAe4ZBe4ZCe4ZDe4ZEe4ZFe4ZGe4ZHe4ZIe4ZJe4ZKe4ZLe4ZMe4ZNe4ZOdePfdYZQdZRiZSdZTdZUdZVdZWdZXdZYdZZdZ[Z\d Z]d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@ddAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddegFZ^d<e_fdfYZ`d=e`fdgYZadheafdiYZbd>e`fdjYZcd?e`fdkYZdiZeejfd ZgdZhdlZid ZjdZkdmZldnZmdoZngdpZodqZpdrZqejrdsZsejrdtZteqZuduZvdvZwewZxdwZydxZze4dyZ{dzZ|dTfd{YZ}dUe}fd|YZ~d7efd}YZd~efdYZd6efdYZeZd@e;fdYZd8fdYZdZdZdZdZdZdZe4dZd[fdYZemeed\efdYZd]efdYZejdYefdYZeZdefdYZdefdYZd^efdYZeme jedVefdYZdWefdYZdXefdYZeTddidZe*dZe*dZee jee*dZeeedZe*dZdZdfdYZdZdZdZdZeejeee2dree2jeneTddieTddidZdZdZdZe4dZdZeejeee jeee2dr) ee2jendZeeedZidZdZdZdZdZejrdjZejrdejejBjZd;efdYZdZdZd9efdYZdefdYZdefdYZied6ed6ed6ZdZdefdYZdZd:e8jjfdYZdZdZdZdZdZdZe jddeQde(dZeedZedZdS(sZ Package resource API -------------------- A resource is a logical file contained within a package, or a logical subdirectory thereof. The package resource API expects resource names to have their path parts separated with ``/``, *not* whatever the local path separator is. Do not use os.path operations to manipulate resource names being passed into the API. The package resource API is designed to work with normal filesystem packages, .egg files, and unpacked .egg files. It can also work in a limited way with .zip files and with custom PEP 302 loaders that support the ``get_data()`` method. i(tabsolute_importN(t get_importer(tsix(turllibtmaptfilter(tutime(tmkdirtrenametunlink(topen(tisdirtspliti(t py31compat(tappdirs(t packagings&pkg_resources.extern.packaging.versions)pkg_resources.extern.packaging.specifierss+pkg_resources.extern.packaging.requirementss&pkg_resources.extern.packaging.markersisPython 3.3 or later is requiredt PEP440WarningcB@seZdZRS(sa Used when there is an issue with a version or specifier not complying with PEP 440. (t__name__t __module__t__doc__(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRnscC@s?ytjj|SWn$tjjk r:tjj|SXdS(N(RtversiontVersiontInvalidVersiont LegacyVersion(tv((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt parse_versionuscK@s-tj|tjtj||dS(N(tglobalstupdatet _state_varstdicttfromkeys(tvartypetkw((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_declare_statescC@sLi}t}x6tjD](\}}|d|||||tcC@s{t}tj|}|dk rwtjdkrwy-ddjtd |jdf}Wqwt k rsqwXn|S(sZReturn this platform's maximum compatible version. distutils.util.get_platform() normally reports the minimum version of Mac OS X that would be required to *use* extensions produced by distutils. But what we want when checking compatibility is to know the version of Mac OS X that we are *running*. To allow usage of packages that explicitly require a newer version of Mac OS X, we must also know the current version of the OS. If this condition occurs for any other platform with a version in its platform strings, this function should be extended accordingly. tdarwins macosx-%s-%st.iiN( tget_build_platformtmacosVersionStringtmatchR3tsystplatformtjoint _macosx_verstgroupt ValueError(tplattm((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytget_supported_platforms - trequiret run_scriptt get_providertget_distributiontload_entry_pointt get_entry_maptget_entry_infotiter_entry_pointstresource_stringtresource_streamtresource_filenametresource_listdirtresource_existstresource_isdirtdeclare_namespacet working_settadd_activation_listenertfind_distributionstset_extraction_pathtcleanup_resourcestget_default_cachet Environmentt WorkingSettResourceManagert Distributiont Requirementt EntryPointtResolutionErrortVersionConflicttDistributionNotFoundt UnknownExtratExtractionErrortparse_requirementsRt safe_namet safe_versiont get_platformtcompatible_platformst yield_linestsplit_sectionst safe_extrat to_filenametinvalid_markertevaluate_markertensure_directorytnormalize_pathtEGG_DISTt BINARY_DISTt SOURCE_DISTt CHECKOUT_DISTt DEVELOP_DISTtIMetadataProvidertIResourceProvidert FileMetadatat PathMetadatat EggMetadatat EmptyProvidertempty_providert NullProvidert EggProvidertDefaultProvidert ZipProvidertregister_findertregister_namespace_handlertregister_loader_typetfixup_namespace_packagesRtrun_maintAvailableDistributionscB@seZdZdZRS(s.Abstract base for dependency resolution errorscC@s|jjt|jS(N(t __class__RtreprR4(tself((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__repr__s(RRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR`scB@sDeZdZdZedZedZdZdZRS(s An already-installed version conflicts with the requested version. Should be initialized with the installed Distribution and the requested Requirement. s3{self.dist} is installed but {self.req} is requiredcC@s |jdS(Ni(R4(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytdistscC@s |jdS(Ni(R4(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytreqscC@s|jjtS(N(t _templatetformattlocals(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytreportscC@s$|s |S|j|f}t|S(st If required_by is non-empty, return a version of self that is a ContextualVersionConflict. (R4tContextualVersionConflict(Rt required_byR4((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt with_context s( RRRRtpropertyRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRas  RcB@s*eZdZejdZedZRS(s A VersionConflict that accepts a third parameter, the set of the requirements that required the installed Distribution. s by {self.required_by}cC@s |jdS(Ni(R4(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs(RRRRaRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs cB@sSeZdZdZedZedZedZdZdZ RS(s&A requested distribution was not foundsSThe '{self.req}' distribution was not found and is required by {self.requirers_str}cC@s |jdS(Ni(R4(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR(scC@s |jdS(Ni(R4(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt requirers,scC@s|js dSdj|jS(Nsthe applications, (RR>(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt requirers_str0s cC@s|jjtS(N(RRR(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR6scC@s |jS(N(R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__str__9s( RRRRRRRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRb"s cB@seZdZRS(s>Distribution doesn't have an "extra feature" of the given name(RRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRc=siicC@s|t|eZdZdZdZdZdZdZRS(cC@sdS(s;Does the package's distribution contain the named metadata?N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt has_metadataR6cC@sdS(s'The named metadata resource as a stringN((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt get_metadataR6cC@sdS(sYield named metadata resource as list of non-blank non-comment lines Leading and trailing whitespace is stripped from each line, and lines with ``#`` as the first non-blank character are omitted.N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytget_metadata_linesR6cC@sdS(s>Is the named metadata a directory? (like ``os.path.isdir()``)N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytmetadata_isdirR6cC@sdS(s?List of metadata names in the directory (like ``os.listdir()``)N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytmetadata_listdirR6cC@sdS(s=Execute the named script in the supplied namespace dictionaryN((Rt namespace((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRFR6(RRRRRRRRF(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRws      cB@sDeZdZdZdZdZdZdZdZRS(s3An object that provides access to package resourcescC@sdS(sdReturn a true filesystem path for `resource_name` `manager` must be an ``IResourceManager``N((tmanagert resource_name((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytget_resource_filenameR6cC@sdS(siReturn a readable file-like object for `resource_name` `manager` must be an ``IResourceManager``N((RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytget_resource_stream R6cC@sdS(smReturn a string containing the contents of `resource_name` `manager` must be an ``IResourceManager``N((RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytget_resource_stringR6cC@sdS(s,Does the package contain the named resource?N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt has_resourceR6cC@sdS(s>Is the named resource a directory? (like ``os.path.isdir()``)N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRRR6cC@sdS(s?List of resource names in the directory (like ``os.listdir()``)N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRPR6( RRRRRRRRRRP(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRxs     cB@seZdZddZedZedZdZdZ dZ ddZ dZ d Z deed Zddedd Zdded Zd ZedZdZdZdZRS(sDA collection of active distributions on sys.path (or a similar list)cC@s^g|_i|_i|_g|_|dkr<tj}nx|D]}|j|qCWdS(s?Create working set from list of path entries (default=sys.path)N(tentriest entry_keystby_keyt callbacksR3R<Rt add_entry(RRtentry((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__init__#s       cC@se|}yddlm}Wntk r1|SXy|j|Wntk r`|j|SX|S(s1 Prepare the master working set. i(t __requires__(t__main__RRRERat_build_from_requirements(tclstwsR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt _build_master0s   cC@s|g}t|}|j|t}x|D]}|j|q4Wx0tjD]%}||jkrU|j|qUqUW|jtj(|S(sQ Build a working set from a requirement spec. Rewrites sys.path. (RetresolveRZtaddR<RRR(Rtreq_specRtreqstdistsRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRDs    cC@sT|jj|g|jj|x*t|tD]}|j||tq3WdS(sAdd a path item to ``.entries``, finding any distributions on it ``find_distributions(entry, True)`` is used to find distributions corresponding to the path entry, and they are added. `entry` is always appended to ``.entries``, even if it is already present. (This is because ``sys.path`` can contain the same value more than once, and the ``.entries`` of the ``sys.path`` WorkingSet should always equal ``sys.path``.) N(Rt setdefaultRRRVRRR(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRZs cC@s|jj|j|kS(s9True if `dist` is the active distribution for its project(RRR.(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt __contains__iscC@sC|jj|j}|dk r?||kr?t||n|S(sFind a distribution matching requirement `req` If there is an active distribution for the requested project, this returns it as long as it meets the version requirement specified by `req`. But, if there is an active distribution for the project and it does *not* meet the `req` requirement, ``VersionConflict`` is raised. If there is no active distribution for the requested project, ``None`` is returned. N(RRR.R3Ra(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRms cc@sgx`|D]X}|j|}|dkrGx4|jD] }|Vq5Wq||kr||VqqWdS(sYield entry point objects from `group` matching `name` If `name` is None, yields all entry points in `group` from all distributions in the working set, otherwise only ones matching both `group` and `name` are yielded (in distribution order). N(RJR3tvalues(RR@RRRtep((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRL}s    cC@sQtjdj}|d}|j||d<|j|dj||dS(s?Locate distribution for `requires` and run `script_name` scriptiRiN(R<RRR-RERF(RtrequiresRRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRFs    cc@spi}xc|jD]X}||jkr+qnx:|j|D]+}||kr9d||<|j|Vq9q9WqWdS(sYield distributions for non-duplicate projects in the working set The yield order is the order in which the items' path entries were added to the working set. iN(RRR(RtseentitemR.((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__iter__s  cC@s|r"|j|j|d|n|dkr:|j}n|jj|g}|jj|jg}| r|j|jkrdS||j|j<|j|kr|j|jn|j|kr|j|jn|j |dS(sAdd `dist` to working set, associated with `entry` If `entry` is unspecified, it defaults to the ``.location`` of `dist`. On exit from this routine, `entry` is added to the end of the working set's ``.entries`` (if it wasn't already present). `dist` is only added to the working set if it's for a project that doesn't already have a distribution in the set, unless `replace=True`. If it's added, any callbacks registered with the ``subscribe()`` method will be called. RN( t insert_onRR3tlocationRRR.RRt _added_new(RRRtinsertRtkeystkeys2((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   cC@s+t|ddd}i}i}g}t} tjt} x|r&|jd} | |krmqFn| j| |sqFn|j| j} | dkr|j j| j} | dks| | krz|rz|} |dkr!| dkrt |j }q!t g}t g} n|j| | |d|} || j<| dkrz| j| d}t| |qzn|j| n| | kr| | }t| | j|n| j| jddd}|j|x/|D]'}| |j| j| j| | Map each requirement to the extras that demanded it. c@s@fd|jd|p$dD}j p?t|S(s Evaluate markers for req against each extra that demanded it. Return False if the req has a marker and fails evaluation. Otherwise, return True. c3@s(|]}jji|d6VqdS(textraN(tmarkertevaluate(t.0R)(R(s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pys s(N(N(RR3R*tany(RRR t extra_evals((Rs:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s  N(RRRR3R (((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscB@seZdZd eedZdZdZd dZ dZ dZ d e dZ d dZd Zd Zd ZRS( s5Searchable snapshot of distributions on a search pathcC@s,i|_||_||_|j|dS(s!Snapshot distributions available on a search path Any distributions found on `search_path` are added to the environment. `search_path` should be a sequence of ``sys.path`` items. If not supplied, ``sys.path`` is used. `platform` is an optional string specifying the name of the platform that platform-specific distributions must be compatible with. If unspecified, it defaults to the current platform. `python` is an optional string naming the desired version of Python (e.g. ``'3.3'``); it defaults to the current version. You may explicitly set `platform` (and/or `python`) to ``None`` if you wish to map *all* distributions, not just those compatible with the running platform or Python version. N(t_distmapR=tpythontscan(Rt search_pathR=R0((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   cC@sI|jdkp-|jdkp-|j|jk}|oHt|j|jS(sIs distribution `dist` acceptable for this environment? The distribution must match the platform and python version requirements specified when this environment was created, or False is returned. N(R0R3t py_versionRiR=(RRt py_compat((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytcan_addscC@s|j|jj|dS(s"Remove `dist` from the environmentN(R/R.tremove(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR6scC@sQ|dkrtj}nx2|D]*}x!t|D]}|j|q2WqWdS(sdScan `search_path` for distributions usable in this environment Any distributions found are added to the environment. `search_path` should be a sequence of ``sys.path`` items. If not supplied, ``sys.path`` is used. Only distributions conforming to the platform/python version defined at initialization are added. N(R3R<RRVR(RR2RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR1s    cC@s|j}|jj|gS(sReturn a newest-to-oldest list of distributions for `project_name` Uses case-insensitive `project_name` comparison, assuming all the project's distributions use their project's name converted to all lowercase as their key. (tlowerR/R(RR tdistribution_key((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt __getitem__s cC@su|j|rq|jrq|jj|jg}||krq|j||jdtjddt qqndS(sLAdd `dist` if we ``can_add()`` it and it has not already been added R.thashcmptreverseN( R5t has_versionR/RR.RRtoperatort attrgetterR(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   cC@sy|j|}Wn#tk r8|s/nd}nX|dk rI|Sx%||jD]}||krW|SqWW|j||S(sFind distribution best matching `req` and usable on `working_set` This calls the ``find(req)`` method of the `working_set` to see if a suitable distribution is already active. (This may raise ``VersionConflict`` if an unsuitable version of the project is already active in the specified `working_set`.) If a suitable distribution isn't active, this method returns the newest distribution in the environment that meets the ``Requirement`` in `req`. If no suitable distribution is found, and `installer` is supplied, then the result of calling the environment's ``obtain(req, installer)`` method will be returned. N(RRaR3R.tobtain(RRRTRRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s    cC@s|dk r||SdS(sObtain a distribution matching `requirement` (e.g. via download) Obtain a distro that matches requirement (e.g. via download). In the base ``Environment`` class, this routine just returns ``installer(requirement)``, unless `installer` is None, in which case None is returned instead. This method is a hook that allows subclasses to attempt other ways of obtaining a distribution before falling back to the `installer` argument.N(R3(Rt requirementR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR?#s cc@s0x)|jjD]}||r|VqqWdS(s=Yield the unique project names of the available distributionsN(R/R(RR.((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR/s cC@s{t|tr|j|nXt|trdxF|D](}x||D]}|j|qFWq5Wntd|f|S(s2In-place addition of a distribution or environmentsCan't add %r to environment(RR]RRZR(RtothertprojectR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__iadd__5s cC@s@|jgdddd}x||fD]}||7}q(W|S(s4Add an environment or distribution to an environmentR=R0N(RR3(RRAtnewR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__add__AsN(RRRR3RDtPY_MAJORRR5R6R1R9RRR R?RRCRE(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRZs        cB@seZdZRS(sTAn error occurred extracting a resource The following attributes are available from instances of this exception: manager The resource manager that raised this exception cache_path The base directory for resource extraction original_error The exception instance that caused extraction to fail (RRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRdMs cB@seZdZdZdZdZdZdZdZ dZ dZ dZ dd Z ed Zd Zd Zed ZRS(s'Manage resource extraction and packagescC@s i|_dS(N(t cached_files(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRascC@st|j|S(sDoes the named resource exist?(RGR(Rtpackage_or_requirementR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRQdscC@st|j|S(s,Is the named resource an existing directory?(RGRR(RRHR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRRhs cC@st|j||S(s4Return a true filesystem path for specified resource(RGR(RRHR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyROns cC@st|j||S(s9Return a readable file-like object for specified resource(RGR(RRHR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRNts cC@st|j||S(s%Return specified resource as a string(RGR(RRHR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRMzs cC@st|j|S(s1List the contents of the named resource directory(RGRP(RRHR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRPs cC@sttjd}|jpt}tjdj}t|jt }||_ ||_ ||_ |dS(s5Give an error message for problems extracting file(s)is Can't extract file(s) to egg cache The following error occurred while trying to extract file(s) to the Python egg cache: {old_exc} The Python egg cache directory is currently set to: {cache_path} Perhaps your account does not have write access to this directory? You can change the cache directory by setting the PYTHON_EGG_CACHE environment variable to point to an accessible directory. N( R<texc_infotextraction_pathRYttextwraptdedenttlstripRdRRRt cache_pathtoriginal_error(Rtold_excRNttmplterr((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytextraction_errors   cC@sx|jpt}tjj||d|}yt|Wntk rY|jnX|j|d|j |<|S(sReturn absolute location in cache for `archive_name` and `names` The parent directory of the resulting path will be created if it does not already exist. `archive_name` should be the base filename of the enclosing egg (which may not be the name of the enclosing zipfile!), including its ".egg" extension. `names`, if provided, should be a sequence of path name parts "under" the egg's extraction location. This method should only be called by resource providers that need to obtain an extraction location, and only for names they intend to extract, as it tracks the generated names for possible cleanup later. s-tmpi( RJRYRRR>t_bypass_ensure_directoryt ExceptionRSt_warn_unsafe_extraction_pathRG(Rt archive_nametnamest extract_patht target_path((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytget_cache_paths    cC@swtjdkr*|jtjd r*dStj|j}|tj@sV|tj@rsd|}tj |t ndS(sN If the default extraction path is overridden and set to an insecure location, such as /tmp, it opens up an opportunity for an attacker to replace an extracted file with an unauthorized payload. Warn the user if a known insecure location is used. See Distribute #375 for more details. tnttwindirNs%s is writable by group/others and vulnerable to attack when used with get_resource_filename. Consider a more secure location (set with .set_extraction_path or the PYTHON_EGG_CACHE environment variable).( RRRtenvirontstattst_modetS_IWOTHtS_IWGRPtwarningstwarnt UserWarning(Rtmodetmsg((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRVs &cC@s@tjdkr<tj|jdBd@}tj||ndS(s4Perform any platform-specific postprocessing of `tempname` This is where Mac header rewrites should be done; other platforms don't have anything special they should do. Resource providers should call this method ONLY after successfully extracting a compressed resource. They must NOT call it on resources that are already in the filesystem. `tempname` is the current (temporary) name of the file, and `filename` is the name it will be renamed to by the caller after this routine returns. tposiximiN(RRR_R`tchmod(RttempnametfilenameRf((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt postprocessscC@s%|jrtdn||_dS(sSet the base path where resources will be extracted to, if needed. If you do not call this routine before any extractions take place, the path defaults to the return value of ``get_default_cache()``. (Which is based on the ``PYTHON_EGG_CACHE`` environment variable, with various platform-specific fallbacks. See that routine's documentation for more details.) Resources are extracted to subdirectories of this path based upon information given by the ``IResourceProvider``. You may set this to a temporary directory, but then you must call ``cleanup_resources()`` to delete the extracted files when done. There is no guarantee that ``cleanup_resources()`` will be able to remove all extracted files. (Note: you may not change the extraction path for a given resource manager once resources have been extracted, unless you first call ``cleanup_resources()``.) s5Can't change extraction path, files already extractedN(RGRARJ(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRWs  cC@sdS(sB Delete all extracted resource files and directories, returning a list of the file and directory names that could not be successfully removed. This function does not have any concurrency protection, so it should generally only be called when the extraction path is a temporary directory exclusive to a single process. This method is not automatically called; you must call it explicitly or register it as an ``atexit`` function if you wish to ensure cleanup of a temporary directory used for extractions. N((Rtforce((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRXR6N((RRRR3RJRRQRRRORNRMRPRSR[t staticmethodRVRlRWRRX(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR\]s           cC@s"tjjdp!tjddS(s Return the ``PYTHON_EGG_CACHE`` environment variable or a platform-relevant user cache dir for an app named "Python-Eggs". tPYTHON_EGG_CACHEtappnames Python-Eggs(RR^RRtuser_cache_dir(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRYscC@stjdd|S(sConvert an arbitrary string to a standard distribution name Any runs of non-alphanumeric/. characters are replaced with a single '-'. s[^A-Za-z0-9.]+t-(tretsub(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRfscC@sZyttjj|SWn9tjjk rU|jdd}tjdd|SXdS(sB Convert an arbitrary string to a standard version string RR8s[^A-Za-z0-9.]+RrN(RRRRRRRsRt(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRg%s cC@stjdd|jS(sConvert an arbitrary string to a standard 'extra' name Any runs of non-alphanumeric characters are replaced with a single '_', and the result is always lowercased. s[^A-Za-z0-9.-]+R(RsRtR7(R)((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRl1scC@s|jddS(s|Convert a project or version name to its filename-escaped form Any '-' characters are currently replaced with '_'. RrR(R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRm:scC@s;yt|Wn&tk r6}d|_d|_|SXtS(so Validate text as a PEP 508 environment marker; return an exception if invalid or False otherwise. N(Rot SyntaxErrorR3RktlinenoR(ttextte((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRnBs  cC@sLy tjj|}|jSWn%tjjk rG}t|nXdS(s Evaluate a PEP 508 environment marker. Return a boolean indicating the marker result in this environment. Raise SyntaxError if marker is invalid. This implementation uses the 'pyparsing' module. N(RtmarkerstMarkerR+t InvalidMarkerRu(RwR)R*Rx((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRoPs cB@seZdZdZdZdZdZdZdZ dZ dZ dZ dZ dZd Zd Zd Zd Zd ZdZdZdZdZdZRS(sETry to implement resources and metadata for arbitrary PEP 302 loaderscC@s:t|dd|_tjjt|dd|_dS(NRt__file__R6(RR3RRRtdirnamet module_path(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRfscC@s|j|j|S(N(t_fnR~(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRjscC@stj|j||S(N(tiotBytesIOR(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRmscC@s|j|j|j|S(N(t_getRR~(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRpscC@s|j|j|j|S(N(t_hasRR~(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRsscC@s%|jo$|j|j|j|S(N(tegg_infoRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRvscC@sE|js dS|j|j|j|}tjrA|jdS|S(NR6sutf-8(RRRRtPY3tdecode(RRtvalue((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRys cC@st|j|S(N(RjR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|j|j|j|S(N(t_isdirRR~(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRRscC@s%|jo$|j|j|j|S(N(RRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|j|j|j|S(N(t_listdirRR~(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRPscC@s)|jr%|j|j|j|SgS(N(RRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs c B@sd|}|j|s4edjen|j|jdd}|jdd}|j|j|}||dR (RtbaseR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s2t|jdr"|jj|StddS(Ntget_datas=Can't perform this operation for loaders without 'get_data()'(RRRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRsN(RRRR3tegg_nameRRRRRRRRRRRRRRPRRFRRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR~_s,                 cB@s eZdZdZdZRS(s&Provider based on a virtual filesystemcC@stj|||jdS(N(R~Rt _setup_prefix(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|j}d}xt||krt|rdtjj||_tjj|d|_||_ Pn|}tjj |\}}qWdS(NsEGG-INFO( R~R3t _is_egg_pathRRtbasenameRR>Rtegg_rootR (RRtoldR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   (RRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs cB@sJeZdZdZdZdZdZdZedZ RS(s6Provides access to package resources in the filesystemcC@stjj|S(N(RRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@stjj|S(N(RRR (RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s tj|S(N(Rtlistdir(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@st|j|j|dS(Ntrb(R RR~(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s&t|d}|jSWdQXdS(NR(R R(RRtstream((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s)ttdtd}t||dS(NtSourceFileLoader(Rtimportlib_machineryttypeR3R(Rt loader_cls((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt _registers ( RRRRRRRRR(R(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs     cB@s<eZdZdZdZZdZdZdZ RS(s.Provider that returns nothing for all requestscC@stS(N(R(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR5R6cC@sdS(NR6((RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@sgS(N((RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@sdS(N((R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR sN( RRRR3R~RRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR|s    t ZipManifestscB@s#eZdZedZeZRS(s zip manifest builder c@sBtj|-fdjD}t|SWdQXdS(s Build a dictionary similar to the zipimport directory caches, except instead of tuples, store ZipInfo objects. Use a platform-specific path separator (os.sep) for the path keys for compatibility with pypy on Windows. c3@s3|])}|jdtjj|fVqdS(RN(RRtseptgetinfo(R,R(tzfile(s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pys sN(tzipfiletZipFiletnamelistR(RRR#((Rs:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytbuilds  (RRRR(Rtload(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRstMemoizedZipManifestscB@s)eZdZejddZdZRS(s% Memoized zipfile manifests. t manifest_modsmanifest mtimecC@svtjj|}tj|j}||ksC||j|krk|j|}|j||||Rt_extract_resourcet _eager_to_zip(RRRRteagersR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRcs     cC@s/|j}|jd}tj|}||fS(Nii(iii(t file_sizet date_timettimetmktime(tzip_stattsizeRt timestamp((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_get_date_and_sizeps  c C@s||jkr^x9|j|D]'}|j|tjj||}q#Wtjj|S|j|j|\}}tst dny(|j |j |j |}|j ||r|Stddtjj|\}} tj||jj|tj|t| ||f|j| |yt| |Wnltjk rtjj|r|j ||r|Stjdkrt|t| ||SnnXWntjk r|jnX|S(Ns>"os.rename" and "os.unlink" are not supported on this platforms .$extracttdirR\(t_indexRRRR>R}RRt WRITE_SUPPORTtIOErrorR[RRt _is_currentt_mkstemptwriteRRtcloseRRlRterrortisfileRR RS( RRRRtlastRRt real_pathtoutfttmpnam((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRysD    c C@s|j|j|\}}tjj|s2tStj|}|j|ks_|j|krctS|j j |}t |d}|j }WdQX||kS(sK Return True if the file_path is current for this zip_path RN( RRRRRRR_tst_sizeRRRR R( Rt file_pathRRRR_t zip_contentstft file_contents((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@sa|jdkrZg}x6dD].}|j|r|j|j|qqW||_n|jS(Nsnative_libs.txtseager_resources.txt(snative_libs.txtseager_resources.txt(RR3RR R(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs  cC@sy |jSWntk ri}x~|jD]s}|jtj}xX|rtjj|d }||kr||j|dPqF|jg||RR(RtindRtpartstparent((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs     cC@s.|j|}||jkp-||jkS(N(RRR(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|j||jkS(N(RR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s%t|jj|j|dS(N((RRRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|j|j|j|S(N(RRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|j|j|j|S(N(RRR~(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRsN(RRRR3RRRRRRRRRRnRRRRRRRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR?s$     7      cB@s;eZdZdZdZdZdZdZRS(s*Metadata handler for standalone PKG-INFO files Usage:: metadata = FileMetadata("/path/to/PKG-INFO") This provider rejects all data and metadata requests except for PKG-INFO, which is treated as existing, and will be the contents of the file at the provided location. cC@s ||_dS(N(R(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s|dkotjj|jS(NsPKG-INFO(RRR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s_|dkrtdntj|jdddd}|j}WdQX|j||S(NsPKG-INFOs(No metadata except PKG-INFO is availabletencodingsutf-8terrorsR(RRR RRt_warn_on_replacement(RRRtmetadata((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs  ! cC@sGdjd}||krCd}|jt}tj|ndS(Ns�sutf-8s2{self.path} could not be properly decoded in UTF-8(RRRRcRd(RRtreplacement_charRQRg((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s  cC@st|j|S(N(RjR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs(RRRRRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRys     cB@seZdZdZRS(ssMetadata provider for egg directories Usage:: # Development eggs: egg_info = "/path/to/PackageName.egg-info" base_dir = os.path.dirname(egg_info) metadata = PathMetadata(base_dir, egg_info) dist_name = os.path.splitext(os.path.basename(egg_info))[0] dist = Distribution(basedir, project_name=dist_name, metadata=metadata) # Unpacked egg directories: egg_path = "/path/to/PackageName-ver-pyver-etc.egg" metadata = PathMetadata(egg_path, os.path.join(egg_path,'EGG-INFO')) dist = Distribution.from_filename(egg_path, metadata=metadata) cC@s||_||_dS(N(R~R(RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR)s (RRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRzscB@seZdZdZRS(s Metadata provider for .egg filescC@s`|jtj|_||_|jrFtjj|j|j|_n |j|_|j dS(s-Create a metadata provider from a zipimporterN( RRRRRtprefixRR>R~R(Rtimporter((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR1s   ! (RRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR{.sRt_distribution_finderscC@s|t|tfind_eggs_in_zipt zipimportt zipimporterR7Rt from_location( RRRRtsubitemtsubpathRRtsubmeta((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRQs$     cC@sdS(N(((RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt find_nothingoscC@sd}t|d|dtS(sL Given a list of filenames, return them in descending order by version number. >>> names = 'bar', 'foo', 'Python-2.7.10.egg', 'Python-2.7.2.egg' >>> _by_version_descending(names) ['Python-2.7.10.egg', 'Python-2.7.2.egg', 'foo', 'bar'] >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.egg' >>> _by_version_descending(names) ['Setuptools-1.2.3.egg', 'Setuptools-1.2.3b1.egg'] >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.post1.egg' >>> _by_version_descending(names) ['Setuptools-1.2.3.post1.egg', 'Setuptools-1.2.3b1.egg'] cS@sYtjj|\}}tj|jd|g}g|D]}tjj|^q=S(s6 Parse each component of the filename Rr( RRtsplitextt itertoolstchainR RRR(RtextRtpart((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt _by_versionsR.R;(tsortedR(RXR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_by_version_descendingvs c #@sttrHtjdttjjdVdSt}fd|D}t |}xQ|D]I}tjj|}t |}x||D] } | VqWqWdS(s6Yield distributions accessible on a sys.path directoryRsEGG-INFONc3@s'|]}t|r|VqdS(N(t dist_factory(R,R(RR(s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pys s( t_normalize_cachedt_is_unpacked_eggR]RRzRRR>t safe_listdirRR( RRRRtfilteredtpath_item_entriesRtfullpathtfactoryR((RRs:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt find_on_paths       cC@sf|j}tt|jd}|r.tS| rEt|rEtS| r_|jdr_tStS(s9 Return a dist_factory for a path_item and entry s .egg-infos .dist-infos .egg-link(s .egg-infos .dist-info( R7R-RRtdistributions_from_metadataRRVtresolve_egg_linktNoDists(RRRR7tis_meta((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   RcB@s2eZdZdZejr'eZndZRS(sS >>> bool(NoDists()) False >>> list(NoDists()('anything')) [] cC@stS(N(R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__bool__scC@s tdS(N((titer(RR ((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt__call__s(RRRRRtPY2t __nonzero__R(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs    cC@sytj|SWnnttfk r*nXtk r}|jtjtjtjfkpot |dddk}|sqnXdS(sI Attempt to list contents of path, but suppress some exceptions. twinerrori N(( RRtPermissionErrortNotADirectoryErrortOSErrorterrnotENOTDIRtEACCEStENOENTRR3(RRxt ignorable((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s! cc@stjj|}tjj|rUttj|dkrCdSt||}n t|}tjj|}t j |||dt VdS(Nit precedence( RRR}R RRRzRyRR]RRv(RtrootRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs cc@sDt|2}x(|D] }|j}|r|VqqWWdQXdS(s1 Yield non-empty lines from file at path N(R tstrip(RRtline((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytnon_empty_liness   c@s>t}fd|D}tt|}t|dS(sa Given a path to an .egg-link, resolve distributions present in the referenced path. c3@s0|]&}tjjtjj|VqdS(N(RRR>R}(R,tref(R(s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pys s((R%RRVtnext(Rtreferenced_pathstresolved_pathst dist_groups((Rs:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs    t FileFindert_namespace_handlerst_namespace_packagescC@s|t|(Rt path_partst module_partsR(t package_nameR=(s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytposition_in_sys_pathTs NR.(R<RRRRRR/(t orig_pathRARtpRB((RAR=R<s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR5Ds"  cC@s tjz|tkrdStjd}}d|krdj|jdd }t||tkrxt |nytj |j }Wqt k rt d|qXntj|gj|tj|gx|D]}t||qWWdtjXdS(s9Declare that package 'packageName' is a namespace packageNR8isNot a package:(t_impt acquire_lockR-R<RR3R>R RSRRR/RRRRR8t release_lock(R6RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRSes&        cC@sbtjzFx?tj|dD]+}t||}|r t||q q WWdtjXdS(sDEnsure that previously-declared namespace packages include path_itemN((RERFR-RR8RRG(RRtpackageR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs cC@s`tjj||jdd}t|}x+|jD]}t||kr8Pq8q8W|SdS(sBCompute an ns-package subpath for a filesystem or zipfile importerR8iN(RRR>R RR/(RRR6RRt normalizedR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytfile_ns_handlers " cC@sdS(N(R3(RRR6R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytnull_ns_handlerscC@stjjtjj|S(s1Normalize a file/dir name for comparison purposes(RRtnormcasetrealpath(Rk((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRqscC@s9y ||SWn&tk r4t|||<}|SXdS(N(RRq(RkRtresult((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   cC@s|jjdS(s7 Determine if given path appears to be an egg. s.egg(R7R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRscC@s.t|o-tjjtjj|ddS(s@ Determine if given path appears to be an unpacked egg. sEGG-INFOsPKG-INFO(RRRRR>(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs cC@sU|jd}|j}|rQdj|}ttj||tj|ndS(NR8(R RR>tsetattrR<R(R6RRR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR3s  cc@st|tjrVxn|jD]0}|j}|r|jd r|VqqWn-x*|D]"}xt|D] }|VqpWq]WdS(s9Yield non-empty/non-comment lines of a string or sequencet#N(RRRt splitlinesR#RRj(tstrststss((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRjs  s \w+(\.\w+)*$s (?P[^-]+) ( -(?P[^-]+) ( -py(?P[^-]+) ( -(?P.+) )? )? )? cB@seZdZd d ddZdZdZedZdZ dddZ e j dZ eddZed Zedd Zedd ZRS(s3Object representing an advertised importable objectcC@s[t|std|n||_||_t||_t||_||_dS(NsInvalid module name(tMODULERARt module_namettupletattrsR R(RRRVRXR R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   cC@sfd|j|jf}|jr<|ddj|j7}n|jrb|ddj|j7}n|S(Ns%s = %st:R8s [%s]t,(RRVRXR>R (RRS((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRs   cC@sdt|S(NsEntryPoint.parse(%r)(R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR scO@sO| s|s|r,tjdtddn|rE|j||n|jS(sH Require packages for this EntryPoint, then resolve it. sJParameters to load are deprecated. Call .resolve and .require separately.t stackleveli(RcRdtDeprecationWarningRER(RRER4tkwargs((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s cC@sdt|jddgdd}ytjt|j|SWn%tk r_}tt|nXdS(sD Resolve the entry point from its module and attrs. tfromlistRtleveliN( RRVt functoolstreduceRRXRRR(RRtexc((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s cC@sr|jr%|j r%td|n|jj|j}tj|||d|j}tttj|dS(Ns&Can't require() without a distributionR ( R RRcRRTRRRR(RRRRR#((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRE s s]\s*(?P.+?)\s*=\s*(?P[\w.]+)\s*(:\s*(?P[\w.]+))?\s*(?P\[.*\])?\s*$cC@s|jj|}|s0d}t||n|j}|j|d}|drl|djdnd}||d|d|||S(sParse a single entry point from string `src` Entry point syntax follows the form:: name = some.module:some.attr [extra1, extra2] The entry name and module name are required, but the ``:attrs`` and ``[extras]`` parts are optional s9EntryPoint must be in 'name=module:attrs [extras]' formatR tattrR8RR((tpatternR;RAt groupdictt _parse_extrasR (RtsrcRRCRgtresR RX((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR6 s  #cC@s9|s dStjd|}|jr2tn|jS(Ntx((R^RtspecsRAR (Rt extras_specR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRfJ s   cC@st|std|ni}xZt|D]L}|j||}|j|krptd||jn|||j '{project_name} ({version})' is being parsed as a legacy, non PEP 440, version. You may find odd behavior and sort order. In particular it will be sorted as less than 0.0. It is recommended to migrate to PEP 440 compatible versions. s R(RRRRRRKRLR#RRcRdRtvarsR(RtLVt is_legacyRQ((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_warn_legacy_version s  cC@sgy |jSWnUtk rbt|j|j}|dkr^d}t||j|n|SXdS(Ns(Missing 'Version:' header and/or %s file(R{RRyt _get_metadatatPKG_INFOR3RA(RRRQ((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s   cC@s>y |jSWn)tk r6|j|j|_nX|jS(s~ A map of extra to its list of (direct) requirements for this distribution, including the null extra. (t_Distribution__dep_mapRt_filter_extrast_build_dep_map(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_dep_map s   cC@sxttd|D]}|}|j|}|jd\}}}|oet|pet| }|rwg}nt|pd}|j|gj |qW|S(s Given a mapping of extras to dependencies, strip off environment markers and filter out any dependencies not matching the markers. RYN( RRR3RRwRnRoRlRR (tdmR)t new_extraRRR*t fails_marker((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s   cC@s`i}xSdD]K}xBt|j|D]+\}}|j|gjt|q)Wq W|S(Ns requires.txts depends.txt(s requires.txts depends.txt(RkRRR Re(RRRR)R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR, s  "'cC@s|j}g}|j|jddxS|D]K}y|j|t|Wq/tk rytd||fq/Xq/W|S(s@List of Requirements needed for this distro if `extras` are useds%s has no such extra feature %rN((RR RR3RlRRc(RR RtdepsR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR3 s   cc@s5|j|r1x|j|D] }|VqWndS(N(RR(RRR$((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRA scC@s|dkrtj}n|j|d||tjkrt|jx6|jdD]"}|tjkrWt|qWqWWndS(s>Ensure distribution is importable on `path` (default=sys.path)Rsnamespace_packages.txtN( R3R<RRRRRRRS(RRRtpkg((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytactivateF s   cC@sOdt|jt|j|jp'tf}|jrK|d|j7}n|S(s@Return what this distribution's standard .egg filename should bes %s-%s-py%sRr(RmR RR3RFR=(RRk((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRQ s  cC@s(|jrd||jfSt|SdS(Ns%s (%s)(RR(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR\ s cC@sMyt|dd}Wntk r/d}nX|p9d}d|j|fS(NRs[unknown version]s%s %s(RR3RAR (RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRb s    cC@s.|jdrt|nt|j|S(sADelegate all unrecognized public attributes to .metadata providerR(RRRR|(RRc((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt __getattr__j scK@s(|jt|tjj|||S(N(RRRRR(RRkRR ((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRp scC@sTt|jtjjr1d|j|jf}nd|j|jf}tj|S(s?Return a ``Requirement`` that matches this distribution exactlys%s==%ss%s===%s(RRRRRR R^R(Rtspec((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRw scC@sD|j||}|dkr:td||ffn|jS(s=Return the `name` entry point of `group` or raise ImportErrorsEntry point %r not foundN(RKR3RR(RR@RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRI s cC@scy |j}Wn3tk rBtj|jd|}|_nX|dk r_|j|iS|S(s=Return the entry point map for `group`, or the full entry mapsentry_points.txtN(t_ep_mapRR_RqRR3R(RR@tep_map((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRJ s    cC@s|j|j|S(s<Return the EntryPoint object for `group`+`name`, or ``None``(RJR(RR@R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRK sc C@s|p |j}|sdSt|}tjj|}g|D]}|rVt|pY|^q>}xt|D]\}}||kr|rPqdSqo||kro|jtkro| r|||krdS|tjkr|j n|j |||j ||PqoqoW|tjkr.|j n|rG|j d|n |j |dSxMt ry|j ||d} Wntk rPq[X|| =|| =| }q[WdS(sEnsure self.location is on path If replace=False (default): - If location is already in path anywhere, do nothing. - Else: - If it's an egg and its parent directory is on path, insert just ahead of the parent. - Else: add to the end of path. If replace=True: - If location is already on path anywhere (not eggs) or higher priority than its parent (eggs) do nothing. - Else: - If it's an egg and its parent directory is on path, insert just ahead of the parent, removing any lower-priority entries. - Else: add it to the front of path. Nii(RRRRR}t enumerateR!RrR<tcheck_version_conflictRRRR:RA( RRtlocRtnloctbdirRDtnpathRtnp((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR sB +       cC@s|jdkrdStj|jd}t|j}x|jdD]}|tjksJ||ksJ|tkr}qJn|dkrqJnt tj|dd}|rt|j |sJ|j |jrqJnt d|||jfqJWdS( Nt setuptoolssnamespace_packages.txts top_level.txtt pkg_resourcestsiteR|sIModule %s was already imported from %s, but %s is being added to sys.path(RRR( R.RRRRqRR<RR-RR3Rt issue_warning(RtnspRtmodnametfn((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s"  cC@s8y |jWn&tk r3tdt|tSXtS(NsUnbuilt egg for (RRARRRR(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR< s   cK@sYd}x0|jD]"}|j|t||dqW|jd|j|j|S(s@Copy this distribution, substituting in any changed keyword argss<project_name version py_version platform location precedenceRN(R RRR3R|R(RR RXRc((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pytclone s  cC@s g|jD]}|r |^q S(N(R(Rtdep((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR  sN((.RRRRR3RFRrRR(RRRR:RRRRRRRR.RRRRRnRRRRRRRRRRRRRIRJRKRRR<RR (((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR] sR                      D   tEggInfoDistributioncB@seZdZRS(cC@s.t|j|j}|r*||_n|S(s Packages installed by distutils (e.g. numpy or scipy), which uses an old safe_version, and so their version numbers can get mangled when converted to filenames (e.g., 1.11.0.dev0+2329eae to 1.11.0.dev0_2329eae). These distributions will not be parsed properly downstream by Distribution and safe_version, so take an extra step and try to get the version number from the metadata file itself instead of the filename. (RyRRR{(Rt md_version((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s  (RRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR stDistInfoDistributioncB@sJeZdZdZejdZedZedZ dZ RS(sV Wrap an actual or potential sys.path entry w/metadata, .dist-info style. tMETADATAs([\(,])\s*(\d.*?)\s*([,\)])cC@sTy |jSWnBtk rO|j|j}tjjj||_|jSXdS(sParse and cache metadataN(t _pkg_infoRRRtemailtparsertParsertparsestr(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_parsed_pkg_info! s   cC@s6y |jSWn$tk r1|j|_|jSXdS(N(t_DistInfoDistribution__dep_mapRt_compute_dependencies(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR+ s   c@sigd6}|_gx3|jjdp2gD]}jt|q3Wfd}t|d}|dj|xR|jjdpgD]8}t|j}t t|||||R4(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR` s(RRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR_ scc@stt|}x|D]~}d|krA||jd }n|jdr|d j}y|t|7}Wqtk rdSXnt|VqWdS(sYield ``Requirement`` objects for each specification in `strs` `strs` must be a string, or a (possibly-nested) iterable thereof. s #s\iN(RRjRRR#R't StopIterationR^(RRRlR$((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRed s   cB@sMeZdZdZdZdZdZdZedZ RS(cC@sytt|j|Wn+tjjk rG}tt|nX|j|_ t |j}||j |_ |_ g|jD]}|j|jf^q|_ttt|j|_|j |jt|j|jrt|jndf|_t|j|_dS(s>DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!N(tsuperR^RRRtInvalidRequirementRRRt unsafe_nameRfR7R R.t specifierR=RRjRWRRlR RR*R3thashCmpRt_Requirement__hash(Rtrequirement_stringRxR R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR{ s + $cC@st|to|j|jkS(N(RR^R(RRA((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR scC@s ||k S(N((RRA((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR scC@sGt|tr1|j|jkr%tS|j}n|jj|dtS(Nt prereleases(RR]R.RRRtcontainsR(RR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s  cC@s|jS(N(R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR scC@sdt|S(NsRequirement.parse(%r)(R(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR scC@st|\}|S(N(Re(RSR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s( RRRRRRRRRnR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR^z s     cC@st|kr|tfS|S(sJ Ensure object appears in the mro even for old-style classes. (tobject(tclasses((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_always_object s  cC@sPttjt|dt|}x"|D]}||kr.||Sq.WdS(s2Return an adapter factory for `ob` from `registry`RN(RtinspecttgetmroRR(tregistryR/R1tt((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s'  cC@s)tjj|}tj|dtdS(s1Ensure that the parent directory of `path` existstexist_okN(RRR}R tmakedirsR(RR}((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRp scC@s^tstdnt|\}}|rZ|rZt| rZt|t|dndS(s/Sandbox-bypassing version of ensure_directory()s*"os.mkdir" not supported on this platform.iN(RRR R RTR(RR}Rk((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRT s  cc@sd}g}xt|D]y}|jdr|jdrs|sI|rW||fVn|dd!j}g}qtd|q|j|qW||fVdS(ssSplit a string or iterable thereof into (section, content) pairs Each ``section`` is a stripped version of the section header ("[section]") and each ``content`` is a list of stripped lines excluding blank lines and comment-only lines. If there are any such lines before the first section header, they're returned in a first ``section`` of ``None``. t[t]iisInvalid section headingN(R3RjRRR#RAR(RStsectiontcontentR$((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyRk s  cO@s7tj}ztt_tj||SWd|t_XdS(N(RR tos_openttempfiletmkstemp(R4R told_open((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR s   tignoretcategoryRcO@s||||S(N((RR4R]((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt _call_aside s c@s:t|d<|jfdtDdS(s=Set up global resource manager (deliberately not state-saved)t_managerc3@s3|])}|jds|t|fVqdS(RN(RR(R,R(R(s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pys sN(R\RR(R%((Rs:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt _initialize s    cC@stj}tdd||j}|j}|j}|j}|}td|D|ddtg|_ t t |j t jtjtdS(sE Prepare the master working set and make the ``require()`` API available. This function has explicit effects on the global state of pkg_resources. It is intended to be invoked once at the initialization of this module. Invocation by other packages is unsupported and done at their own risk. RRTcs@s!|]}|jdtVqdS(RN(RR(R,R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pys + scS@s|jdtS(NR(RR(R((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyR5/ R6R%N(R[RR!RERLR&RFRWRRRRRR<RRRR(RTRERLRURFR((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyt_initialize_master_working_set s        (Rt __future__RR<RRRRsR1RRRcR_R`tpkgutilR=R=RRt email.parserRRRRKRRRRERtimptpkg_resources.externRtpkg_resources.extern.six.movesRRRRRRR RRRR Rtos.pathR R timportlib.machineryt machineryRRR3R6R RRRt version_infot RuntimeErrorRRRRERTRUtresources_streamRXt resource_dirRNRWRRRMRLRPRORQRR,R-tRuntimeWarningRRRR!R'R)R,R0R1R2t _sget_nonet _sset_noneRDt__all__RUR`RaRRbRcRRRFRrRsRtRuRvRRGR?RR9RR:RRhRiRFRRHRIRJRKRwRxRR[RRRZRRdR\RYRfRgRlRmRnRoR~RRRR|R}RRRRRyRzR{RRVRRRRRRR RR%Rt ImpImporterRR+RR8R5RSRRJRKRqRRRR3RjR;RUtVERBOSEt IGNORECASERR_RuRyR]RRRRRARReRR^RRRpRTRkRtfilterwarningsRRRR(((s:/usr/lib/python2.7/site-packages/pkg_resources/__init__.pyts                                 +                                    .        d   '            ! !          }2   6      PK@N#]%,,*site-packages/pkg_resources/py31compat.pycnu[ fc@sddlZddlZddlZedZejd kpzd ejkoYd knpzd ejkoxd knZerenejZdS(iNcCsJytj|Wn2tk rE}| s<|jtjkrFqFnXdS(N(tostmakedirstOSErrorterrnotEEXIST(tpathtexist_oktexc((s</usr/lib/python2.7/site-packages/pkg_resources/py31compat.pyt _makedirs_31s iiiiii(iii(ii(iii(ii(iii(RRtsystFalseRt version_infotneeds_makedirsR(((s</usr/lib/python2.7/site-packages/pkg_resources/py31compat.pyts    PK@N#]!Ί;;site-packages/easy_install.pyonu[ fc@s0dZedkr,ddlmZendS(sRun the EasyInstall commandt__main__i(tmainN(t__doc__t__name__tsetuptools.command.easy_installR(((s0/usr/lib/python2.7/site-packages/easy_install.pyts PK@N#]P?| *site-packages/pip-9.0.3.dist-info/METADATAnu[Metadata-Version: 2.1 Name: pip Version: 9.0.3 Summary: The PyPA recommended tool for installing Python packages. Home-page: https://pip.pypa.io/ Author: The pip developers Author-email: python-virtualenv@groups.google.com License: MIT Keywords: easy_install distutils setuptools egg virtualenv Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Topic :: Software Development :: Build Tools Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: Implementation :: PyPy Requires-Python: >=2.6,!=3.0.*,!=3.1.*,!=3.2.* Provides-Extra: testing Provides-Extra: testing Requires-Dist: pytest; extra == 'testing' Requires-Dist: virtualenv (>=1.10); extra == 'testing' Requires-Dist: scripttest (>=1.3); extra == 'testing' Requires-Dist: mock; extra == 'testing' Requires-Dist: pretend; extra == 'testing' pip === The `PyPA recommended `_ tool for installing Python packages. * `Installation `_ * `Documentation `_ * `Changelog `_ * `Github Page `_ * `Issue Tracking `_ * `User mailing list `_ * `Dev mailing list `_ * User IRC: #pypa on Freenode. * Dev IRC: #pypa-dev on Freenode. .. image:: https://img.shields.io/pypi/v/pip.svg :target: https://pypi.python.org/pypi/pip .. image:: https://img.shields.io/travis/pypa/pip/master.svg :target: http://travis-ci.org/pypa/pip .. image:: https://img.shields.io/appveyor/ci/pypa/pip.svg :target: https://ci.appveyor.com/project/pypa/pip/history .. image:: https://readthedocs.org/projects/pip/badge/?version=stable :target: https://pip.pypa.io/en/stable Code of Conduct --------------- Everyone interacting in the pip project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the `PyPA Code of Conduct`_. .. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/ PK@N#]bޛ""(site-packages/pip-9.0.3.dist-info/RECORDnu[pip/__init__.py,sha256=4lW9KYLzqHLnjA4LqDJpzrQvCoV1WcsiCpQv6UcaWhU,11934 pip/__main__.py,sha256=V6Kh-IEDEFpt1cahRE6MajUF_14qJR_Qsvn4MjWZXzE,584 pip/basecommand.py,sha256=TTlmZesQ4Vuxcto2KqwZGmgmN5ioHEl_DeFev9ie_SA,11910 pip/baseparser.py,sha256=AKMOeF3fTrRroiv0DmTQbdiLW0DQux2KqGC_dJJB9d0,10465 pip/cmdoptions.py,sha256=8JCcF2kKAF2cFnV77oW-3DsHJifr9jF2WuChzzwgcwg,16474 pip/download.py,sha256=qZIbS-XFZeHSy4Ub_4nRwS9eyEj6vfwm0K8fSLIdzAQ,32847 pip/exceptions.py,sha256=BvqH-Jw3tP2b-2IJ2kjrQemOAPMqKrQMLRIZHZQpJXk,8121 pip/index.py,sha256=L6UhtAEZc2qw7BqfQrkPQcw2gCgEw3GukLRSA95BNyI,39950 pip/locations.py,sha256=9rJRlgonC6QC2zGDIn_7mXaoZ9_tF_IHM2BQhWVRgbo,5626 pip/pep425tags.py,sha256=q3kec4f6NHszuGYIhGIbVvs896D06uJAnKFgJ_wce44,10980 pip/status_codes.py,sha256=F6uDG6Gj7RNKQJUDnd87QKqI16Us-t-B0wPF_4QMpWc,156 pip/wheel.py,sha256=sYlucHaRqyQZJ-e6H-190HHnJQhL5mT0tlNQN3yQ0Ws,32287 pip/_vendor/__init__.py,sha256=WaaSJ3roSSJ_Uv4yKAxlGohKEH9YUA3aIh1Xg2IjfgU,4670 pip/_vendor/appdirs.py,sha256=-9UOIZy62ahCQVY9-b7Nn6_5_4Y6ooHnv72tM8iHi9Y,22368 pip/_vendor/distro.py,sha256=A4Douw9pcqdYxDTp5b-OR02fxVXnfWs-wC1wA89rhRk,38349 pip/_vendor/ipaddress.py,sha256=wimbqcE7rwwETlucn8A_4Qd_-NKXPOBcNxJHarUoXng,80176 pip/_vendor/pyparsing.py,sha256=7vAuUVbh6txUKQR2IzJ8_9DKmD5vtm5MDssWkI0ka8o,224171 pip/_vendor/re-vendor.py,sha256=PcdZ40d0ohMsdJmA4t0AeAWbPXi1tFsvAwA5KE5FGeY,773 pip/_vendor/retrying.py,sha256=k3fflf5_Mm0XcIJYhB7Tj34bqCCPhUDkYbx1NvW2FPE,9972 pip/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 pip/_vendor/cachecontrol/__init__.py,sha256=UPyFlz0dIjxusu5ITig9UDFJdSY5LTwijhldn0AfyzU,302 pip/_vendor/cachecontrol/_cmd.py,sha256=MPxZfZd2LKDzVrs55X3wA1rsI2YuP8evLZSwQj0dIk0,1320 pip/_vendor/cachecontrol/adapter.py,sha256=RaGYyRA-RA1J0AnE67GzEYFPBu4YH4EQUvQqTKa57iM,4608 pip/_vendor/cachecontrol/cache.py,sha256=xtl-V-pr9KSt9VvFDRCB9yrHPEvqvbk-5M1vAInZb5k,790 pip/_vendor/cachecontrol/compat.py,sha256=2MTOyI1JlG_gJpfuy3-UQQlKMRiJimR-XXB0sr44wj0,380 pip/_vendor/cachecontrol/controller.py,sha256=elDsLcaYA15ncodRmHnWQp6ekU_ocEGtDeGLbsnTjzo,13024 pip/_vendor/cachecontrol/filewrapper.py,sha256=_K8cStmXqD33m15PfsQ8rlpo6FfXjVbKmjvLXyICRgI,2531 pip/_vendor/cachecontrol/heuristics.py,sha256=WtJrVsyWjpP9WoUiDVdTZZRNBCz5ZVptaQpYnqofDQU,4141 pip/_vendor/cachecontrol/serialize.py,sha256=XM6elG9DSNexwaOCgMjUtfrHHW5NAB6TSbIf3x235xs,6536 pip/_vendor/cachecontrol/wrapper.py,sha256=Kqyu_3TW_54XDudha4-HF21vyEOAJ4ZnRXFysTiLmXA,498 pip/_vendor/cachecontrol/caches/__init__.py,sha256=uWnUtyMvHY_LULaL_4_IR1F_xPgK5zHfJyRnBq4DnPE,369 pip/_vendor/cachecontrol/caches/file_cache.py,sha256=FsDug3bwUAQ3okjjfGzxlDaBf2fwVSn1iBKMTL6SyGU,3532 pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=XywqxkS9MkCaflTOY_wjrE02neKdywB9YwlOBbP7Ywc,973 pip/_vendor/certifi/__init__.py,sha256=QSRy1UztE-i09IuGIKKuc190k07lt6ktabbelPMIZoc,63 pip/_vendor/certifi/__main__.py,sha256=FiOYt1Fltst7wk9DRa6GCoBr8qBUxlNQu_MKJf04E6s,41 pip/_vendor/certifi/core.py,sha256=9MGV_bfdXHlJJ18qDuEEi_QvAbPUsgK8YggA2b70tqg,806 pip/_vendor/chardet/__init__.py,sha256=YsP5wQlsHJ2auF1RZJfypiSrCA7_bQiRm3ES_NI76-Y,1559 pip/_vendor/chardet/big5freq.py,sha256=D_zK5GyzoVsRes0HkLJziltFQX0bKCLOrFe9_xDvO_8,31254 pip/_vendor/chardet/big5prober.py,sha256=kBxHbdetBpPe7xrlb-e990iot64g_eGSLd32lB7_h3M,1757 pip/_vendor/chardet/chardistribution.py,sha256=3woWS62KrGooKyqz4zQSnjFbJpa6V7g02daAibTwcl8,9411 pip/_vendor/chardet/charsetgroupprober.py,sha256=6bDu8YIiRuScX4ca9Igb0U69TA2PGXXDej6Cc4_9kO4,3787 pip/_vendor/chardet/charsetprober.py,sha256=KSmwJErjypyj0bRZmC5F5eM7c8YQgLYIjZXintZNstg,5110 pip/_vendor/chardet/codingstatemachine.py,sha256=VYp_6cyyki5sHgXDSZnXW4q1oelHc3cu9AyQTX7uug8,3590 pip/_vendor/chardet/compat.py,sha256=PKTzHkSbtbHDqS9PyujMbX74q1a8mMpeQTDVsQhZMRw,1134 pip/_vendor/chardet/cp949prober.py,sha256=TZ434QX8zzBsnUvL_8wm4AQVTZ2ZkqEEQL_lNw9f9ow,1855 pip/_vendor/chardet/enums.py,sha256=Aimwdb9as1dJKZaFNUH2OhWIVBVd6ZkJJ_WK5sNY8cU,1661 pip/_vendor/chardet/escprober.py,sha256=kkyqVg1Yw3DIOAMJ2bdlyQgUFQhuHAW8dUGskToNWSc,3950 pip/_vendor/chardet/escsm.py,sha256=RuXlgNvTIDarndvllNCk5WZBIpdCxQ0kcd9EAuxUh84,10510 pip/_vendor/chardet/eucjpprober.py,sha256=iD8Jdp0ISRjgjiVN7f0e8xGeQJ5GM2oeZ1dA8nbSeUw,3749 pip/_vendor/chardet/euckrfreq.py,sha256=-7GdmvgWez4-eO4SuXpa7tBiDi5vRXQ8WvdFAzVaSfo,13546 pip/_vendor/chardet/euckrprober.py,sha256=MqFMTQXxW4HbzIpZ9lKDHB3GN8SP4yiHenTmf8g_PxY,1748 pip/_vendor/chardet/euctwfreq.py,sha256=No1WyduFOgB5VITUA7PLyC5oJRNzRyMbBxaKI1l16MA,31621 pip/_vendor/chardet/euctwprober.py,sha256=13p6EP4yRaxqnP4iHtxHOJ6R2zxHq1_m8hTRjzVZ95c,1747 pip/_vendor/chardet/gb2312freq.py,sha256=JX8lsweKLmnCwmk8UHEQsLgkr_rP_kEbvivC4qPOrlc,20715 pip/_vendor/chardet/gb2312prober.py,sha256=gGvIWi9WhDjE-xQXHvNIyrnLvEbMAYgyUSZ65HUfylw,1754 pip/_vendor/chardet/hebrewprober.py,sha256=c3SZ-K7hvyzGY6JRAZxJgwJ_sUS9k0WYkvMY00YBYFo,13838 pip/_vendor/chardet/jisfreq.py,sha256=vpmJv2Bu0J8gnMVRPHMFefTRvo_ha1mryLig8CBwgOg,25777 pip/_vendor/chardet/jpcntx.py,sha256=PYlNqRUQT8LM3cT5FmHGP0iiscFlTWED92MALvBungo,19643 pip/_vendor/chardet/langbulgarianmodel.py,sha256=1HqQS9Pbtnj1xQgxitJMvw8X6kKr5OockNCZWfEQrPE,12839 pip/_vendor/chardet/langcyrillicmodel.py,sha256=LODajvsetH87yYDDQKA2CULXUH87tI223dhfjh9Zx9c,17948 pip/_vendor/chardet/langgreekmodel.py,sha256=8YAW7bU8YwSJap0kIJSbPMw1BEqzGjWzqcqf0WgUKAA,12688 pip/_vendor/chardet/langhebrewmodel.py,sha256=JSnqmE5E62tDLTPTvLpQsg5gOMO4PbdWRvV7Avkc0HA,11345 pip/_vendor/chardet/langhungarianmodel.py,sha256=RhapYSG5l0ZaO-VV4Fan5sW0WRGQqhwBM61yx3yxyOA,12592 pip/_vendor/chardet/langthaimodel.py,sha256=8l0173Gu_W6G8mxmQOTEF4ls2YdE7FxWf3QkSxEGXJQ,11290 pip/_vendor/chardet/langturkishmodel.py,sha256=W22eRNJsqI6uWAfwXSKVWWnCerYqrI8dZQTm_M0lRFk,11102 pip/_vendor/chardet/latin1prober.py,sha256=S2IoORhFk39FEFOlSFWtgVybRiP6h7BlLldHVclNkU8,5370 pip/_vendor/chardet/mbcharsetprober.py,sha256=AR95eFH9vuqSfvLQZN-L5ijea25NOBCoXqw8s5O9xLQ,3413 pip/_vendor/chardet/mbcsgroupprober.py,sha256=h6TRnnYq2OxG1WdD5JOyxcdVpn7dG0q-vB8nWr5mbh4,2012 pip/_vendor/chardet/mbcssm.py,sha256=SY32wVIF3HzcjY3BaEspy9metbNSKxIIB0RKPn7tjpI,25481 pip/_vendor/chardet/sbcharsetprober.py,sha256=LDSpCldDCFlYwUkGkwD2oFxLlPWIWXT09akH_2PiY74,5657 pip/_vendor/chardet/sbcsgroupprober.py,sha256=1IprcCB_k1qfmnxGC6MBbxELlKqD3scW6S8YIwdeyXA,3546 pip/_vendor/chardet/sjisprober.py,sha256=IIt-lZj0WJqK4rmUZzKZP4GJlE8KUEtFYVuY96ek5MQ,3774 pip/_vendor/chardet/universaldetector.py,sha256=qL0174lSZE442eB21nnktT9_VcAye07laFWUeUrjttY,12485 pip/_vendor/chardet/utf8prober.py,sha256=IdD8v3zWOsB8OLiyPi-y_fqwipRFxV9Nc1eKBLSuIEw,2766 pip/_vendor/chardet/version.py,sha256=sp3B08mrDXB-pf3K9fqJ_zeDHOCLC8RrngQyDFap_7g,242 pip/_vendor/chardet/cli/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 pip/_vendor/chardet/cli/chardetect.py,sha256=YBO8L4mXo0WR6_-Fjh_8QxPBoEBNqB9oNxNrdc54AQs,2738 pip/_vendor/colorama/__init__.py,sha256=9xByrTvk9upkL5NGV5It2Eje4-kzNLwa_1lGPWpXoNU,240 pip/_vendor/colorama/ansi.py,sha256=Fi0un-QLqRm-v7o_nKiOqyC8PapBJK7DLV_q9LKtTO0,2524 pip/_vendor/colorama/ansitowin32.py,sha256=gJZB35Lbdjatykd2zrUUnokMzkvcFgscyn_tNxxMFHA,9668 pip/_vendor/colorama/initialise.py,sha256=cHqVJtb82OG7HUCxvQ2joG7N_CoxbIKbI_fgryZkj20,1917 pip/_vendor/colorama/win32.py,sha256=_SCEoTK_GA2tU1nhbayKKac-v9Jn98lCPIFOeFMGCHQ,5365 pip/_vendor/colorama/winterm.py,sha256=V7U7ojwG1q4n6PKripjEvW_htYQi5ueXSM3LUUoqqDY,6290 pip/_vendor/distlib/__init__.py,sha256=-aUeNNCfiIG_1Tqf19BH0xLNuBKGX1I7lNhcLYgFUEA,581 pip/_vendor/distlib/compat.py,sha256=FzKlP9dNUMH-j_1LCVnjgx6KgUbpnRjTjYkTkDYRPlI,40801 pip/_vendor/distlib/database.py,sha256=jniJmYk0Mj2t6gZYbnn68TvQwnVZ0kXyeuf_3AxFclk,49672 pip/_vendor/distlib/index.py,sha256=Cw8gxFq_7xXvdgExL3efjLAY3EAPDMSL3VA42RkbQBs,21085 pip/_vendor/distlib/locators.py,sha256=hD_Hm3aSL9DklY9Cxyct2n_74gZ0xNFFGB5L7M6ds14,51013 pip/_vendor/distlib/manifest.py,sha256=3qEuZhHlDbvyYZ1BZbdapDAivgMgUwWpZ00cmXqcn18,14810 pip/_vendor/distlib/markers.py,sha256=iRrVWwpyVwjkKJSX8NEQ92_MRMwpROcfNGKCD-Ch1QM,6282 pip/_vendor/distlib/metadata.py,sha256=hUsf7Qh2Ae4CCkL33qK8ppwC8ZTzT7ep6Hj9RKpijKU,38833 pip/_vendor/distlib/resources.py,sha256=VFBVbFqLVqDBSQDXcFQHrX1KEcuoDxTK699Ydi_beyc,10766 pip/_vendor/distlib/scripts.py,sha256=xpehNfISGPTNxQZu02K9Rw2QbNx_2Q4emePv3W5X0iw,15224 pip/_vendor/distlib/util.py,sha256=E2wU-RZShPMFUMJr9kPmemTULinM4qDzosNPihCuKE0,52991 pip/_vendor/distlib/version.py,sha256=CgghOUylxGD7dEA2S3MvWjx7mY_2bWsluF0Of3Yxl4Y,23711 pip/_vendor/distlib/wheel.py,sha256=UP53cKxOM5r7bHSS-n5prF6hwJEVsMW9ZNJutOuC26c,39115 pip/_vendor/distlib/_backport/__init__.py,sha256=bqS_dTOH6uW9iGgd0uzfpPjo6vZ4xpPZ7kyfZJ2vNaw,274 pip/_vendor/distlib/_backport/misc.py,sha256=KWecINdbFNOxSOP1fGF680CJnaC6S4fBRgEtaYTw0ig,971 pip/_vendor/distlib/_backport/shutil.py,sha256=VW1t3uYqUjWZH7jV-6QiimLhnldoV5uIpH4EuiT1jfw,25647 pip/_vendor/distlib/_backport/sysconfig.cfg,sha256=swZKxq9RY5e9r3PXCrlvQPMsvOdiWZBTHLEbqS8LJLU,2617 pip/_vendor/distlib/_backport/sysconfig.py,sha256=eSEyJg7jxF_eHlHG8IOtl93kb07UoMIRp1wYsPeGi9k,26955 pip/_vendor/distlib/_backport/tarfile.py,sha256=Ihp7rXRcjbIKw8COm9wSePV9ARGXbSF9gGXAMn2Q-KU,92628 pip/_vendor/html5lib/__init__.py,sha256=JsIwmFldk-9raBadPSTS74JrfmJvozc-3aekMi7Hr9s,780 pip/_vendor/html5lib/_ihatexml.py,sha256=tzXygYmisUmiEUt2v7E1Ab50AKQsrD-SglPRnY75vME,16705 pip/_vendor/html5lib/_inputstream.py,sha256=C4lX5gUBwebOWy41hYP2ZBpkPVNvxk_hZBm3OVyPZM4,32532 pip/_vendor/html5lib/_tokenizer.py,sha256=YAaOEBD6qc5ISq9Xt9Nif1OFgcybTTfMdwqBkZhpAq4,76580 pip/_vendor/html5lib/_utils.py,sha256=bS6THVlL8ZyTcI6CIxiM6xxuHsE8i1j5Ogd3Ha1G84U,4096 pip/_vendor/html5lib/constants.py,sha256=Dfc1Fv3_9frktgWjg4tbj-CjMMp02Ko9qMe4il1BVdo,83387 pip/_vendor/html5lib/html5parser.py,sha256=Dmlu9hlq5w_id6mBZyY_sE5LukIACgvG4kpgIsded8Q,117170 pip/_vendor/html5lib/serializer.py,sha256=Urrsa0cPPLqNX-UbJWS2gUhs_06qVbNxZvUnrmGZK6E,14177 pip/_vendor/html5lib/_trie/__init__.py,sha256=8VR1bcgD2OpeS2XExpu5yBhP_Q1K-lwKbBKICBPf1kU,289 pip/_vendor/html5lib/_trie/_base.py,sha256=6P_AcIoGjtwB2qAlhV8H4VP-ztQxoXFGwt4NyMqG_Kw,979 pip/_vendor/html5lib/_trie/datrie.py,sha256=EQpqSfkZRuTbE-DuhW7xMdVDxdZNZ0CfmnYfHA_3zxM,1178 pip/_vendor/html5lib/_trie/py.py,sha256=wXmQLrZRf4MyWNyg0m3h81m9InhLR7GJ002mIIZh-8o,1775 pip/_vendor/html5lib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pip/_vendor/html5lib/filters/alphabeticalattributes.py,sha256=DXv-P2vdQ5F3OTWM6QZ6KhyDlAWm90pbfrD1Bk9D_l0,621 pip/_vendor/html5lib/filters/base.py,sha256=z-IU9ZAYjpsVsqmVt7kuWC63jR11hDMr6CVrvuao8W0,286 pip/_vendor/html5lib/filters/inject_meta_charset.py,sha256=2Q_JnMscn_tNbV_qpgYN_5M3PnBGfmuvECMKDExHUcY,2742 pip/_vendor/html5lib/filters/lint.py,sha256=qf5cLrT6xXd8V7GH1R_3lKxIjuJSfpbWTpSwaglYdDw,3365 pip/_vendor/html5lib/filters/optionaltags.py,sha256=EHig4kM-QiLjuxVJ3FAAFNy-10k4aV6HJbQzHKZ_3u8,10534 pip/_vendor/html5lib/filters/sanitizer.py,sha256=7PqJrhm6mo3JvaHk2IQW7i74Or7Qtd-FV8UftJIyDys,25112 pip/_vendor/html5lib/filters/whitespace.py,sha256=KPt067nYTqqi8KLTClyynn4eVzNDC_-MApXNVHRXVX0,1139 pip/_vendor/html5lib/treeadapters/__init__.py,sha256=l3LcqMSEyoh99Jh_eWjGexHnIvKhLAXoP-LDz88whuM,208 pip/_vendor/html5lib/treeadapters/genshi.py,sha256=6VIuHDNoExv1JWv3ePj6V5CM-tcyiUSWe5_Hd2ejbwY,1555 pip/_vendor/html5lib/treeadapters/sax.py,sha256=3of4vvaUYIAic7pngebwJV24hpOS7Zg9ggJa_WQegy4,1661 pip/_vendor/html5lib/treebuilders/__init__.py,sha256=UlB4orkTgZhFIKQdXrtiWn9cpKSsuhnOQOIHeD0Fv4k,3406 pip/_vendor/html5lib/treebuilders/base.py,sha256=4vdjm_Z2f_GTQBwKnWlrzVcctTb-K5sfN8pXDaWODiA,13942 pip/_vendor/html5lib/treebuilders/dom.py,sha256=SY3MsijXyzdNPc8aK5IQsupBoM8J67y56DgNtGvsb9g,8835 pip/_vendor/html5lib/treebuilders/etree.py,sha256=aqIBOGj_dFYqBURIcTegGNBhAIJOw5iFDHb4jrkYH-8,12764 pip/_vendor/html5lib/treebuilders/etree_lxml.py,sha256=CEgwHMIQZvIDFAqct4kqPkVtyKIm9efHFq_VeExEPCA,14161 pip/_vendor/html5lib/treewalkers/__init__.py,sha256=CFpUOCfLuhAgVJ8NYk9wviCu1khYnv7XRStvyzU1Fws,5544 pip/_vendor/html5lib/treewalkers/base.py,sha256=ei-2cFbNFd0gRjyaFmxnxZGLNID4o0bHFCH9bMyZ5Bk,4939 pip/_vendor/html5lib/treewalkers/dom.py,sha256=EHyFR8D8lYNnyDU9lx_IKigVJRyecUGua0mOi7HBukc,1413 pip/_vendor/html5lib/treewalkers/etree.py,sha256=8jVLEY2FjgN4RFugwhAh44l9ScVYoDStQFCnlPwvafI,4684 pip/_vendor/html5lib/treewalkers/etree_lxml.py,sha256=sY6wfRshWTllu6n48TPWpKsQRPp-0CQrT0hj_AdzHSU,6309 pip/_vendor/html5lib/treewalkers/genshi.py,sha256=4D2PECZ5n3ZN3qu3jMl9yY7B81jnQApBQSVlfaIuYbA,2309 pip/_vendor/idna/__init__.py,sha256=9Nt7xpyet3DmOrPUGooDdAwmHZZu1qUAy2EaJ93kGiQ,58 pip/_vendor/idna/codec.py,sha256=lvYb7yu7PhAqFaAIAdWcwgaWI2UmgseUua-1c0AsG0A,3299 pip/_vendor/idna/compat.py,sha256=R-h29D-6mrnJzbXxymrWUW7iZUvy-26TQwZ0ij57i4U,232 pip/_vendor/idna/core.py,sha256=GafiWdYQIK5TSjWdRzCYCho704ALtMCrV_dnXXn57U0,11390 pip/_vendor/idna/idnadata.py,sha256=-Cg83lurKoA9p7lb0lMAsos0rFz1dnKrGeBE3o8UuCA,32999 pip/_vendor/idna/intranges.py,sha256=TY1lpxZIQWEP6tNqjZkFA5hgoMWOj1OBmnUG8ihT87E,1749 pip/_vendor/idna/package_data.py,sha256=KMSUTS_M7ZZ7Ugl_V_EOxV-D3o7v7yVkt45JK_bpW24,21 pip/_vendor/idna/uts46data.py,sha256=YylQYBfljAx_WVqR2D7HgcGGyVCWwPm6uF38aERuhyw,184944 pip/_vendor/lockfile/__init__.py,sha256=Tqpz90DwKYfhPsfzVOJl84TL87pdFE5ePNHdXAxs4Tk,9371 pip/_vendor/lockfile/linklockfile.py,sha256=C7OH3H4GdK68u4FQgp8fkP2kO4fyUTSyj3X6blgfobc,2652 pip/_vendor/lockfile/mkdirlockfile.py,sha256=e3qgIL-etZMLsS-3ft19iW_8IQ360HNkGOqE3yBKsUw,3096 pip/_vendor/lockfile/pidlockfile.py,sha256=ukH9uk6NFuxyVmG5QiWw4iKq3fT7MjqUguX95avYPIY,6090 pip/_vendor/lockfile/sqlitelockfile.py,sha256=o2TMkMRY0iwn-iL1XMRRIFStMUkS4i3ajceeYNntKFg,5506 pip/_vendor/lockfile/symlinklockfile.py,sha256=ABwXXmvTHvCl5viPblShL3PG-gGsLiT1roAMfDRwhi8,2616 pip/_vendor/packaging/__about__.py,sha256=zkcCPTN_6TcLW0Nrlg0176-R1QQ_WVPTm8sz1R4-HjM,720 pip/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 pip/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 pip/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 pip/_vendor/packaging/markers.py,sha256=mtg2nphJE1oQO39g1DgsdPsMO-guBBClpR-AEYFrbMg,8230 pip/_vendor/packaging/requirements.py,sha256=SD7dVJGjdPUqtoHb47qwK6wWJTQd-ZXWjxpJg83UcBA,4327 pip/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 pip/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 pip/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 pip/_vendor/pkg_resources/__init__.py,sha256=CcwuHtCBZn9OTkmgF9cFpadIAMhlrnZTVKTOo4V2p58,103230 pip/_vendor/progress/__init__.py,sha256=Wn1074LUDZovd4zfoVYojnPBgOc6ctHbQX7rp_p8lRA,3023 pip/_vendor/progress/bar.py,sha256=YNPJeRrwYVKFO2nyaEwsQjYByamMWTgJMvQO1NpD-AY,2685 pip/_vendor/progress/counter.py,sha256=kEqA8jWEdwrc6P_9VaRx7bjOHwk9gxl-Q9oVbQ08v5c,1502 pip/_vendor/progress/helpers.py,sha256=FehfwZTv-5cCfsbcMlvlUkm3xZ0cRhsev6XVpmeTF4c,2854 pip/_vendor/progress/spinner.py,sha256=iCVtUQbaJUFHTjn1ZLPQLPYeao4lC9aXAa_HxIeUK6k,1314 pip/_vendor/requests/__init__.py,sha256=JRFVBw6JyV98WQSqv8jshc5_g9xIbLhevI5LHaVi9I4,3575 pip/_vendor/requests/__version__.py,sha256=BQ279bjqQ_8PHhvD_FN36UuFqjbSUqsm7bMeyJV-kVo,436 pip/_vendor/requests/_internal_utils.py,sha256=Zx3PnEUccyfsB-ie11nZVAW8qClJy0gx1qNME7rgT18,1096 pip/_vendor/requests/adapters.py,sha256=LAay3OH0ZbvI6bDW_M5Of06tU5z2fnCflrp_Xm38KsY,21016 pip/_vendor/requests/api.py,sha256=BqVZnvsWu6Pwm0vQ3fw_Dj9_I-gcOR9CbScB2htPArA,6237 pip/_vendor/requests/auth.py,sha256=4KCFQHrL1Lcox3uMh4tjOh3OrJhw-F5zti91wY-ZyTY,9728 pip/_vendor/requests/certs.py,sha256=nXRVq9DtGmv_1AYbwjTu9UrgAcdJv05ZvkNeaoLOZxY,465 pip/_vendor/requests/compat.py,sha256=kcqhV7U43c4i8Ouk5e5YdJXMDEmWNLT97LYm6Uor-74,1626 pip/_vendor/requests/cookies.py,sha256=u7QC5hmloMwdT9-2taz5GpwAvzp2LTUS9cP4SWUKnfM,18208 pip/_vendor/requests/exceptions.py,sha256=oZwYwCm65Y0FMuFqojEgUlWUBQ4MkXRy5URHV1b98L4,3115 pip/_vendor/requests/help.py,sha256=UuBTtc7tEpnU_ivnpuk2hjgzuS6z7GnTEkSbENlc1XQ,3667 pip/_vendor/requests/hooks.py,sha256=HXAHoC1FNTFRZX6-lNdvPM7Tst4kvGwYTN-AOKRxoRU,767 pip/_vendor/requests/models.py,sha256=lcz2GEOe2eOu-GqAGdpA0vJUpI7EE4eDSlWI78R8Y64,34051 pip/_vendor/requests/packages.py,sha256=njJmVifY4aSctuW3PP5EFRCxjEwMRDO6J_feG2dKWsI,695 pip/_vendor/requests/sessions.py,sha256=Ug4EFuHIkqS3EPmD__hWy0JVCzoAGv_F342kzVLnHrg,28689 pip/_vendor/requests/status_codes.py,sha256=a9bwuU7lMr4HshsRZdzBbUsYVsIo4Fu9GYg1XFTFFPc,3323 pip/_vendor/requests/structures.py,sha256=yexCvWbX40M6E8mLQOpAGZZ-ZoAnyaT2dni-Bp-b42g,3012 pip/_vendor/requests/utils.py,sha256=YEGPbyXaf3hosTL0dI4JrCIDpGYaFgHtLhYj96py7AQ,27695 pip/_vendor/urllib3/__init__.py,sha256=EfUPF9RHveaF9g5dcK5kBsGDp5LrIB-396MpK2RQk1I,2853 pip/_vendor/urllib3/_collections.py,sha256=b0-x45LBArs96Rum5xGAbPsriwfB3MZVQbsv7lFiUwE,10204 pip/_vendor/urllib3/connection.py,sha256=4GKR8uXHz6IpztYhtuhKBqXj84HbbFUF3CvwymGfLD0,13003 pip/_vendor/urllib3/connectionpool.py,sha256=5ub8CXnKs1wc2X-MyuVVPo3_9scWLghSgbHOJTpQXuE,35358 pip/_vendor/urllib3/exceptions.py,sha256=dz1gBEgtROnLrW8V911KhVZWeAn3H2OhDGztWNXQpr0,6603 pip/_vendor/urllib3/fields.py,sha256=YrNRM8RBUmM8guXKUQFa3kwj6XvQZ78Z8inE6l-YK-E,5943 pip/_vendor/urllib3/filepost.py,sha256=NF6Rly66bilWU-sdULXjCdQgN1uRxfFRedeifcRLzkU,2321 pip/_vendor/urllib3/poolmanager.py,sha256=V843K_nTlkV8u3GIj6M-ProgIuUIkqpgOsLy_epC-q4,16820 pip/_vendor/urllib3/request.py,sha256=wrt2D0SWLLgTRKrRnaZophq2xXpCvNRd7RMT6F5o5hY,5946 pip/_vendor/urllib3/response.py,sha256=7mGUH35L2IPuZVOY7QvDQ1GSSKIf6V6geJXThdjmQD4,22903 pip/_vendor/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pip/_vendor/urllib3/contrib/appengine.py,sha256=41l3arTy-kBBpOdVpSPYVC64Qo7RLnXnDED6hcIthA0,10865 pip/_vendor/urllib3/contrib/ntlmpool.py,sha256=Q9-rO5Rh2-IqyEd4ZicpTDfMnOlf0IPPCkjhChBCjV4,4478 pip/_vendor/urllib3/contrib/pyopenssl.py,sha256=BxJ1yMPE62duuHJP6jlZxLz_FNTKbWI0b-nVRKlBDgI,15354 pip/_vendor/urllib3/contrib/securetransport.py,sha256=ZRPz6Q1tnsu9H1BOAQVUSHIyowWmfaBb7pGlbG5iOPk,30501 pip/_vendor/urllib3/contrib/socks.py,sha256=zPYUKMg_c0n9HFjZPG9nGN2kjpaH7qUCZxrD5B7G0_I,6195 pip/_vendor/urllib3/contrib/_securetransport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pip/_vendor/urllib3/contrib/_securetransport/bindings.py,sha256=x2kLSh-ASZKsun0FxtraBuLVe3oHuth4YW6yZ5Vof-w,17560 pip/_vendor/urllib3/contrib/_securetransport/low_level.py,sha256=UbhUykEH6HUIJud9_rn_6YWjionk5iq_rq6YrhVM6Co,12062 pip/_vendor/urllib3/packages/__init__.py,sha256=nlChrGzkjCkmhCX9HrF_qHPUgosfsPQkVIJxiiLhk9g,109 pip/_vendor/urllib3/packages/ordered_dict.py,sha256=VQaPONfhVMsb8B63Xg7ZOydJqIE_jzeMhVN3Pec6ogw,8935 pip/_vendor/urllib3/packages/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 pip/_vendor/urllib3/packages/backports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pip/_vendor/urllib3/packages/backports/makefile.py,sha256=r1IADol_pBBq2Y1ub4CPyuS2hXuShK47nfFngZRcRhI,1461 pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py,sha256=WBVbxQBojNAxfZwNavkox3BgJiMA9BJmm-_fwd0jD_o,688 pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py,sha256=lAj7qGCZLOldhn8gZDY6Tqp4mvgkbTfy4k4gDIDRo8g,5702 pip/_vendor/urllib3/util/__init__.py,sha256=6Ran4oAVIy40Cu_oEPWnNV9bwF5rXx6G1DUZ7oehjPY,1044 pip/_vendor/urllib3/util/connection.py,sha256=_6_5JZJF3HHRXR7HaxHg3mk7qMKK3N0nl3DL8gFAfo4,4237 pip/_vendor/urllib3/util/request.py,sha256=H5_lrHvtwl2U2BbT1UYN9HpruNc1gsNFlz2njQmhPrQ,3705 pip/_vendor/urllib3/util/response.py,sha256=SSNL888W-MQ8t3HAi44kNGgF682p6H__ytEXzBYxV_M,2343 pip/_vendor/urllib3/util/retry.py,sha256=ZfL_m5PNUz8XSNy4VJT77Z3EnykjPBLYYHF-3rF_jeM,15104 pip/_vendor/urllib3/util/selectors.py,sha256=PIINzwjiD5Z6IyTKA1tR5n1kCOXyThpDCE2fCVFzLeM,21147 pip/_vendor/urllib3/util/ssl_.py,sha256=4cgfqqgM5U_71CgpKG-aqcUDInWv5-YaPeguohjC97I,12214 pip/_vendor/urllib3/util/timeout.py,sha256=7lHNrgL5YH2cI1j-yZnzV_J8jBlRVdmFhQaNyM1_2b8,9757 pip/_vendor/urllib3/util/url.py,sha256=2hwSEH6nZjUTeE6o54BmZy_8irGtOZpGezXExDcsP1g,6798 pip/_vendor/urllib3/util/wait.py,sha256=Q_pd_bD6iaPgRKwEmcjTYDrSPj4Dd4ojykmqA398b8o,1451 pip/_vendor/webencodings/__init__.py,sha256=t7rAQQxXwalY-ak9hTl73qHjhia9UH-sL-e00qQrBpo,10576 pip/_vendor/webencodings/labels.py,sha256=4AO_KxTddqGtrL9ns7kAPjb0CcN6xsCIxbK37HY9r3E,8979 pip/_vendor/webencodings/mklabels.py,sha256=GYIeywnpaLnP0GSic8LFWgd0UVvO_l1Nc6YoF-87R_4,1305 pip/_vendor/webencodings/tests.py,sha256=7vTk7LgOJn_t1XtT_viofZlEJ7cJCzPe_hvVHOkcQl8,6562 pip/_vendor/webencodings/x_user_defined.py,sha256=72cfPRhbfkRCGkkA8ZnvVV7UnoiLb5uPMhXwhrXiLPk,4306 pip/commands/__init__.py,sha256=2Uq3HCdjchJD9FL1LB7rd5v6UySVAVizX0W3EX3hIoE,2244 pip/commands/check.py,sha256=-A7GI1-WZBh9a4P6UoH_aR-J7I8Lz8ly7m3wnCjmevs,1382 pip/commands/completion.py,sha256=kkPgVX7SUcJ_8Juw5GkgWaxHN9_45wmAr9mGs1zXEEs,2453 pip/commands/download.py,sha256=8RuuPmSYgAq3iEDTqZY_1PDXRqREdUULHNjWJeAv7Mo,7810 pip/commands/freeze.py,sha256=h6-yFMpjCjbNj8-gOm5UuoF6cg14N5rPV4TCi3_CeuI,2835 pip/commands/hash.py,sha256=MCt4jEFyfoce0lVeNEz1x49uaTY-VDkKiBvvxrVcHkw,1597 pip/commands/help.py,sha256=84HWkEdnGP_AEBHnn8gJP2Te0XTXRKFoXqXopbOZTNo,982 pip/commands/install.py,sha256=q45kfTQUKkUJLCdPs38FKYfrVeFz4i9WyeRLfcr4b-Y,18289 pip/commands/list.py,sha256=93bCiFyt2Qut_YHkYHJMZHpXladmxsjS-yOtZeb3uqI,11369 pip/commands/search.py,sha256=oTs9QNdefnrmCV_JeftG0PGiMuYVmiEDF1OUaYsmDao,4502 pip/commands/show.py,sha256=ZYM57_7U8KP9MQIIyHKQdZxmiEZByy-DRzB697VFoTY,5891 pip/commands/uninstall.py,sha256=tz8cXz4WdpUdnt3RvpdQwH6_SNMB50egBIZWa1dwfcc,2884 pip/commands/wheel.py,sha256=z5SEhws2YRMb0Ml1IEkg6jFZMLRpLl86bHCrQbYt5zo,7729 pip/compat/__init__.py,sha256=2Xs_IpsmdRgHbQgQO0c8_lPvHJnQXHyGWxPbLbYJL4c,4672 pip/compat/dictconfig.py,sha256=dRrelPDWrceDSzFT51RTEVY2GuM7UDyc5Igh_tn4Fvk,23096 pip/models/__init__.py,sha256=0Rs7_RA4DxeOkWT5Cq4CQzDrSEhvYcN3TH2cazr72PE,71 pip/models/index.py,sha256=pUfbO__v3mD9j-2n_ClwPS8pVyx4l2wIwyvWt8GMCRA,487 pip/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pip/operations/check.py,sha256=uwUN9cs1sPo7c0Sj6pRrSv7b22Pk29SXUImTelVchMQ,1590 pip/operations/freeze.py,sha256=k-7w7LsM-RpPv7ERBzHiPpYkH-GuYfHLyR-Cp_1VPL0,5194 pip/req/__init__.py,sha256=vFwZY8_Vc1WU1zFAespg1My_r_AT3n7cN0W9eX0EFqk,276 pip/req/req_file.py,sha256=fG9MDsXUNPhmGwxUiwrIXEynyD8Q7s3L47-hLZPDXq0,11926 pip/req/req_install.py,sha256=U2n95c8zh7TE5Zo49EjygQOAlngVBmnZAVsOZG_UrSA,46683 pip/req/req_set.py,sha256=jHspXqcA2FxcF05dgUIAZ5huYPv6bn0wRUX0Z7PKmaA,34462 pip/req/req_uninstall.py,sha256=fdH2VgCjEC8NRYDS7fRu3ZJaBBUEy-N5muwxDX5MBNM,6897 pip/utils/__init__.py,sha256=HX_wYS15oiYOz-H3qG1Kbi1CY7AGWCNK5jloiD0fauc,27187 pip/utils/appdirs.py,sha256=kj2LK-I2fC5QnEh_A_v-ev_IQMcXaWWF5DE39sNvCLQ,8811 pip/utils/build.py,sha256=4smLRrfSCmXmjEnVnMFh2tBEpNcSLRe6J0ejZJ-wWJE,1312 pip/utils/deprecation.py,sha256=X_FMjtDbMJqfqEkdRrki-mYyIdPB6I6DHUTCA_ChY6M,2232 pip/utils/encoding.py,sha256=NQxGiFS5GbeAveLZTnx92t5r0PYqvt0iRnP2u9SGG1w,971 pip/utils/filesystem.py,sha256=ZEVBuYM3fqr2_lgOESh4Y7fPFszGD474zVm_M3Mb5Tk,899 pip/utils/glibc.py,sha256=jcQYjt_oJLPKVZB28Kauy4Sw70zS-wawxoU1HHX36_0,2939 pip/utils/hashes.py,sha256=oMk7cd3PbJgzpSQyXq1MytMud5f6H5Oa2YY5hYuCq6I,2866 pip/utils/logging.py,sha256=7yWu4gZw-Qclj7X80QVdpGWkdTWGKT4LiUVKcE04pro,3327 pip/utils/outdated.py,sha256=9xLA0dbtgGBb07OTI1bHbrA5rVFtOv7XbBCdSosRe6s,5989 pip/utils/packaging.py,sha256=qhmli14odw6DIhWJgQYS2Q0RrSbr8nXNcG48f5yTRms,2080 pip/utils/setuptools_build.py,sha256=0blfscmNJW_iZ5DcswJeDB_PbtTEjfK9RL1R1WEDW2E,278 pip/utils/ui.py,sha256=pbDkSAeumZ6jdZcOJ2yAbx8iBgeP2zfpqNnLJK1gskQ,11597 pip/vcs/__init__.py,sha256=WafFliUTHMmsSISV8PHp1M5EXDNSWyJr78zKaQmPLdY,12374 pip/vcs/bazaar.py,sha256=tYTwc4b4off8mr0O2o8SiGejqBDJxcbDBMSMd9-ISYc,3803 pip/vcs/git.py,sha256=5LfWryi78A-2ULjEZJvCTarJ_3l8venwXASlwm8hiug,11197 pip/vcs/mercurial.py,sha256=xG6rDiwHCRytJEs23SIHBXl_SwQo2jkkdD_6rVVP5h4,3472 pip/vcs/subversion.py,sha256=GAuX2Sk7IZvJyEzENKcVld_wGBrQ3fpXDlXjapZEYdI,9350 pip-9.0.3.dist-info/METADATA,sha256=7TKg_fIKb5ZtStvVt1I2cVLTy_YeR0tCSLKegg3AcMs,2553 pip-9.0.3.dist-info/RECORD,, pip-9.0.3.dist-info/WHEEL,sha256=gduuPyBvFJQSQ0zdyxF7k0zynDXbIbvg5ZBHoXum5uk,110 pip-9.0.3.dist-info/entry_points.txt,sha256=ka64YTzlkYMlaqzdHt9zPqn1h_HRJuoX2B-hYNNtlMo,68 pip-9.0.3.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 ../../../bin/pip,sha256=424S_cveYHLtcsS6fkPof29Nde-cw0-EWzxy5dbYsE4,206 ../../../bin/pip2,sha256=424S_cveYHLtcsS6fkPof29Nde-cw0-EWzxy5dbYsE4,206 ../../../bin/pip2.7,sha256=424S_cveYHLtcsS6fkPof29Nde-cw0-EWzxy5dbYsE4,206 pip-9.0.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 pip/_vendor/chardet/version.pyc,, pip/_vendor/requests/compat.pyc,, pip/_vendor/requests/certs.pyc,, pip/_vendor/requests/adapters.pyc,, pip/_vendor/progress/spinner.pyc,, pip/_vendor/html5lib/_tokenizer.pyc,, pip/__init__.pyc,, pip/_vendor/chardet/euckrprober.pyc,, pip/_vendor/cachecontrol/cache.pyc,, pip/_vendor/distlib/_backport/__init__.pyc,, pip/vcs/bazaar.pyc,, pip/_vendor/distlib/metadata.pyc,, pip/compat/__init__.pyc,, pip/_vendor/webencodings/tests.pyc,, pip/_vendor/html5lib/treebuilders/__init__.pyc,, pip/req/req_install.pyc,, pip/_vendor/html5lib/_trie/datrie.pyc,, pip/_vendor/distlib/util.pyc,, pip/_vendor/chardet/euctwprober.pyc,, pip/_vendor/urllib3/contrib/_securetransport/bindings.pyc,, pip/_vendor/html5lib/html5parser.pyc,, pip/_vendor/html5lib/filters/lint.pyc,, pip/pep425tags.pyc,, pip/_vendor/packaging/__init__.pyc,, pip/_vendor/lockfile/symlinklockfile.pyc,, pip/_vendor/packaging/utils.pyc,, pip/_vendor/html5lib/treewalkers/etree.pyc,, pip/_vendor/html5lib/filters/whitespace.pyc,, pip/compat/dictconfig.pyc,, pip/_vendor/html5lib/treebuilders/etree_lxml.pyc,, pip/_vendor/idna/codec.pyc,, pip/_vendor/html5lib/treeadapters/sax.pyc,, pip/_vendor/urllib3/contrib/socks.pyc,, pip/_vendor/requests/auth.pyc,, pip/commands/hash.pyc,, pip/_vendor/packaging/__about__.pyc,, pip/_vendor/progress/__init__.pyc,, pip/_vendor/cachecontrol/_cmd.pyc,, pip/_vendor/chardet/__init__.pyc,, pip/_vendor/webencodings/__init__.pyc,, pip/_vendor/urllib3/util/url.pyc,, pip/commands/list.pyc,, pip/_vendor/urllib3/exceptions.pyc,, pip/_vendor/distlib/scripts.pyc,, pip/_vendor/chardet/langhebrewmodel.pyc,, pip/_vendor/html5lib/filters/sanitizer.pyc,, pip/_vendor/urllib3/contrib/_securetransport/__init__.pyc,, pip/utils/packaging.pyc,, pip/vcs/git.pyc,, pip/cmdoptions.pyc,, pip/_vendor/lockfile/linklockfile.pyc,, pip/_vendor/certifi/__main__.pyc,, pip/_vendor/chardet/sbcharsetprober.pyc,, pip/commands/check.pyc,, pip/_vendor/urllib3/filepost.pyc,, pip/_vendor/html5lib/_trie/_base.pyc,, pip/_vendor/chardet/big5freq.pyc,, pip/_vendor/html5lib/filters/base.pyc,, pip/_vendor/certifi/core.pyc,, pip/req/req_set.pyc,, pip/req/__init__.pyc,, pip/_vendor/colorama/win32.pyc,, pip/_vendor/distlib/resources.pyc,, pip/_vendor/chardet/mbcssm.pyc,, pip/utils/__init__.pyc,, pip/_vendor/lockfile/__init__.pyc,, pip/_vendor/chardet/langgreekmodel.pyc,, pip/_vendor/progress/helpers.pyc,, pip/_vendor/ipaddress.pyc,, pip/operations/__init__.pyc,, pip/_vendor/pyparsing.pyc,, pip/_vendor/chardet/hebrewprober.pyc,, pip/_vendor/html5lib/__init__.pyc,, pip/_vendor/urllib3/response.pyc,, pip/_vendor/cachecontrol/serialize.pyc,, pip/_vendor/urllib3/contrib/securetransport.pyc,, pip/_vendor/distlib/_backport/misc.pyc,, pip/_vendor/chardet/universaldetector.pyc,, pip/_vendor/chardet/jpcntx.pyc,, pip/_vendor/chardet/enums.pyc,, pip/_vendor/urllib3/__init__.pyc,, pip/_vendor/cachecontrol/controller.pyc,, pip/utils/deprecation.pyc,, pip/_vendor/chardet/escprober.pyc,, pip/commands/show.pyc,, pip/_vendor/urllib3/packages/six.pyc,, pip/_vendor/html5lib/_utils.pyc,, pip/_vendor/html5lib/filters/alphabeticalattributes.pyc,, pip/_vendor/chardet/langthaimodel.pyc,, pip/_vendor/chardet/latin1prober.pyc,, pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.pyc,, pip/_vendor/html5lib/treeadapters/genshi.pyc,, pip/commands/help.pyc,, pip/_vendor/idna/__init__.pyc,, pip/_vendor/requests/utils.pyc,, pip/_vendor/urllib3/util/__init__.pyc,, pip/_vendor/colorama/__init__.pyc,, pip/commands/completion.pyc,, pip/_vendor/packaging/_compat.pyc,, pip/_vendor/distlib/version.pyc,, pip/utils/ui.pyc,, pip/commands/uninstall.pyc,, pip/_vendor/idna/uts46data.pyc,, pip/_vendor/distlib/index.pyc,, pip/_vendor/cachecontrol/heuristics.pyc,, pip/_vendor/requests/sessions.pyc,, pip/_vendor/html5lib/treewalkers/__init__.pyc,, pip/utils/glibc.pyc,, pip/commands/freeze.pyc,, pip/utils/hashes.pyc,, pip/_vendor/distlib/_backport/tarfile.pyc,, pip/_vendor/idna/package_data.pyc,, pip/_vendor/html5lib/treewalkers/etree_lxml.pyc,, pip/_vendor/html5lib/treebuilders/dom.pyc,, pip/_vendor/html5lib/filters/__init__.pyc,, pip/baseparser.pyc,, pip/_vendor/urllib3/util/connection.pyc,, pip/_vendor/urllib3/util/request.pyc,, pip/commands/__init__.pyc,, pip/_vendor/chardet/euctwfreq.pyc,, pip/_vendor/chardet/cli/chardetect.pyc,, pip/status_codes.pyc,, pip/_vendor/distlib/__init__.pyc,, pip/_vendor/cachecontrol/caches/__init__.pyc,, pip/_vendor/urllib3/fields.pyc,, pip/_vendor/pkg_resources/__init__.pyc,, pip/operations/freeze.pyc,, pip/commands/search.pyc,, pip/_vendor/html5lib/_ihatexml.pyc,, pip/_vendor/urllib3/_collections.pyc,, pip/_vendor/urllib3/contrib/pyopenssl.pyc,, pip/_vendor/chardet/cp949prober.pyc,, pip/_vendor/requests/structures.pyc,, pip/_vendor/packaging/version.pyc,, pip/_vendor/urllib3/util/wait.pyc,, pip/_vendor/cachecontrol/adapter.pyc,, pip/vcs/__init__.pyc,, pip/vcs/mercurial.pyc,, pip/req/req_file.pyc,, pip/models/__init__.pyc,, pip/_vendor/packaging/specifiers.pyc,, pip/_vendor/html5lib/treewalkers/genshi.pyc,, pip/_vendor/urllib3/connectionpool.pyc,, pip/_vendor/html5lib/treebuilders/base.pyc,, pip/_vendor/distlib/compat.pyc,, pip/models/index.pyc,, pip/_vendor/lockfile/mkdirlockfile.pyc,, pip/_vendor/urllib3/util/retry.pyc,, pip/_vendor/distlib/wheel.pyc,, pip/_vendor/requests/_internal_utils.pyc,, pip/_vendor/chardet/gb2312prober.pyc,, pip/utils/build.pyc,, pip/_vendor/requests/help.pyc,, pip/_vendor/requests/status_codes.pyc,, pip/_vendor/requests/exceptions.pyc,, pip/_vendor/distlib/markers.pyc,, pip/_vendor/distlib/database.pyc,, pip/index.pyc,, pip/_vendor/urllib3/poolmanager.pyc,, pip/_vendor/appdirs.pyc,, pip/_vendor/chardet/sjisprober.pyc,, pip/utils/logging.pyc,, pip/_vendor/chardet/langcyrillicmodel.pyc,, pip/_vendor/urllib3/contrib/_securetransport/low_level.pyc,, pip/_vendor/chardet/charsetgroupprober.pyc,, pip/_vendor/packaging/requirements.pyc,, pip/utils/outdated.pyc,, pip/_vendor/requests/api.pyc,, pip/_vendor/html5lib/treebuilders/etree.pyc,, pip/_vendor/cachecontrol/caches/file_cache.pyc,, pip/_vendor/distlib/_backport/shutil.pyc,, pip/_vendor/idna/core.pyc,, pip/utils/encoding.pyc,, pip/__main__.pyc,, pip/_vendor/cachecontrol/compat.pyc,, pip/download.pyc,, pip/_vendor/chardet/charsetprober.pyc,, pip/_vendor/urllib3/packages/__init__.pyc,, pip/_vendor/requests/models.pyc,, pip/_vendor/lockfile/sqlitelockfile.pyc,, pip/_vendor/progress/counter.pyc,, pip/commands/install.pyc,, pip/_vendor/urllib3/util/response.pyc,, pip/_vendor/chardet/cli/__init__.pyc,, pip/utils/filesystem.pyc,, pip/_vendor/urllib3/util/selectors.pyc,, pip/_vendor/six.pyc,, pip/_vendor/colorama/initialise.pyc,, pip/_vendor/requests/__version__.pyc,, pip/_vendor/urllib3/packages/backports/makefile.pyc,, pip/_vendor/chardet/utf8prober.pyc,, pip/_vendor/retrying.pyc,, pip/_vendor/cachecontrol/wrapper.pyc,, pip/_vendor/chardet/big5prober.pyc,, pip/_vendor/urllib3/connection.pyc,, pip/_vendor/requests/hooks.pyc,, pip/_vendor/idna/idnadata.pyc,, pip/_vendor/packaging/_structures.pyc,, pip/_vendor/chardet/langbulgarianmodel.pyc,, pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.pyc,, pip/_vendor/requests/packages.pyc,, pip/locations.pyc,, pip/_vendor/idna/intranges.pyc,, pip/_vendor/html5lib/_inputstream.pyc,, pip/utils/setuptools_build.pyc,, pip/vcs/subversion.pyc,, pip/exceptions.pyc,, pip/_vendor/lockfile/pidlockfile.pyc,, pip/basecommand.pyc,, pip/_vendor/chardet/sbcsgroupprober.pyc,, pip/_vendor/html5lib/_trie/py.pyc,, pip/_vendor/distlib/locators.pyc,, pip/_vendor/re-vendor.pyc,, pip/_vendor/html5lib/treewalkers/dom.pyc,, pip/commands/download.pyc,, pip/_vendor/webencodings/labels.pyc,, pip/_vendor/distlib/_backport/sysconfig.pyc,, pip/_vendor/webencodings/x_user_defined.pyc,, pip/_vendor/chardet/langturkishmodel.pyc,, pip/req/req_uninstall.pyc,, pip/_vendor/urllib3/util/timeout.pyc,, pip/_vendor/urllib3/request.pyc,, pip/_vendor/chardet/mbcharsetprober.pyc,, pip/_vendor/html5lib/serializer.pyc,, pip/_vendor/chardet/eucjpprober.pyc,, pip/commands/wheel.pyc,, pip/_vendor/idna/compat.pyc,, pip/_vendor/colorama/ansitowin32.pyc,, pip/_vendor/cachecontrol/filewrapper.pyc,, pip/_vendor/chardet/euckrfreq.pyc,, pip/_vendor/html5lib/_trie/__init__.pyc,, pip/_vendor/urllib3/contrib/ntlmpool.pyc,, pip/_vendor/chardet/langhungarianmodel.pyc,, pip/_vendor/requests/cookies.pyc,, pip/_vendor/webencodings/mklabels.pyc,, pip/_vendor/certifi/__init__.pyc,, pip/_vendor/html5lib/treewalkers/base.pyc,, pip/_vendor/distlib/manifest.pyc,, pip/_vendor/chardet/codingstatemachine.pyc,, pip/_vendor/html5lib/treeadapters/__init__.pyc,, pip/_vendor/cachecontrol/caches/redis_cache.pyc,, pip/_vendor/html5lib/filters/inject_meta_charset.pyc,, pip/_vendor/cachecontrol/__init__.pyc,, pip/_vendor/urllib3/contrib/appengine.pyc,, pip/_vendor/chardet/chardistribution.pyc,, pip/_vendor/urllib3/contrib/__init__.pyc,, pip/_vendor/__init__.pyc,, pip/_vendor/html5lib/constants.pyc,, pip/_vendor/chardet/gb2312freq.pyc,, pip/_vendor/urllib3/packages/backports/__init__.pyc,, pip/_vendor/colorama/ansi.pyc,, pip/_vendor/packaging/markers.pyc,, pip/_vendor/urllib3/packages/ordered_dict.pyc,, pip/_vendor/chardet/mbcsgroupprober.pyc,, pip/_vendor/distro.pyc,, pip/_vendor/chardet/escsm.pyc,, pip/_vendor/progress/bar.pyc,, pip/wheel.pyc,, pip/_vendor/chardet/compat.pyc,, pip/_vendor/requests/__init__.pyc,, pip/_vendor/urllib3/util/ssl_.pyc,, pip/_vendor/html5lib/filters/optionaltags.pyc,, pip/utils/appdirs.pyc,, pip/_vendor/colorama/winterm.pyc,, pip/_vendor/chardet/jisfreq.pyc,, pip/operations/check.pyc,, PK@N#]/site-packages/pip-9.0.3.dist-info/top_level.txtnu[pip PK@N#]b%DD2site-packages/pip-9.0.3.dist-info/entry_points.txtnu[[console_scripts] pip = pip:main pip2 = pip:main pip2.7 = pip:main PK@N#]nn'site-packages/pip-9.0.3.dist-info/WHEELnu[Wheel-Version: 1.0 Generator: bdist_wheel (0.31.1) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any PK@N#]#+site-packages/pip-9.0.3.dist-info/INSTALLERnu[rpm PK@N#]ץtD0e0e"site-packages/cssselect/parser.pyonu[ ǁaWc@sdZddlZddlZddlZejddkrLeZeZn e Ze ZdZ de fdYZ de efd YZd efd YZd efd YZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZejdZejdZejd Zd!Zd"Z d#Z!e"d$Z#d%Z$d&Z%d'Z&d(e'fd)YZ(d*e(fd+YZ)d,dBd-YZ*d.Z+e+d/Z,e+d0Z-e+d1Z.e+d2Z/ie+d3d46e+d5d66Z0ejd7j1Z2eje*j3ej4j1Z5ejd8j1Z6e7ed9rej8d:d;Z9n d<Z9d=Z:d>Z;d?Z<d@efdAYZ=dS(Cs cssselect.parser ================ Tokenizer, parser and parsed objects for CSS selectors. :copyright: (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. :license: BSD, see LICENSE for more details. iNiicCs|jdjjdS(s(Lower-case, but only in the ASCII range.tutf8(tencodetlowertdecode(tstring((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt ascii_lowerst SelectorErrorcBseZdZRS(sCommon parent for :class:`SelectorSyntaxError` and :class:`ExpressionError`. You can just use ``except SelectorError:`` when calling :meth:`~GenericTranslator.css_to_xpath` and handle both exceptions types. (t__name__t __module__t__doc__(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR!stSelectorSyntaxErrorcBseZdZRS(s3Parsing a selector that does not match the grammar.(RRR (((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR *stSelectorcBs,eZdZddZdZdZRS(s" Represents a parsed selector. :meth:`~GenericTranslator.selector_to_xpath` accepts this object, but ignores :attr:`pseudo_element`. It is the user’s responsibility to account for pseudo-elements and reject selectors with unknown or unsupported pseudo-elements. cCsA||_|dk r4t|t r4t|}n||_dS(N(t parsed_treetNonet isinstancetFunctionalPseudoElementRtpseudo_element(tselfttreeR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt__init__:s   cCs]t|jtr$t|j}n|jr=d|j}nd}d|jj|j|fS(Ns::%sts%s[%r%s](RRRtreprt __class__RR (RR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt__repr__Us cCs;|jj\}}}|jr.|d7}n|||fS(sReturn the specificity_ of this selector as a tuple of 3 integers. .. _specificity: http://www.w3.org/TR/selectors/#specificity i(R t specificityR(Rtatbtc((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR_s  N(RRR R RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR 0s   tClasscBs)eZdZdZdZdZRS(s( Represents selector.class_name cCs||_||_dS(N(tselectort class_name(RRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRos cCsd|jj|j|jfS(Ns %s[%r.%s](RRRR(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRsscCs/|jj\}}}|d7}|||fS(Ni(RR(RRRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRws (RRR RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRks  RcBs2eZdZdZdZdZdZRS(sx Represents selector::name(arguments) .. attribute:: name The name (identifier) of the pseudo-element, as a string. .. attribute:: arguments The arguments of the pseudo-element, as a list of tokens. **Note:** tokens are not part of the public API, and may change between cssselect versions. Use at your own risks. cCst||_||_dS(N(Rtnamet arguments(RRR ((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRscCs3d|jj|jg|jD]}|j^qfS(Ns %s[::%s(%r)](RRRR tvalue(Rttoken((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRscCsg|jD]}|j^q S(N(R ttype(RR"((s4/usr/lib/python2.7/site-packages/cssselect/parser.pytargument_typesscCs/|jj\}}}|d7}|||fS(Ni(RR(RRRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs (RRR RRR$R(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR}s    tFunctioncBs2eZdZdZdZdZdZRS(s( Represents selector:name(expr) cCs%||_t||_||_dS(N(RRRR (RRRR ((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs cCs9d|jj|j|jg|jD]}|j^q"fS(Ns %s[%r:%s(%r)](RRRRR R!(RR"((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRscCsg|jD]}|j^q S(N(R R#(RR"((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR$scCs/|jj\}}}|d7}|||fS(Ni(RR(RRRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs (RRR RRR$R(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR%s    tPseudocBs)eZdZdZdZdZRS(s# Represents selector:ident cCs||_t||_dS(N(RRtident(RRR'((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs cCsd|jj|j|jfS(Ns %s[%r:%s](RRRR'(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRscCs/|jj\}}}|d7}|||fS(Ni(RR(RRRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs (RRR RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR&s  tNegationcBs)eZdZdZdZdZRS(s. Represents selector:not(subselector) cCs||_||_dS(N(Rt subselector(RRR)((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs cCsd|jj|j|jfS(Ns%s[%r:not(%r)](RRRR)(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRscCsI|jj\}}}|jj\}}}||||||fS(N(RRR)(Rta1tb1tc1ta2tb2tc2((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs(RRR RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR(s  tAttribcBs)eZdZdZdZdZRS(s> Represents selector[namespace|attrib operator value] cCs1||_||_||_||_||_dS(N(Rt namespacetattribtoperatorR!(RRR1R2R3R!((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs     cCs~|jr"d|j|jf}n |j}|jdkrTd|jj|j|fSd|jj|j||j|jfSdS(Ns%s|%stexistss %s[%r[%s]]s%s[%r[%s %s %r]](R1R2R3RRRR!(RR2((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs  cCs/|jj\}}}|d7}|||fS(Ni(RR(RRRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs (RRR RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR0s  tElementcBs/eZdZdddZdZdZRS(sU Represents namespace|element `None` is for the universal selector '*' cCs||_||_dS(N(R1telement(RR1R6((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs cCsB|jp d}|jr.d|j|f}nd|jj|fS(Nt*s%s|%ss%s[%s](R6R1RR(RR6((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs cCs|jr dSdSdS(Nii(iii(iii(R6(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR s N(RRR R RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR5s tHashcBs)eZdZdZdZdZRS(s Represents selector#id cCs||_||_dS(N(Rtid(RRR9((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs cCsd|jj|j|jfS(Ns %s[%r#%s](RRRR9(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRscCs/|jj\}}}|d7}|||fS(Ni(RR(RRRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs (RRR RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR8s  tCombinedSelectorcBs#eZdZdZdZRS(cCs||_||_||_dS(N(Rt combinatorR)(RRR;R)((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR$s  cCsA|jdkrd}n |j}d|jj|j||jfS(Nt s s %s[%r %s %r](R;RRRR)(Rtcomb((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR*s   cCsI|jj\}}}|jj\}}}||||||fS(N(RRR)(RR*R+R,R-R.R/((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR2s(RRRRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR:#s  s%^[ \t\r\n\f]*([a-zA-Z]+)[ \t\r\n\f]*$s6^[ \t\r\n\f]*([a-zA-Z]*)#([a-zA-Z0-9_-]+)[ \t\r\n\f]*$s?^[ \t\r\n\f]*([a-zA-Z]*)\.([a-zA-Z][a-zA-Z0-9_-]*)[ \t\r\n\f]*$cCstj|}|r4ttd|jdgStj|}|dk rtttd|jdpmd|jdgStj|}|dk rtt td|jdpd|jdgSt t |}||_ t t|S(sParse a CSS *group of selectors*. If you don't care about pseudo-elements or selector specificity, you can skip this and use :meth:`~GenericTranslator.css_to_xpath`. :param css: A *group of selectors* as an Unicode string. :raises: :class:`SelectorSyntaxError` on invalid selectors. :returns: A list of parsed :class:`Selector` objects, one for each selector in the comma-separated group. R6iiN(t_el_retmatchR R5tgroupt_id_reR R8t _class_reRt TokenStreamttokenizetsourcetlisttparse_selector_group(tcssR?tstream((s4/usr/lib/python2.7/site-packages/cssselect/parser.pytparseEs ! ! ccsP|jx?tt|V|jdkrG|j|jq Pq WdS(NtDELIMt,(RKRL(tskip_whitespaceR tparse_selectortpeektnext(RI((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRGos   cCst|\}}x|j|j}|d d fkrAPn|rZtd|n|jdddr|jj}|jnd}t|\}}t|||}qW||fS( NtEOFRKRLs4Got pseudo-element ::%s not at the end of a selectort+t>t~R<(RQN(RKRL( tparse_simple_selectorRMROR R tis_delimRPR!R:(RItresultRROR;t next_selector((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRNys"    c Cs|jt|j}|j}|jdks@|dkr|jdkra|jj}n|jd}|jdkr|j|j}q|}d}n d}}t ||}d}x|j}|jdks|j ddd d s|r|dkrPn|r/t d |n|jd krYt ||jj}q|d kr|jt ||j}q|d!kr|jt||}q|d"krN|j|jd#kr'|j|j}|jd$kr|jt|t|}qqn|j}|jd%krWt|}qn|jd&kr~t||}qn|j|j|jdkr3|rt dnt|dt\} } |j} | rt d| | jfn| d'kr!t d| fnt|| }qat||t|}qt d|fqWt|j|krt d|jfn||fS((NtIDENTRKR7t|tSRQRLRRRSRTt)s4Got pseudo-element ::%s not at the end of a selectortHASHt.t[t:t(s first-lines first-lettertbeforetaftertnotsGot nested :not()tinside_negations+Got pseudo-element ::%s inside :not() at %ssExpected ')', got %ssExpected selector, got %s(RKR7(RKRZ(R[RQ(RKR\(RKR^(RKR_(RKR`(RKR`(RKRa(s first-lines first-letterRbRc(RKRa(RKR\(RMtlentusedROR#RPR!R tnext_ident_or_starR5RVR R8Rt next_identt parse_attribRtparse_argumentsRt_unicodeR&RUtTruetposR(R%( RIRetselector_startROR1R6RWRR'targumenttargument_pseudo_elementRP((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRUs       '                  cCs{g}xn|j|j}|jd ks@|d d gkrP|j|q |d kr`|Std|fq WdS( NRYtSTRINGtNUMBERRKRRt-R\sExpected an argument, got %s(RYRrRs(RKRR(RKRt(RKR\(RMRPR#tappendR (RIR RP((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRks   cCs|j|j}|dkrP|jdkrPtd|jfn|jdkr|j|jdkrd}|jd}q|}|j}d}n d}}|dkru|j|j}|dkrt|||ddS|dkrd}qu|jdd d d dd r_|jdkr_|j d}|jqutd |fn|j|j}|j dkrtd|fn|j|j}|dkrtd|fnt|||||j S(NRKRZsExpected '|', got %st=s|=t]R4t^t$R7RTt!sOperator expected, got %sRYRrs Expected string or ident, got %ssExpected ']', got %s(RKRZ(RKRZ(RKRv(RKRw(RKRv(RKRv(RYRr(RKRw( RMRhR ROR RPRiR0RVR!R#(RRIR2R1topRPR!((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRjsN                     cCsx,|D]$}|jdkrtdqqWdjd|Dj}|dkr^dS|dkrndS|d kr~dSd |krd t|fS|jd d\}}|sd}n7|d ks|d krt|d }n t|}|sd }n t|}||fS(sv Parses the arguments for :nth-child() and friends. :raises: A list of tokens :returns: :``(a, b)`` Rrs$String tokens not allowed in series.Rcss|]}|jVqdS(N(R!(t.0R"((s4/usr/lib/python2.7/site-packages/cssselect/parser.pys +stoddiitevenitnRtRRt1(ii(ii(ii(R#t ValueErrortjointstriptinttsplit(ttokensR"tsRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt parse_series s,         tTokencBsMeZdZdZdZeejdZeejdZ RS(cCs%tj|||f}||_|S(N(ttuplet__new__Rn(tclsttype_R!Rntobj((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRFs cCsd|j|j|jfS(Ns<%s '%s' at %i>(R#R!Rn(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRKscGs|jdko|j|kS(NRK(R#R!(Rtvalues((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRVNsii( RRRRRVtpropertyR3t itemgetterR#R!(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyREs    tEOFTokencBseZdZdZRS(cCstj|dd|S(NRQ(RRR (RRn((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRVscCsd|j|jfS(Ns <%s at %i>(R#Rn(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRYs(RRRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRUs t TokenMacroscBsHeZdZedZdeZdZdeefZdeefZRS(s&\\([0-9a-f]{1,6})(?:\r\n|[ \n\r\t\f])?s|\\[^\n\r\f0-9a-f]s\\(?:\n|\r\n|\r|\f)|s [^\0-\177]s[_a-z0-9-]|%s|%ss [_a-z]|%s|%s(RRtunicode_escapetescapet string_escapetnonasciitnmchartnmstart(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR`s   cCs tj|tttjjS(N(tretcompiletvarsRt IGNORECASER?(tpattern((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt_compilehss [ \t\r\n\f]+s[+-]?(?:[0-9]*\.[0-9]+|[0-9]+)s#(?:%(nmchar)s)+s -?(?:%(nmstart)s)(?:%(nmchar)s)*s!([^\n\r\f\\']|%(string_escape)s)*t's!([^\n\r\f\\"]|%(string_escape)s)*t"s\\(.)s\\(?:\n|\r\n|\r|\f)t methodcallerR@icCs |jdS(Ni(R@(R?((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt_replace_simple}scCs:t|jdd}|tjkr0d}nt|S(Niii(RR@tsyst maxunicodet_unichr(R?t codepoint((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt_replace_unicodes cCs"tt|}tt|}|S(N(t_sub_unicode_escapeRt_sub_simple_escapeR(R!((s4/usr/lib/python2.7/site-packages/cssselect/parser.pytunescape_identsccsd}t|}x||krt|d|}|r\tdd|V|j}qnt|d|}|rtttt|j }td||V|j}qnt |d|}|rtttt|j d}td||V|j}qn||}|t krt ||d|d}|j}||krmt d|n|||krt d |nttttt d |j }td ||V|d}qnt|d|}|r|j }td ||V|j}qn|d }|||!dkrs|jd|}|dkrc|}q|d 7}qntd|||V|d7}qWt|VdS(NiRnR[R<RYiR]sUnclosed string at %ssInvalid string at %sRRrRsis/*s*/iRK(Rft_match_whitespaceRtendt _match_identRRRRR@t _match_hasht_match_string_by_quoteR t_sub_newline_escapet _match_numbertfindR(RRntlen_sR?R!tquotetend_postpos2((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRDsh               RCcBsAeZddZdZdZdZdZdZRS(cCsmg|_t||_||_d|_t|_y|jj|_ Wn t k rh|jj |_ nXdS(N( RgtiterRRER tpeekedtFalset_peekingRPt next_tokentAttributeErrort__next__(RRRE((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs     cCsP|jr,t|_|jj|j|jS|j}|jj||SdS(N(RRRgRuRR(RRP((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRPs   cCs+|js$|j|_t|_n|jS(N(RRRRm(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyROs  cCs8|j}|jdkr1td|fn|jS(NRYsExpected ident, got %s(RPR#R R!(RRP((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRis cCsI|j}|jdkr"|jS|dkr2dStd|fdS(NRYRKR7sExpected ident or '*', got %s(RKR7(RPR#R!R R (RRP((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRhs  cCs,|j}|jdkr(|jndS(NR[(ROR#RP(RRO((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRMs N( RRR RRPRORiRhRM(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRCs    ((>R RRR3t version_infotunicodeRltunichrRtstrtchrRt ExceptionRt SyntaxErrorR tobjectR RRR%R&R(R0R5R8R:RR>RARBRJRGRNRRURkRjRRRRRRRRRRRtsubRRtIRRthasattrRRRRRDRC(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt sj      ;#  *  S  - %           APK@N#]q\˶]]!site-packages/cssselect/xpath.pyonu[ ǁaWc@s dZddlZddlZddlmZmZmZejddkr\eZ e Z n e Z e Z e dZdeefdYZd efd YZejd jZejd jZejd jZdefdYZdefdYZdS(s cssselect.xpath =============== Translation of parsed CSS selectors to XPath expressions. :copyright: (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. :license: BSD, see LICENSE for more details. iN(tparset parse_seriest SelectorErroriicCs+|jddjd}t|||S(Ntasciitreplace(tencodetdecodetgetattr(tobjtnametdefault((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt_unicode_safe_getattrstExpressionErrorcBseZdZRS(s3Unknown or unsupported selector (eg. pseudo-class).(t__name__t __module__t__doc__(((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyR #st XPathExprcBsSeZdddedZdZdZdZdZdZdZ RS( tt*cCs||_||_||_dS(N(tpathtelementt condition(tselfRRRt star_prefix((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt__init__+s  cCs=t|jt|j}|jr9|d|j7}n|S(Ns[%s](t_unicodeRRR(RR((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt__str__0s cCsd|jj|fS(Ns%s[%s](t __class__R (R((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt__repr__6scCs/|jr"d|j|f|_n ||_|S(Ns %s and (%s)(R(RR((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt add_condition9s  cCs=|jdkrdS|jdtj|jd|_dS(NRs name() = %s(RRtGenericTranslatort xpath_literal(R((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt add_name_test@s cCs|jd7_dS(se Append '*/' to the path to keep the context constrained to a single parent. s*/N(R(R((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytadd_star_prefixHscCsTt||}|jdkr/||j7}n||_|j|_|j|_|S(Ns*/(RRRR(RtcombinertotherR((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytjoinOs   ( R RtFalseRRRRR R!R$(((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyR)s     s('+)s^[a-zA-Z_][a-zA-Z0-9_.-]*$s^[^ \t\r\n\f]+$RcBsEeZdZidd6dd6dd6dd6Zid d 6d d 6d d 6dd6dd6dd6dd6dd6ZdZdZeZeZ eZ e Z ddZ dedZdZedZdZd Zd!Zd"Zd#Zd$Zd%Zd&Zd'Zd(Zd)Zd*Zd+Zeed,Z d-Z!d.Z"d/Z#d0Z$d1Z%d2Z&d3Z'd4Z(d5Z)d6Z*d7Z+d8Z,d9Z-d:Z.e.Z/e.Z0e.Z1e.Z2e.Z3e.Z4e.Z5e.Z6e.Z7d;Z8d<Z9d=Z:d>Z;d?Z<d@Z=dAZ>dBZ?RS(Cs Translator for "generic" XML documents. Everything is case-sensitive, no assumption is made on the meaning of element names and attribute names. t descendantt tchildt>tdirect_adjacentt+tindirect_adjacentt~texiststequalst=tincludess~=t dashmatchs|=t prefixmatchs^=t suffixmatchs$=tsubstringmatchs*=t differents!=tidsxml:langsdescendant-or-self::cs&djfdt|DS(sTranslate a *group of selectors* to XPath. Pseudo-elements are not supported here since XPath only knows about "real" elements. :param css: A *group of selectors* as an Unicode string. :param prefix: This string is prepended to the XPath expression for each selector. The default makes selectors scoped to the context node’s subtree. :raises: :class:`SelectorSyntaxError` on invalid selectors, :class:`ExpressionError` on unknown/unsupported selectors, including pseudo-elements. :returns: The equivalent XPath 1.0 expression as an Unicode string. s | c3s'|]}j|dtVqdS(ttranslate_pseudo_elementsN(tselector_to_xpathtTrue(t.0tselector(tprefixR(s3/usr/lib/python2.7/site-packages/cssselect/xpath.pys s(R$R(RtcssR=((R=Rs3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt css_to_xpathscCsxt|dd}|s.td|fn|j|}|rd|jrd|j||j}n|pmdt|S(s4Translate a parsed selector to XPath. :param selector: A parsed :class:`Selector` object. :param prefix: This string is prepended to the resulting XPath expression. The default makes selectors scoped to the context node’s subtree. :param translate_pseudo_elements: Unless this is set to ``True`` (as :meth:`css_to_xpath` does), the :attr:`~Selector.pseudo_element` attribute of the selector is ignored. It is the caller's responsibility to reject selectors with pseudo-elements, or to account for them somehow. :raises: :class:`ExpressionError` on unknown/unsupported selectors. :returns: The equivalent XPath 1.0 expression as an Unicode string. t parsed_trees"Expected a parsed selector, got %rRN(RtNonet TypeErrortxpathtpseudo_elementtxpath_pseudo_elementR(RR<R=R8ttreeRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyR9scCstddS(sTranslate a pseudo-element. Defaults to not supporting pseudo-elements at all, but can be overridden by sub-classes. s"Pseudo-elements are not supported.N(R (RRCRD((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyREscCst|}d|kr%d|}nad|kr>d|}nHddjgt|D](}|rTd|krrdpud|^qT}|S(Nt's'%s't"s"%s"s concat(%s)t,(RR$tsplit_at_single_quotes(tstpart((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRs      <cCsTt|j}t|d|jd}|dkrJtd|n||S(s%Translate any parsed selector object.sxpath_%ss%s is not supported.N(ttypeR RtlowerRAR (Rtparsed_selectort type_nametmethod((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRCs  cCsH|j|j}t|d|}||j|j|j|jS(sTranslate a combined selector.sxpath_%s_combinator(tcombinator_mappingt combinatorRRCR<t subselector(RtcombinedRSRQ((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_combinedselectorscCs\|j|j}|j|j}|j|jrK|jd|jS|jdSdS(Nsnot(%s)t0(RCR<RTR RR(RtnegationRCt sub_xpath((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_negation s   cCs`d|jjdd}t||d}|sGtd|jn||j|j|S(s$Translate a functional pseudo-class.sxpath_%s_functiont-t_s!The pseudo-class :%s() is unknownN(R RR RAR RCR<(RtfunctionRQ((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_functions cCs]d|jjdd}t||d}|sGtd|jn||j|jS(sTranslate a pseudo-class.sxpath_%s_pseudoR[R\sThe pseudo-class :%s is unknownN(tidentRR RAR RCR<(RtpseudoRQ((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt xpath_pseudos cCs|j|j}t|d|}|jr>|jj}n |j}t|}|jrd|j|f}|ot|j}n|rd|}nd|j|}|j r|j j}n |j }||j |j ||S(s Translate an attribute selector.sxpath_attrib_%ss%s:%st@sattribute::*[name() = %s]( tattribute_operator_mappingtoperatorRtlower_case_attribute_namestattribRNt is_safe_namet namespaceRtlower_case_attribute_valuestvalueRCR<(RR<RdRQR tsafeRfRj((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt xpath_attrib's        cCs(|j|j}|j|d|jS(sTranslate a class selector.s@class(RCR<txpath_attrib_includest class_name(Rtclass_selectorRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt xpath_class=scCs(|j|j}|j|d|jS(sTranslate an ID selector.s@id(RCR<txpath_attrib_equalsR7(Rt id_selectorRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt xpath_hashDscCs|j}|sd}t}n$t|}|jrB|j}n|jrvd|j|f}|opt|j}n|jd|}|s|jn|S(s'Translate a type or universal selector.Rs%s:%sR(RR:Rgtlower_case_element_namesRNRht xpathexpr_clsR (RR<RRkRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt xpath_elementIs      cCs|jd|S(s;right is a child, grand-child or further descendant of lefts/descendant-or-self::*/(R$(Rtlefttright((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_descendant_combinator`scCs|jd|S(s#right is an immediate child of leftt/(R$(RRwRx((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_child_combinatordscCs)|jd|}|j|jdS(s)right is a sibling immediately after lefts/following-sibling::sposition() = 1(R$R R(RRwRxRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt xpath_direct_adjacent_combinatorhs cCs|jd|S(s1right is a sibling after left, immediately or nots/following-sibling::(R$(RRwRx((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt"xpath_indirect_adjacent_combinatornsc Csbyt|j\}}Wn$tk r?td|jnX|rS|jn|j|dkr|r|d|}n|jd|S|r| }| }n|dkrt| }n d| }|dkrd||fg}ng}|dkr|jd|n&|dkr9|r9|jd |nd j |}|r^|j|n|S( NsInvalid series: '%r'is last() - %ssposition() = %ss+%sis(position() %s) mod %s = 0sposition() >= %ssposition() < (last() %s)s and ( Rt argumentst ValueErrorR R R!RtstrtappendR$( RRCR]tlastR tatbtb_negtexpr((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_nth_child_functionus8          cCs|j||dtS(NR(RR:(RRCR]((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_nth_last_child_functionscCs4|jdkrtdn|j||dtS(NRs"*:nth-of-type() is not implementedR (RR RR%(RRCR]((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_nth_of_type_functions  cCs:|jdkrtdn|j||dtdtS(NRs"*:nth-of-type() is not implementedRR (RR RR:R%(RRCR]((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_nth_last_of_type_functions  cCs^|jdgdgfkr4td|jn|jdj}|jd|j|S(NtSTRINGtIDENTs9Expected a single string or ident for :contains(), got %riscontains(., %s)(targument_typesR R~RjRR(RRCR]Rj((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_contains_functionscCs^|jdgdgfkr4td|jn|jdj}|jd|j|S(NRRs5Expected a single string or ident for :lang(), got %rislang(%s)(RR R~RjRR(RRCR]Rj((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_lang_functionscCs |jdS(Nsnot(parent::*)(R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_root_pseudoscCs!|j|j|jdS(Nsposition() = 1(R!R R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_first_child_pseudos  cCs!|j|j|jdS(Nsposition() = last()(R!R R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_last_child_pseudos  cCs5|jdkrtdn|j|jdS(NRs"*:first-of-type is not implementedsposition() = 1(RR R!R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_first_of_type_pseudos   cCs5|jdkrtdn|j|jdS(NRs!*:last-of-type is not implementedsposition() = last()(RR R!R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_last_of_type_pseudos   cCs!|j|j|jdS(Ns last() = 1(R R!R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_only_child_pseudos  cCs+|jdkrtdn|jdS(NRs!*:only-of-type is not implementeds last() = 1(RR R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_only_of_type_pseudos cCs |jdS(Nsnot(*) and not(string-length())(R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_empty_pseudoscCs |jdS(s:Common implementation for pseudo-classes that never match.RW(R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytpseudo_never_matchesscCs|j||S(N(R(RRCR Rj((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_attrib_existss cCs$|jd||j|f|S(Ns%s = %s(RR(RRCR Rj((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRqs cCsP|r,|jd|||j|fn |jd||j|f|S(Nsnot(%s) or %s != %ss%s != %s(RR(RRCR Rj((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_attrib_differents   cCsKt|r:|jd|||jd|dfn |jd|S(Ns:%s and contains(concat(' ', normalize-space(%s), ' '), %s)R'RW(tis_non_whitespaceRR(RRCR Rj((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRms  % c Cs:|jd|||j|||j|df|S(Ns'%s and (%s = %s or starts-with(%s, %s))R[(RR(RRCR Rj((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_attrib_dashmatchs  cCs=|r,|jd|||j|fn |jd|S(Ns%s and starts-with(%s, %s)RW(RR(RRCR Rj((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_attrib_prefixmatch#s   cCsM|r<|jd|||t|d|j|fn |jd|S(Ns/%s and substring(%s, string-length(%s)-%s) = %siRW(RtlenR(RRCR Rj((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_attrib_suffixmatch+s - cCs=|r,|jd|||j|fn |jd|S(Ns%s and contains(%s, %s)RW(RR(RRCR Rj((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_attrib_substringmatch5s   (@R RRRRRct id_attributetlang_attributeR%RtReRiRRuR?R9REt staticmethodRRCRVRZR^RaRlRpRsRvRyR{R|R}R:RRRRRRRRRRRRRRRtxpath_link_pseudotxpath_visited_pseudotxpath_hover_pseudotxpath_active_pseudotxpath_focus_pseudotxpath_target_pseudotxpath_enabled_pseudotxpath_disabled_pseudotxpath_checked_pseudoRRqRRmRRRR(((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRgs               (                 tHTMLTranslatorcBsMeZdZdZedZdZdZdZdZ dZ RS(s Translator for (X)HTML documents. Has a more useful implementation of some pseudo-classes based on HTML-specific element names and attribute names, as described in the `HTML5 specification`_. It assumes no-quirks mode. The API is the same as :class:`GenericTranslator`. .. _HTML5 specification: http://www.w3.org/TR/html5/links.html#selectors :param xhtml: If false (the default), element names and attribute names are case-insensitive. tlangcCs(||_|s$t|_t|_ndS(N(txhtmlR:RtRe(RR((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRRs  cCs |jdS(Ns(@selected and name(.) = 'option') or (@checked and (name(.) = 'input' or name(.) = 'command')and (@type = 'checkbox' or @type = 'radio'))(R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRYscCsq|jdgdgfkr4td|jn|jdj}|jd|j|j|jdfS(NRRs5Expected a single string or ident for :lang(), got %risancestor-or-self::*[@lang][1][starts-with(concat(translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-'), %s)]R[(RR R~RjRRRRN(RRCR]Rj((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRascCs |jdS(NsA@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area')(R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRoscCs |jdS(Ns ( @disabled and ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' or name(.) = 'command' or name(.) = 'fieldset' or name(.) = 'optgroup' or name(.) = 'option' ) ) or ( ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' ) and ancestor::fieldset[@disabled] ) (R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRvscCs |jdS(Ns' ( @href and ( name(.) = 'a' or name(.) = 'link' or name(.) = 'area' ) ) or ( ( name(.) = 'command' or name(.) = 'fieldset' or name(.) = 'optgroup' ) and not(@disabled) ) or ( ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' or name(.) = 'keygen' ) and not (@disabled or ancestor::fieldset[@disabled]) ) or ( name(.) = 'option' and not( @disabled or ancestor::optgroup[@disabled] ) ) (R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRs( R RRRR%RRRRRR(((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyR?s     (Rtsystretcssselect.parserRRRt version_infot basestringt _basestringtunicodeRRRAR t RuntimeErrorR tobjectRtcompiletsplitRJtmatchRgRRR(((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt s"    1PK@N#]{ɷee"site-packages/cssselect/parser.pycnu[ ǁaWc@sdZddlZddlZddlZejddkrLeZeZn e Ze ZdZ de fdYZ de efd YZd efd YZd efd YZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZdefdYZejdZejdZejd Zd!Zd"Z d#Z!e"d$Z#d%Z$d&Z%d'Z&d(e'fd)YZ(d*e(fd+YZ)d,dBd-YZ*d.Z+e+d/Z,e+d0Z-e+d1Z.e+d2Z/ie+d3d46e+d5d66Z0ejd7j1Z2eje*j3ej4j1Z5ejd8j1Z6e7ed9rej8d:d;Z9n d<Z9d=Z:d>Z;d?Z<d@efdAYZ=dS(Cs cssselect.parser ================ Tokenizer, parser and parsed objects for CSS selectors. :copyright: (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. :license: BSD, see LICENSE for more details. iNiicCs|jdjjdS(s(Lower-case, but only in the ASCII range.tutf8(tencodetlowertdecode(tstring((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt ascii_lowerst SelectorErrorcBseZdZRS(sCommon parent for :class:`SelectorSyntaxError` and :class:`ExpressionError`. You can just use ``except SelectorError:`` when calling :meth:`~GenericTranslator.css_to_xpath` and handle both exceptions types. (t__name__t __module__t__doc__(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR!stSelectorSyntaxErrorcBseZdZRS(s3Parsing a selector that does not match the grammar.(RRR (((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR *stSelectorcBs,eZdZddZdZdZRS(s" Represents a parsed selector. :meth:`~GenericTranslator.selector_to_xpath` accepts this object, but ignores :attr:`pseudo_element`. It is the user’s responsibility to account for pseudo-elements and reject selectors with unknown or unsupported pseudo-elements. cCsA||_|dk r4t|t r4t|}n||_dS(N(t parsed_treetNonet isinstancetFunctionalPseudoElementRtpseudo_element(tselfttreeR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt__init__:s   cCs]t|jtr$t|j}n|jr=d|j}nd}d|jj|j|fS(Ns::%sts%s[%r%s](RRRtreprt __class__RR (RR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt__repr__Us cCs;|jj\}}}|jr.|d7}n|||fS(sReturn the specificity_ of this selector as a tuple of 3 integers. .. _specificity: http://www.w3.org/TR/selectors/#specificity i(R t specificityR(Rtatbtc((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR_s  N(RRR R RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR 0s   tClasscBs)eZdZdZdZdZRS(s( Represents selector.class_name cCs||_||_dS(N(tselectort class_name(RRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRos cCsd|jj|j|jfS(Ns %s[%r.%s](RRRR(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRsscCs/|jj\}}}|d7}|||fS(Ni(RR(RRRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRws (RRR RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRks  RcBs2eZdZdZdZdZdZRS(sx Represents selector::name(arguments) .. attribute:: name The name (identifier) of the pseudo-element, as a string. .. attribute:: arguments The arguments of the pseudo-element, as a list of tokens. **Note:** tokens are not part of the public API, and may change between cssselect versions. Use at your own risks. cCst||_||_dS(N(Rtnamet arguments(RRR ((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRscCs3d|jj|jg|jD]}|j^qfS(Ns %s[::%s(%r)](RRRR tvalue(Rttoken((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRscCsg|jD]}|j^q S(N(R ttype(RR"((s4/usr/lib/python2.7/site-packages/cssselect/parser.pytargument_typesscCs/|jj\}}}|d7}|||fS(Ni(RR(RRRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs (RRR RRR$R(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR}s    tFunctioncBs2eZdZdZdZdZdZRS(s( Represents selector:name(expr) cCs%||_t||_||_dS(N(RRRR (RRRR ((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs cCs9d|jj|j|jg|jD]}|j^q"fS(Ns %s[%r:%s(%r)](RRRRR R!(RR"((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRscCsg|jD]}|j^q S(N(R R#(RR"((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR$scCs/|jj\}}}|d7}|||fS(Ni(RR(RRRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs (RRR RRR$R(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR%s    tPseudocBs)eZdZdZdZdZRS(s# Represents selector:ident cCs||_t||_dS(N(RRtident(RRR'((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs cCsd|jj|j|jfS(Ns %s[%r:%s](RRRR'(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRscCs/|jj\}}}|d7}|||fS(Ni(RR(RRRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs (RRR RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR&s  tNegationcBs)eZdZdZdZdZRS(s. Represents selector:not(subselector) cCs||_||_dS(N(Rt subselector(RRR)((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs cCsd|jj|j|jfS(Ns%s[%r:not(%r)](RRRR)(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRscCsI|jj\}}}|jj\}}}||||||fS(N(RRR)(Rta1tb1tc1ta2tb2tc2((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs(RRR RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR(s  tAttribcBs)eZdZdZdZdZRS(s> Represents selector[namespace|attrib operator value] cCs1||_||_||_||_||_dS(N(Rt namespacetattribtoperatorR!(RRR1R2R3R!((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs     cCs~|jr"d|j|jf}n |j}|jdkrTd|jj|j|fSd|jj|j||j|jfSdS(Ns%s|%stexistss %s[%r[%s]]s%s[%r[%s %s %r]](R1R2R3RRRR!(RR2((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs  cCs/|jj\}}}|d7}|||fS(Ni(RR(RRRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs (RRR RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR0s  tElementcBs/eZdZdddZdZdZRS(sU Represents namespace|element `None` is for the universal selector '*' cCs||_||_dS(N(R1telement(RR1R6((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs cCsB|jp d}|jr.d|j|f}nd|jj|fS(Nt*s%s|%ss%s[%s](R6R1RR(RR6((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs cCs|jr dSdSdS(Nii(iii(iii(R6(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR s N(RRR R RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR5s tHashcBs)eZdZdZdZdZRS(s Represents selector#id cCs||_||_dS(N(Rtid(RRR9((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs cCsd|jj|j|jfS(Ns %s[%r#%s](RRRR9(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRscCs/|jj\}}}|d7}|||fS(Ni(RR(RRRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs (RRR RRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR8s  tCombinedSelectorcBs#eZdZdZdZRS(cCs1|dk st||_||_||_dS(N(R tAssertionErrorRt combinatorR)(RRR<R)((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR$s  cCsA|jdkrd}n |j}d|jj|j||jfS(Nt s s %s[%r %s %r](R<RRRR)(Rtcomb((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR*s   cCsI|jj\}}}|jj\}}}||||||fS(N(RRR)(RR*R+R,R-R.R/((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR2s(RRRRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR:#s  s%^[ \t\r\n\f]*([a-zA-Z]+)[ \t\r\n\f]*$s6^[ \t\r\n\f]*([a-zA-Z]*)#([a-zA-Z0-9_-]+)[ \t\r\n\f]*$s?^[ \t\r\n\f]*([a-zA-Z]*)\.([a-zA-Z][a-zA-Z0-9_-]*)[ \t\r\n\f]*$cCstj|}|r4ttd|jdgStj|}|dk rtttd|jdpmd|jdgStj|}|dk rtt td|jdpd|jdgSt t |}||_ t t|S(sParse a CSS *group of selectors*. If you don't care about pseudo-elements or selector specificity, you can skip this and use :meth:`~GenericTranslator.css_to_xpath`. :param css: A *group of selectors* as an Unicode string. :raises: :class:`SelectorSyntaxError` on invalid selectors. :returns: A list of parsed :class:`Selector` objects, one for each selector in the comma-separated group. R6iiN(t_el_retmatchR R5tgroupt_id_reR R8t _class_reRt TokenStreamttokenizetsourcetlisttparse_selector_group(tcssR@tstream((s4/usr/lib/python2.7/site-packages/cssselect/parser.pytparseEs ! ! ccsP|jx?tt|V|jdkrG|j|jq Pq WdS(NtDELIMt,(RLRM(tskip_whitespaceR tparse_selectortpeektnext(RJ((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRHos   cCst|\}}x|j|j}|d d fkrAPn|rZtd|n|jdddr|jj}|jnd}t|\}}t|||}qW||fS( NtEOFRLRMs4Got pseudo-element ::%s not at the end of a selectort+t>t~R=(RRN(RLRM( tparse_simple_selectorRNRPR R tis_delimRQR!R:(RJtresultRRPR<t next_selector((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyROys"    c Cs|jt|j}|j}|jdks@|dkr|jdkra|jj}n|jd}|jdkr|j|j}q|}d}n d}}t ||}d}x|j}|jdks|j ddd d s|r|dkrPn|r/t d |n|jd krYt ||jj}q|d kr|jt ||j}q|d!kr|jt||}q|d"krN|j|jd#kr'|j|j}|jd$kr|jt|t|}qqn|j}|jd%krWt|}qn|jd&kr~t||}qn|j|j|jdkr3|rt dnt|dt\} } |j} | rt d| | jfn| d'kr!t d| fnt|| }qat||t|}qt d|fqWt|j|krt d|jfn||fS((NtIDENTRLR7t|tSRRRMRSRTRUt)s4Got pseudo-element ::%s not at the end of a selectortHASHt.t[t:t(s first-lines first-lettertbeforetaftertnotsGot nested :not()tinside_negations+Got pseudo-element ::%s inside :not() at %ssExpected ')', got %ssExpected selector, got %s(RLR7(RLR[(R\RR(RLR](RLR_(RLR`(RLRa(RLRa(RLRb(s first-lines first-letterRcRd(RLRb(RLR](RNtlentusedRPR#RQR!R tnext_ident_or_starR5RWR R8Rt next_identt parse_attribRtparse_argumentsRt_unicodeR&RVtTruetposR(R%( RJRftselector_startRPR1R6RXRR'targumenttargument_pseudo_elementRQ((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRVs       '                  cCs{g}xn|j|j}|jd ks@|d d gkrP|j|q |d kr`|Std|fq WdS( NRZtSTRINGtNUMBERRLRSt-R]sExpected an argument, got %s(RZRsRt(RLRS(RLRu(RLR](RNRQR#tappendR (RJR RQ((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRls   cCs|j|j}|dkrP|jdkrPtd|jfn|jdkr|j|jdkrd}|jd}q|}|j}d}n d}}|dkru|j|j}|dkrt|||ddS|dkrd}qu|jdd d d dd r_|jdkr_|j d}|jqutd |fn|j|j}|j dkrtd|fn|j|j}|dkrtd|fnt|||||j S(NRLR[sExpected '|', got %st=s|=t]R4t^t$R7RUt!sOperator expected, got %sRZRss Expected string or ident, got %ssExpected ']', got %s(RLR[(RLR[(RLRw(RLRx(RLRw(RLRw(RZRs(RLRx( RNRiR RPR RQRjR0RWR!R#(RRJR2R1topRQR!((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRksN                     cCsx,|D]$}|jdkrtdqqWdjd|Dj}|dkr^dS|dkrndS|d kr~dSd |krd t|fS|jd d\}}|sd}n7|d ks|d krt|d }n t|}|sd }n t|}||fS(sv Parses the arguments for :nth-child() and friends. :raises: A list of tokens :returns: :``(a, b)`` Rss$String tokens not allowed in series.Rcss|]}|jVqdS(N(R!(t.0R"((s4/usr/lib/python2.7/site-packages/cssselect/parser.pys +stoddiitevenitnRuRSt1(ii(ii(ii(R#t ValueErrortjointstriptinttsplit(ttokensR"tsRR((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt parse_series s,         tTokencBsMeZdZdZdZeejdZeejdZ RS(cCs%tj|||f}||_|S(N(ttuplet__new__Ro(tclsttype_R!Rotobj((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRFs cCsd|j|j|jfS(Ns<%s '%s' at %i>(R#R!Ro(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRKscGs|jdko|j|kS(NRL(R#R!(Rtvalues((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRWNsii( RRRRRWtpropertyR3t itemgetterR#R!(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyREs    tEOFTokencBseZdZdZRS(cCstj|dd|S(NRR(RRR (RRo((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRVscCsd|j|jfS(Ns <%s at %i>(R#Ro(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRYs(RRRR(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRUs t TokenMacroscBsHeZdZedZdeZdZdeefZdeefZRS(s&\\([0-9a-f]{1,6})(?:\r\n|[ \n\r\t\f])?s|\\[^\n\r\f0-9a-f]s\\(?:\n|\r\n|\r|\f)|s [^\0-\177]s[_a-z0-9-]|%s|%ss [_a-z]|%s|%s(RRtunicode_escapetescapet string_escapetnonasciitnmchartnmstart(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyR`s   cCs tj|tttjjS(N(tretcompiletvarsRt IGNORECASER@(tpattern((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt_compilehss [ \t\r\n\f]+s[+-]?(?:[0-9]*\.[0-9]+|[0-9]+)s#(?:%(nmchar)s)+s -?(?:%(nmstart)s)(?:%(nmchar)s)*s!([^\n\r\f\\']|%(string_escape)s)*t's!([^\n\r\f\\"]|%(string_escape)s)*t"s\\(.)s\\(?:\n|\r\n|\r|\f)t methodcallerRAicCs |jdS(Ni(RA(R@((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt_replace_simple}scCs:t|jdd}|tjkr0d}nt|S(Niii(RRAtsyst maxunicodet_unichr(R@t codepoint((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt_replace_unicodes cCs"tt|}tt|}|S(N(t_sub_unicode_escapeRt_sub_simple_escapeR(R!((s4/usr/lib/python2.7/site-packages/cssselect/parser.pytunescape_identsccsd}t|}x||krt|d|}|r\tdd|V|j}qnt|d|}|rtttt|j }td||V|j}qnt |d|}|rtttt|j d}td||V|j}qn||}|t krt ||d|d}|sTt d|j}||krt d |n|||krt d |ntttttd |j }td ||V|d}qnt|d|}|r1|j }td ||V|j}qn|d}|||!dkr|jd|}|dkru|}q|d7}qntd|||V|d7}qW||kst t|VdS(NiRoR\R=RZiR^s)Should have found at least an empty matchsUnclosed string at %ssInvalid string at %sRRsRtis/*s*/iRL(Rgt_match_whitespaceRtendt _match_identRRRRRAt _match_hasht_match_string_by_quoteR;R t_sub_newline_escapet _match_numbertfindR(RRotlen_sR@R!tquotetend_postpos2((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyREsl               RDcBsAeZddZdZdZdZdZdZRS(cCsmg|_t||_||_d|_t|_y|jj|_ Wn t k rh|jj |_ nXdS(N( RhtiterRRFR tpeekedtFalset_peekingRQt next_tokentAttributeErrort__next__(RRRF((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRs     cCsP|jr,t|_|jj|j|jS|j}|jj||SdS(N(RRRhRvRR(RRQ((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRQs   cCs+|js$|j|_t|_n|jS(N(RRRRn(R((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRPs  cCs8|j}|jdkr1td|fn|jS(NRZsExpected ident, got %s(RQR#R R!(RRQ((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRjs cCsI|j}|jdkr"|jS|dkr2dStd|fdS(NRZRLR7sExpected ident or '*', got %s(RLR7(RQR#R!R R (RRQ((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRis  cCs,|j}|jdkr(|jndS(NR\(RPR#RQ(RRP((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRNs N( RRR RRQRPRjRiRN(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyRDs    ((>R RRR3t version_infotunicodeRmtunichrRtstrtchrRt ExceptionRt SyntaxErrorR tobjectR RRR%R&R(R0R5R8R:RR?RBRCRKRHRORRVRlRkRRRRRRRRRRRtsubRRtIRRthasattrRRRRRERD(((s4/usr/lib/python2.7/site-packages/cssselect/parser.pyt sj      ;#  *  S  - %           APK@N#]' xx$site-packages/cssselect/__init__.pyonu[ ǁaWc@sZdZddlmZmZmZmZmZddlmZm Z m Z dZ e Z dS(s\ CSS Selectors based on XPath ============================ This module supports selecting XML/HTML elements based on CSS selectors. See the `CSSSelector` class for details. :copyright: (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. :license: BSD, see LICENSE for more details. i(tparsetSelectortFunctionalPseudoElementt SelectorErrortSelectorSyntaxError(tGenericTranslatortHTMLTranslatortExpressionErrors0.9.2N( t__doc__tcssselect.parserRRRRRtcssselect.xpathRRRtVERSIONt __version__(((s6/usr/lib/python2.7/site-packages/cssselect/__init__.pyts(PK@N#];aa site-packages/cssselect/xpath.pynu[# -*- coding: utf-8 -*- """ cssselect.xpath =============== Translation of parsed CSS selectors to XPath expressions. :copyright: (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. :license: BSD, see LICENSE for more details. """ import sys import re from cssselect.parser import parse, parse_series, SelectorError if sys.version_info[0] < 3: _basestring = basestring _unicode = unicode else: _basestring = str _unicode = str def _unicode_safe_getattr(obj, name, default=None): # getattr() with a non-ASCII name fails on Python 2.x name = name.encode('ascii', 'replace').decode('ascii') return getattr(obj, name, default) class ExpressionError(SelectorError, RuntimeError): """Unknown or unsupported selector (eg. pseudo-class).""" #### XPath Helpers class XPathExpr(object): def __init__(self, path='', element='*', condition='', star_prefix=False): self.path = path self.element = element self.condition = condition def __str__(self): path = _unicode(self.path) + _unicode(self.element) if self.condition: path += '[%s]' % self.condition return path def __repr__(self): return '%s[%s]' % (self.__class__.__name__, self) def add_condition(self, condition): if self.condition: self.condition = '%s and (%s)' % (self.condition, condition) else: self.condition = condition return self def add_name_test(self): if self.element == '*': # We weren't doing a test anyway return self.add_condition( "name() = %s" % GenericTranslator.xpath_literal(self.element)) self.element = '*' def add_star_prefix(self): """ Append '*/' to the path to keep the context constrained to a single parent. """ self.path += '*/' def join(self, combiner, other): path = _unicode(self) + combiner # Any "star prefix" is redundant when joining. if other.path != '*/': path += other.path self.path = path self.element = other.element self.condition = other.condition return self split_at_single_quotes = re.compile("('+)").split # The spec is actually more permissive than that, but don’t bother. # This is just for the fast path. # http://www.w3.org/TR/REC-xml/#NT-NameStartChar is_safe_name = re.compile('^[a-zA-Z_][a-zA-Z0-9_.-]*$').match # Test that the string is not empty and does not contain whitespace is_non_whitespace = re.compile(r'^[^ \t\r\n\f]+$').match #### Translation class GenericTranslator(object): """ Translator for "generic" XML documents. Everything is case-sensitive, no assumption is made on the meaning of element names and attribute names. """ #### #### HERE BE DRAGONS #### #### You are welcome to hook into this to change some behavior, #### but do so at your own risks. #### Until is has recieved a lot more work and review, #### I reserve the right to change this API in backward-incompatible ways #### with any minor version of cssselect. #### See https://github.com/scrapy/cssselect/pull/22 #### -- Simon Sapin. #### combinator_mapping = { ' ': 'descendant', '>': 'child', '+': 'direct_adjacent', '~': 'indirect_adjacent', } attribute_operator_mapping = { 'exists': 'exists', '=': 'equals', '~=': 'includes', '|=': 'dashmatch', '^=': 'prefixmatch', '$=': 'suffixmatch', '*=': 'substringmatch', '!=': 'different', # XXX Not in Level 3 but meh } #: The attribute used for ID selectors depends on the document language: #: http://www.w3.org/TR/selectors/#id-selectors id_attribute = 'id' #: The attribute used for ``:lang()`` depends on the document language: #: http://www.w3.org/TR/selectors/#lang-pseudo lang_attribute = 'xml:lang' #: The case sensitivity of document language element names, #: attribute names, and attribute values in selectors depends #: on the document language. #: http://www.w3.org/TR/selectors/#casesens #: #: When a document language defines one of these as case-insensitive, #: cssselect assumes that the document parser makes the parsed values #: lower-case. Making the selector lower-case too makes the comparaison #: case-insensitive. #: #: In HTML, element names and attributes names (but not attribute values) #: are case-insensitive. All of lxml.html, html5lib, BeautifulSoup4 #: and HTMLParser make them lower-case in their parse result, so #: the assumption holds. lower_case_element_names = False lower_case_attribute_names = False lower_case_attribute_values = False # class used to represent and xpath expression xpathexpr_cls = XPathExpr def css_to_xpath(self, css, prefix='descendant-or-self::'): """Translate a *group of selectors* to XPath. Pseudo-elements are not supported here since XPath only knows about "real" elements. :param css: A *group of selectors* as an Unicode string. :param prefix: This string is prepended to the XPath expression for each selector. The default makes selectors scoped to the context node’s subtree. :raises: :class:`SelectorSyntaxError` on invalid selectors, :class:`ExpressionError` on unknown/unsupported selectors, including pseudo-elements. :returns: The equivalent XPath 1.0 expression as an Unicode string. """ return ' | '.join(self.selector_to_xpath(selector, prefix, translate_pseudo_elements=True) for selector in parse(css)) def selector_to_xpath(self, selector, prefix='descendant-or-self::', translate_pseudo_elements=False): """Translate a parsed selector to XPath. :param selector: A parsed :class:`Selector` object. :param prefix: This string is prepended to the resulting XPath expression. The default makes selectors scoped to the context node’s subtree. :param translate_pseudo_elements: Unless this is set to ``True`` (as :meth:`css_to_xpath` does), the :attr:`~Selector.pseudo_element` attribute of the selector is ignored. It is the caller's responsibility to reject selectors with pseudo-elements, or to account for them somehow. :raises: :class:`ExpressionError` on unknown/unsupported selectors. :returns: The equivalent XPath 1.0 expression as an Unicode string. """ tree = getattr(selector, 'parsed_tree', None) if not tree: raise TypeError('Expected a parsed selector, got %r' % (selector,)) xpath = self.xpath(tree) assert isinstance(xpath, self.xpathexpr_cls) # help debug a missing 'return' if translate_pseudo_elements and selector.pseudo_element: xpath = self.xpath_pseudo_element(xpath, selector.pseudo_element) return (prefix or '') + _unicode(xpath) def xpath_pseudo_element(self, xpath, pseudo_element): """Translate a pseudo-element. Defaults to not supporting pseudo-elements at all, but can be overridden by sub-classes. """ raise ExpressionError('Pseudo-elements are not supported.') @staticmethod def xpath_literal(s): s = _unicode(s) if "'" not in s: s = "'%s'" % s elif '"' not in s: s = '"%s"' % s else: s = "concat(%s)" % ','.join([ (("'" in part) and '"%s"' or "'%s'") % part for part in split_at_single_quotes(s) if part ]) return s def xpath(self, parsed_selector): """Translate any parsed selector object.""" type_name = type(parsed_selector).__name__ method = getattr(self, 'xpath_%s' % type_name.lower(), None) if method is None: raise ExpressionError('%s is not supported.' % type_name) return method(parsed_selector) # Dispatched by parsed object type def xpath_combinedselector(self, combined): """Translate a combined selector.""" combinator = self.combinator_mapping[combined.combinator] method = getattr(self, 'xpath_%s_combinator' % combinator) return method(self.xpath(combined.selector), self.xpath(combined.subselector)) def xpath_negation(self, negation): xpath = self.xpath(negation.selector) sub_xpath = self.xpath(negation.subselector) sub_xpath.add_name_test() if sub_xpath.condition: return xpath.add_condition('not(%s)' % sub_xpath.condition) else: return xpath.add_condition('0') def xpath_function(self, function): """Translate a functional pseudo-class.""" method = 'xpath_%s_function' % function.name.replace('-', '_') method = _unicode_safe_getattr(self, method, None) if not method: raise ExpressionError( "The pseudo-class :%s() is unknown" % function.name) return method(self.xpath(function.selector), function) def xpath_pseudo(self, pseudo): """Translate a pseudo-class.""" method = 'xpath_%s_pseudo' % pseudo.ident.replace('-', '_') method = _unicode_safe_getattr(self, method, None) if not method: # TODO: better error message for pseudo-elements? raise ExpressionError( "The pseudo-class :%s is unknown" % pseudo.ident) return method(self.xpath(pseudo.selector)) def xpath_attrib(self, selector): """Translate an attribute selector.""" operator = self.attribute_operator_mapping[selector.operator] method = getattr(self, 'xpath_attrib_%s' % operator) if self.lower_case_attribute_names: name = selector.attrib.lower() else: name = selector.attrib safe = is_safe_name(name) if selector.namespace: name = '%s:%s' % (selector.namespace, name) safe = safe and is_safe_name(selector.namespace) if safe: attrib = '@' + name else: attrib = 'attribute::*[name() = %s]' % self.xpath_literal(name) if self.lower_case_attribute_values: value = selector.value.lower() else: value = selector.value return method(self.xpath(selector.selector), attrib, value) def xpath_class(self, class_selector): """Translate a class selector.""" # .foo is defined as [class~=foo] in the spec. xpath = self.xpath(class_selector.selector) return self.xpath_attrib_includes( xpath, '@class', class_selector.class_name) def xpath_hash(self, id_selector): """Translate an ID selector.""" xpath = self.xpath(id_selector.selector) return self.xpath_attrib_equals(xpath, '@id', id_selector.id) def xpath_element(self, selector): """Translate a type or universal selector.""" element = selector.element if not element: element = '*' safe = True else: safe = is_safe_name(element) if self.lower_case_element_names: element = element.lower() if selector.namespace: # Namespace prefixes are case-sensitive. # http://www.w3.org/TR/css3-namespace/#prefixes element = '%s:%s' % (selector.namespace, element) safe = safe and is_safe_name(selector.namespace) xpath = self.xpathexpr_cls(element=element) if not safe: xpath.add_name_test() return xpath # CombinedSelector: dispatch by combinator def xpath_descendant_combinator(self, left, right): """right is a child, grand-child or further descendant of left""" return left.join('/descendant-or-self::*/', right) def xpath_child_combinator(self, left, right): """right is an immediate child of left""" return left.join('/', right) def xpath_direct_adjacent_combinator(self, left, right): """right is a sibling immediately after left""" xpath = left.join('/following-sibling::', right) xpath.add_name_test() return xpath.add_condition('position() = 1') def xpath_indirect_adjacent_combinator(self, left, right): """right is a sibling after left, immediately or not""" return left.join('/following-sibling::', right) # Function: dispatch by function/pseudo-class name def xpath_nth_child_function(self, xpath, function, last=False, add_name_test=True): try: a, b = parse_series(function.arguments) except ValueError: raise ExpressionError("Invalid series: '%r'" % function.arguments) if add_name_test: xpath.add_name_test() xpath.add_star_prefix() if a == 0: if last: b = 'last() - %s' % b return xpath.add_condition('position() = %s' % b) if last: # FIXME: I'm not sure if this is right a = -a b = -b if b > 0: b_neg = str(-b) else: b_neg = '+%s' % (-b) if a != 1: expr = ['(position() %s) mod %s = 0' % (b_neg, a)] else: expr = [] if b >= 0: expr.append('position() >= %s' % b) elif b < 0 and last: expr.append('position() < (last() %s)' % b) expr = ' and '.join(expr) if expr: xpath.add_condition(expr) return xpath # FIXME: handle an+b, odd, even # an+b means every-a, plus b, e.g., 2n+1 means odd # 0n+b means b # n+0 means a=1, i.e., all elements # an means every a elements, i.e., 2n means even # -n means -1n # -1n+6 means elements 6 and previous def xpath_nth_last_child_function(self, xpath, function): return self.xpath_nth_child_function(xpath, function, last=True) def xpath_nth_of_type_function(self, xpath, function): if xpath.element == '*': raise ExpressionError( "*:nth-of-type() is not implemented") return self.xpath_nth_child_function(xpath, function, add_name_test=False) def xpath_nth_last_of_type_function(self, xpath, function): if xpath.element == '*': raise ExpressionError( "*:nth-of-type() is not implemented") return self.xpath_nth_child_function(xpath, function, last=True, add_name_test=False) def xpath_contains_function(self, xpath, function): # Defined there, removed in later drafts: # http://www.w3.org/TR/2001/CR-css3-selectors-20011113/#content-selectors if function.argument_types() not in (['STRING'], ['IDENT']): raise ExpressionError( "Expected a single string or ident for :contains(), got %r" % function.arguments) value = function.arguments[0].value return xpath.add_condition( 'contains(., %s)' % self.xpath_literal(value)) def xpath_lang_function(self, xpath, function): if function.argument_types() not in (['STRING'], ['IDENT']): raise ExpressionError( "Expected a single string or ident for :lang(), got %r" % function.arguments) value = function.arguments[0].value return xpath.add_condition( "lang(%s)" % (self.xpath_literal(value))) # Pseudo: dispatch by pseudo-class name def xpath_root_pseudo(self, xpath): return xpath.add_condition("not(parent::*)") def xpath_first_child_pseudo(self, xpath): xpath.add_star_prefix() xpath.add_name_test() return xpath.add_condition('position() = 1') def xpath_last_child_pseudo(self, xpath): xpath.add_star_prefix() xpath.add_name_test() return xpath.add_condition('position() = last()') def xpath_first_of_type_pseudo(self, xpath): if xpath.element == '*': raise ExpressionError( "*:first-of-type is not implemented") xpath.add_star_prefix() return xpath.add_condition('position() = 1') def xpath_last_of_type_pseudo(self, xpath): if xpath.element == '*': raise ExpressionError( "*:last-of-type is not implemented") xpath.add_star_prefix() return xpath.add_condition('position() = last()') def xpath_only_child_pseudo(self, xpath): xpath.add_name_test() xpath.add_star_prefix() return xpath.add_condition('last() = 1') def xpath_only_of_type_pseudo(self, xpath): if xpath.element == '*': raise ExpressionError( "*:only-of-type is not implemented") return xpath.add_condition('last() = 1') def xpath_empty_pseudo(self, xpath): return xpath.add_condition("not(*) and not(string-length())") def pseudo_never_matches(self, xpath): """Common implementation for pseudo-classes that never match.""" return xpath.add_condition("0") xpath_link_pseudo = pseudo_never_matches xpath_visited_pseudo = pseudo_never_matches xpath_hover_pseudo = pseudo_never_matches xpath_active_pseudo = pseudo_never_matches xpath_focus_pseudo = pseudo_never_matches xpath_target_pseudo = pseudo_never_matches xpath_enabled_pseudo = pseudo_never_matches xpath_disabled_pseudo = pseudo_never_matches xpath_checked_pseudo = pseudo_never_matches # Attrib: dispatch by attribute operator def xpath_attrib_exists(self, xpath, name, value): assert not value xpath.add_condition(name) return xpath def xpath_attrib_equals(self, xpath, name, value): xpath.add_condition('%s = %s' % (name, self.xpath_literal(value))) return xpath def xpath_attrib_different(self, xpath, name, value): # FIXME: this seems like a weird hack... if value: xpath.add_condition('not(%s) or %s != %s' % (name, name, self.xpath_literal(value))) else: xpath.add_condition('%s != %s' % (name, self.xpath_literal(value))) return xpath def xpath_attrib_includes(self, xpath, name, value): if is_non_whitespace(value): xpath.add_condition( "%s and contains(concat(' ', normalize-space(%s), ' '), %s)" % (name, name, self.xpath_literal(' '+value+' '))) else: xpath.add_condition('0') return xpath def xpath_attrib_dashmatch(self, xpath, name, value): # Weird, but true... xpath.add_condition('%s and (%s = %s or starts-with(%s, %s))' % ( name, name, self.xpath_literal(value), name, self.xpath_literal(value + '-'))) return xpath def xpath_attrib_prefixmatch(self, xpath, name, value): if value: xpath.add_condition('%s and starts-with(%s, %s)' % ( name, name, self.xpath_literal(value))) else: xpath.add_condition('0') return xpath def xpath_attrib_suffixmatch(self, xpath, name, value): if value: # Oddly there is a starts-with in XPath 1.0, but not ends-with xpath.add_condition( '%s and substring(%s, string-length(%s)-%s) = %s' % (name, name, name, len(value)-1, self.xpath_literal(value))) else: xpath.add_condition('0') return xpath def xpath_attrib_substringmatch(self, xpath, name, value): if value: # Attribute selectors are case sensitive xpath.add_condition('%s and contains(%s, %s)' % ( name, name, self.xpath_literal(value))) else: xpath.add_condition('0') return xpath class HTMLTranslator(GenericTranslator): """ Translator for (X)HTML documents. Has a more useful implementation of some pseudo-classes based on HTML-specific element names and attribute names, as described in the `HTML5 specification`_. It assumes no-quirks mode. The API is the same as :class:`GenericTranslator`. .. _HTML5 specification: http://www.w3.org/TR/html5/links.html#selectors :param xhtml: If false (the default), element names and attribute names are case-insensitive. """ lang_attribute = 'lang' def __init__(self, xhtml=False): self.xhtml = xhtml # Might be useful for sub-classes? if not xhtml: # See their definition in GenericTranslator. self.lower_case_element_names = True self.lower_case_attribute_names = True def xpath_checked_pseudo(self, xpath): # FIXME: is this really all the elements? return xpath.add_condition( "(@selected and name(.) = 'option') or " "(@checked " "and (name(.) = 'input' or name(.) = 'command')" "and (@type = 'checkbox' or @type = 'radio'))") def xpath_lang_function(self, xpath, function): if function.argument_types() not in (['STRING'], ['IDENT']): raise ExpressionError( "Expected a single string or ident for :lang(), got %r" % function.arguments) value = function.arguments[0].value return xpath.add_condition( "ancestor-or-self::*[@lang][1][starts-with(concat(" # XPath 1.0 has no lower-case function... "translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', " "'abcdefghijklmnopqrstuvwxyz'), " "'-'), %s)]" % (self.lang_attribute, self.xpath_literal(value.lower() + '-'))) def xpath_link_pseudo(self, xpath): return xpath.add_condition("@href and " "(name(.) = 'a' or name(.) = 'link' or name(.) = 'area')") # Links are never visited, the implementation for :visited is the same # as in GenericTranslator def xpath_disabled_pseudo(self, xpath): # http://www.w3.org/TR/html5/section-index.html#attributes-1 return xpath.add_condition(''' ( @disabled and ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' or name(.) = 'command' or name(.) = 'fieldset' or name(.) = 'optgroup' or name(.) = 'option' ) ) or ( ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' ) and ancestor::fieldset[@disabled] ) ''') # FIXME: in the second half, add "and is not a descendant of that # fieldset element's first legend element child, if any." def xpath_enabled_pseudo(self, xpath): # http://www.w3.org/TR/html5/section-index.html#attributes-1 return xpath.add_condition(''' ( @href and ( name(.) = 'a' or name(.) = 'link' or name(.) = 'area' ) ) or ( ( name(.) = 'command' or name(.) = 'fieldset' or name(.) = 'optgroup' ) and not(@disabled) ) or ( ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' or name(.) = 'keygen' ) and not (@disabled or ancestor::fieldset[@disabled]) ) or ( name(.) = 'option' and not( @disabled or ancestor::optgroup[@disabled] ) ) ''') # FIXME: ... or "li elements that are children of menu elements, # and that have a child element that defines a command, if the first # such element's Disabled State facet is false (not disabled)". # FIXME: after ancestor::fieldset[@disabled], add "and is not a # descendant of that fieldset element's first legend element child, # if any." PK@N#]5/\\!site-packages/cssselect/parser.pynu[# -*- coding: utf-8 -*- """ cssselect.parser ================ Tokenizer, parser and parsed objects for CSS selectors. :copyright: (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. :license: BSD, see LICENSE for more details. """ import sys import re import operator if sys.version_info[0] < 3: _unicode = unicode _unichr = unichr else: _unicode = str _unichr = chr def ascii_lower(string): """Lower-case, but only in the ASCII range.""" return string.encode('utf8').lower().decode('utf8') class SelectorError(Exception): """Common parent for :class:`SelectorSyntaxError` and :class:`ExpressionError`. You can just use ``except SelectorError:`` when calling :meth:`~GenericTranslator.css_to_xpath` and handle both exceptions types. """ class SelectorSyntaxError(SelectorError, SyntaxError): """Parsing a selector that does not match the grammar.""" #### Parsed objects class Selector(object): """ Represents a parsed selector. :meth:`~GenericTranslator.selector_to_xpath` accepts this object, but ignores :attr:`pseudo_element`. It is the user’s responsibility to account for pseudo-elements and reject selectors with unknown or unsupported pseudo-elements. """ def __init__(self, tree, pseudo_element=None): self.parsed_tree = tree if pseudo_element is not None and not isinstance( pseudo_element, FunctionalPseudoElement): pseudo_element = ascii_lower(pseudo_element) #: A :class:`FunctionalPseudoElement`, #: or the identifier for the pseudo-element as a string, # or ``None``. #: #: +-------------------------+----------------+--------------------------------+ #: | | Selector | Pseudo-element | #: +=========================+================+================================+ #: | CSS3 syntax | ``a::before`` | ``'before'`` | #: +-------------------------+----------------+--------------------------------+ #: | Older syntax | ``a:before`` | ``'before'`` | #: +-------------------------+----------------+--------------------------------+ #: | From the Lists3_ draft, | ``li::marker`` | ``'marker'`` | #: | not in Selectors3 | | | #: +-------------------------+----------------+--------------------------------+ #: | Invalid pseudo-class | ``li:marker`` | ``None`` | #: +-------------------------+----------------+--------------------------------+ #: | Functinal | ``a::foo(2)`` | ``FunctionalPseudoElement(…)`` | #: +-------------------------+----------------+--------------------------------+ #: #: .. _Lists3: http://www.w3.org/TR/2011/WD-css3-lists-20110524/#marker-pseudoelement self.pseudo_element = pseudo_element def __repr__(self): if isinstance(self.pseudo_element, FunctionalPseudoElement): pseudo_element = repr(self.pseudo_element) elif self.pseudo_element: pseudo_element = '::%s' % self.pseudo_element else: pseudo_element = '' return '%s[%r%s]' % ( self.__class__.__name__, self.parsed_tree, pseudo_element) def specificity(self): """Return the specificity_ of this selector as a tuple of 3 integers. .. _specificity: http://www.w3.org/TR/selectors/#specificity """ a, b, c = self.parsed_tree.specificity() if self.pseudo_element: c += 1 return a, b, c class Class(object): """ Represents selector.class_name """ def __init__(self, selector, class_name): self.selector = selector self.class_name = class_name def __repr__(self): return '%s[%r.%s]' % ( self.__class__.__name__, self.selector, self.class_name) def specificity(self): a, b, c = self.selector.specificity() b += 1 return a, b, c class FunctionalPseudoElement(object): """ Represents selector::name(arguments) .. attribute:: name The name (identifier) of the pseudo-element, as a string. .. attribute:: arguments The arguments of the pseudo-element, as a list of tokens. **Note:** tokens are not part of the public API, and may change between cssselect versions. Use at your own risks. """ def __init__(self, name, arguments): self.name = ascii_lower(name) self.arguments = arguments def __repr__(self): return '%s[::%s(%r)]' % ( self.__class__.__name__, self.name, [token.value for token in self.arguments]) def argument_types(self): return [token.type for token in self.arguments] def specificity(self): a, b, c = self.selector.specificity() b += 1 return a, b, c class Function(object): """ Represents selector:name(expr) """ def __init__(self, selector, name, arguments): self.selector = selector self.name = ascii_lower(name) self.arguments = arguments def __repr__(self): return '%s[%r:%s(%r)]' % ( self.__class__.__name__, self.selector, self.name, [token.value for token in self.arguments]) def argument_types(self): return [token.type for token in self.arguments] def specificity(self): a, b, c = self.selector.specificity() b += 1 return a, b, c class Pseudo(object): """ Represents selector:ident """ def __init__(self, selector, ident): self.selector = selector self.ident = ascii_lower(ident) def __repr__(self): return '%s[%r:%s]' % ( self.__class__.__name__, self.selector, self.ident) def specificity(self): a, b, c = self.selector.specificity() b += 1 return a, b, c class Negation(object): """ Represents selector:not(subselector) """ def __init__(self, selector, subselector): self.selector = selector self.subselector = subselector def __repr__(self): return '%s[%r:not(%r)]' % ( self.__class__.__name__, self.selector, self.subselector) def specificity(self): a1, b1, c1 = self.selector.specificity() a2, b2, c2 = self.subselector.specificity() return a1 + a2, b1 + b2, c1 + c2 class Attrib(object): """ Represents selector[namespace|attrib operator value] """ def __init__(self, selector, namespace, attrib, operator, value): self.selector = selector self.namespace = namespace self.attrib = attrib self.operator = operator self.value = value def __repr__(self): if self.namespace: attrib = '%s|%s' % (self.namespace, self.attrib) else: attrib = self.attrib if self.operator == 'exists': return '%s[%r[%s]]' % ( self.__class__.__name__, self.selector, attrib) else: return '%s[%r[%s %s %r]]' % ( self.__class__.__name__, self.selector, attrib, self.operator, self.value) def specificity(self): a, b, c = self.selector.specificity() b += 1 return a, b, c class Element(object): """ Represents namespace|element `None` is for the universal selector '*' """ def __init__(self, namespace=None, element=None): self.namespace = namespace self.element = element def __repr__(self): element = self.element or '*' if self.namespace: element = '%s|%s' % (self.namespace, element) return '%s[%s]' % (self.__class__.__name__, element) def specificity(self): if self.element: return 0, 0, 1 else: return 0, 0, 0 class Hash(object): """ Represents selector#id """ def __init__(self, selector, id): self.selector = selector self.id = id def __repr__(self): return '%s[%r#%s]' % ( self.__class__.__name__, self.selector, self.id) def specificity(self): a, b, c = self.selector.specificity() a += 1 return a, b, c class CombinedSelector(object): def __init__(self, selector, combinator, subselector): assert selector is not None self.selector = selector self.combinator = combinator self.subselector = subselector def __repr__(self): if self.combinator == ' ': comb = '' else: comb = self.combinator return '%s[%r %s %r]' % ( self.__class__.__name__, self.selector, comb, self.subselector) def specificity(self): a1, b1, c1 = self.selector.specificity() a2, b2, c2 = self.subselector.specificity() return a1 + a2, b1 + b2, c1 + c2 #### Parser # foo _el_re = re.compile(r'^[ \t\r\n\f]*([a-zA-Z]+)[ \t\r\n\f]*$') # foo#bar or #bar _id_re = re.compile(r'^[ \t\r\n\f]*([a-zA-Z]*)#([a-zA-Z0-9_-]+)[ \t\r\n\f]*$') # foo.bar or .bar _class_re = re.compile( r'^[ \t\r\n\f]*([a-zA-Z]*)\.([a-zA-Z][a-zA-Z0-9_-]*)[ \t\r\n\f]*$') def parse(css): """Parse a CSS *group of selectors*. If you don't care about pseudo-elements or selector specificity, you can skip this and use :meth:`~GenericTranslator.css_to_xpath`. :param css: A *group of selectors* as an Unicode string. :raises: :class:`SelectorSyntaxError` on invalid selectors. :returns: A list of parsed :class:`Selector` objects, one for each selector in the comma-separated group. """ # Fast path for simple cases match = _el_re.match(css) if match: return [Selector(Element(element=match.group(1)))] match = _id_re.match(css) if match is not None: return [Selector(Hash(Element(element=match.group(1) or None), match.group(2)))] match = _class_re.match(css) if match is not None: return [Selector(Class(Element(element=match.group(1) or None), match.group(2)))] stream = TokenStream(tokenize(css)) stream.source = css return list(parse_selector_group(stream)) # except SelectorSyntaxError: # e = sys.exc_info()[1] # message = "%s at %s -> %r" % ( # e, stream.used, stream.peek()) # e.msg = message # if sys.version_info < (2,6): # e.message = message # e.args = tuple([message]) # raise def parse_selector_group(stream): stream.skip_whitespace() while 1: yield Selector(*parse_selector(stream)) if stream.peek() == ('DELIM', ','): stream.next() stream.skip_whitespace() else: break def parse_selector(stream): result, pseudo_element = parse_simple_selector(stream) while 1: stream.skip_whitespace() peek = stream.peek() if peek in (('EOF', None), ('DELIM', ',')): break if pseudo_element: raise SelectorSyntaxError( 'Got pseudo-element ::%s not at the end of a selector' % pseudo_element) if peek.is_delim('+', '>', '~'): # A combinator combinator = stream.next().value stream.skip_whitespace() else: # By exclusion, the last parse_simple_selector() ended # at peek == ' ' combinator = ' ' next_selector, pseudo_element = parse_simple_selector(stream) result = CombinedSelector(result, combinator, next_selector) return result, pseudo_element def parse_simple_selector(stream, inside_negation=False): stream.skip_whitespace() selector_start = len(stream.used) peek = stream.peek() if peek.type == 'IDENT' or peek == ('DELIM', '*'): if peek.type == 'IDENT': namespace = stream.next().value else: stream.next() namespace = None if stream.peek() == ('DELIM', '|'): stream.next() element = stream.next_ident_or_star() else: element = namespace namespace = None else: element = namespace = None result = Element(namespace, element) pseudo_element = None while 1: peek = stream.peek() if peek.type in ('S', 'EOF') or peek.is_delim(',', '+', '>', '~') or ( inside_negation and peek == ('DELIM', ')')): break if pseudo_element: raise SelectorSyntaxError( 'Got pseudo-element ::%s not at the end of a selector' % pseudo_element) if peek.type == 'HASH': result = Hash(result, stream.next().value) elif peek == ('DELIM', '.'): stream.next() result = Class(result, stream.next_ident()) elif peek == ('DELIM', '['): stream.next() result = parse_attrib(result, stream) elif peek == ('DELIM', ':'): stream.next() if stream.peek() == ('DELIM', ':'): stream.next() pseudo_element = stream.next_ident() if stream.peek() == ('DELIM', '('): stream.next() pseudo_element = FunctionalPseudoElement( pseudo_element, parse_arguments(stream)) continue ident = stream.next_ident() if ident.lower() in ('first-line', 'first-letter', 'before', 'after'): # Special case: CSS 2.1 pseudo-elements can have a single ':' # Any new pseudo-element must have two. pseudo_element = _unicode(ident) continue if stream.peek() != ('DELIM', '('): result = Pseudo(result, ident) continue stream.next() stream.skip_whitespace() if ident.lower() == 'not': if inside_negation: raise SelectorSyntaxError('Got nested :not()') argument, argument_pseudo_element = parse_simple_selector( stream, inside_negation=True) next = stream.next() if argument_pseudo_element: raise SelectorSyntaxError( 'Got pseudo-element ::%s inside :not() at %s' % (argument_pseudo_element, next.pos)) if next != ('DELIM', ')'): raise SelectorSyntaxError("Expected ')', got %s" % (next,)) result = Negation(result, argument) else: result = Function(result, ident, parse_arguments(stream)) else: raise SelectorSyntaxError( "Expected selector, got %s" % (peek,)) if len(stream.used) == selector_start: raise SelectorSyntaxError( "Expected selector, got %s" % (stream.peek(),)) return result, pseudo_element def parse_arguments(stream): arguments = [] while 1: stream.skip_whitespace() next = stream.next() if next.type in ('IDENT', 'STRING', 'NUMBER') or next in [ ('DELIM', '+'), ('DELIM', '-')]: arguments.append(next) elif next == ('DELIM', ')'): return arguments else: raise SelectorSyntaxError( "Expected an argument, got %s" % (next,)) def parse_attrib(selector, stream): stream.skip_whitespace() attrib = stream.next_ident_or_star() if attrib is None and stream.peek() != ('DELIM', '|'): raise SelectorSyntaxError( "Expected '|', got %s" % (stream.peek(),)) if stream.peek() == ('DELIM', '|'): stream.next() if stream.peek() == ('DELIM', '='): namespace = None stream.next() op = '|=' else: namespace = attrib attrib = stream.next_ident() op = None else: namespace = op = None if op is None: stream.skip_whitespace() next = stream.next() if next == ('DELIM', ']'): return Attrib(selector, namespace, attrib, 'exists', None) elif next == ('DELIM', '='): op = '=' elif next.is_delim('^', '$', '*', '~', '|', '!') and ( stream.peek() == ('DELIM', '=')): op = next.value + '=' stream.next() else: raise SelectorSyntaxError( "Operator expected, got %s" % (next,)) stream.skip_whitespace() value = stream.next() if value.type not in ('IDENT', 'STRING'): raise SelectorSyntaxError( "Expected string or ident, got %s" % (value,)) stream.skip_whitespace() next = stream.next() if next != ('DELIM', ']'): raise SelectorSyntaxError( "Expected ']', got %s" % (next,)) return Attrib(selector, namespace, attrib, op, value.value) def parse_series(tokens): """ Parses the arguments for :nth-child() and friends. :raises: A list of tokens :returns: :``(a, b)`` """ for token in tokens: if token.type == 'STRING': raise ValueError('String tokens not allowed in series.') s = ''.join(token.value for token in tokens).strip() if s == 'odd': return (2, 1) elif s == 'even': return (2, 0) elif s == 'n': return (1, 0) if 'n' not in s: # Just b return (0, int(s)) a, b = s.split('n', 1) if not a: a = 1 elif a == '-' or a == '+': a = int(a+'1') else: a = int(a) if not b: b = 0 else: b = int(b) return (a, b) #### Token objects class Token(tuple): def __new__(cls, type_, value, pos): obj = tuple.__new__(cls, (type_, value)) obj.pos = pos return obj def __repr__(self): return "<%s '%s' at %i>" % (self.type, self.value, self.pos) def is_delim(self, *values): return self.type == 'DELIM' and self.value in values type = property(operator.itemgetter(0)) value = property(operator.itemgetter(1)) class EOFToken(Token): def __new__(cls, pos): return Token.__new__(cls, 'EOF', None, pos) def __repr__(self): return '<%s at %i>' % (self.type, self.pos) #### Tokenizer class TokenMacros: unicode_escape = r'\\([0-9a-f]{1,6})(?:\r\n|[ \n\r\t\f])?' escape = unicode_escape + r'|\\[^\n\r\f0-9a-f]' string_escape = r'\\(?:\n|\r\n|\r|\f)|' + escape nonascii = r'[^\0-\177]' nmchar = '[_a-z0-9-]|%s|%s' % (escape, nonascii) nmstart = '[_a-z]|%s|%s' % (escape, nonascii) def _compile(pattern): return re.compile(pattern % vars(TokenMacros), re.IGNORECASE).match _match_whitespace = _compile(r'[ \t\r\n\f]+') _match_number = _compile('[+-]?(?:[0-9]*\.[0-9]+|[0-9]+)') _match_hash = _compile('#(?:%(nmchar)s)+') _match_ident = _compile('-?(?:%(nmstart)s)(?:%(nmchar)s)*') _match_string_by_quote = { "'": _compile(r"([^\n\r\f\\']|%(string_escape)s)*"), '"': _compile(r'([^\n\r\f\\"]|%(string_escape)s)*'), } _sub_simple_escape = re.compile(r'\\(.)').sub _sub_unicode_escape = re.compile(TokenMacros.unicode_escape, re.I).sub _sub_newline_escape =re.compile(r'\\(?:\n|\r\n|\r|\f)').sub # Same as r'\1', but faster on CPython if hasattr(operator, 'methodcaller'): # Python 2.6+ _replace_simple = operator.methodcaller('group', 1) else: def _replace_simple(match): return match.group(1) def _replace_unicode(match): codepoint = int(match.group(1), 16) if codepoint > sys.maxunicode: codepoint = 0xFFFD return _unichr(codepoint) def unescape_ident(value): value = _sub_unicode_escape(_replace_unicode, value) value = _sub_simple_escape(_replace_simple, value) return value def tokenize(s): pos = 0 len_s = len(s) while pos < len_s: match = _match_whitespace(s, pos=pos) if match: yield Token('S', ' ', pos) pos = match.end() continue match = _match_ident(s, pos=pos) if match: value = _sub_simple_escape(_replace_simple, _sub_unicode_escape(_replace_unicode, match.group())) yield Token('IDENT', value, pos) pos = match.end() continue match = _match_hash(s, pos=pos) if match: value = _sub_simple_escape(_replace_simple, _sub_unicode_escape(_replace_unicode, match.group()[1:])) yield Token('HASH', value, pos) pos = match.end() continue quote = s[pos] if quote in _match_string_by_quote: match = _match_string_by_quote[quote](s, pos=pos + 1) assert match, 'Should have found at least an empty match' end_pos = match.end() if end_pos == len_s: raise SelectorSyntaxError('Unclosed string at %s' % pos) if s[end_pos] != quote: raise SelectorSyntaxError('Invalid string at %s' % pos) value = _sub_simple_escape(_replace_simple, _sub_unicode_escape(_replace_unicode, _sub_newline_escape('', match.group()))) yield Token('STRING', value, pos) pos = end_pos + 1 continue match = _match_number(s, pos=pos) if match: value = match.group() yield Token('NUMBER', value, pos) pos = match.end() continue pos2 = pos + 2 if s[pos:pos2] == '/*': pos = s.find('*/', pos2) if pos == -1: pos = len_s else: pos += 2 continue yield Token('DELIM', s[pos], pos) pos += 1 assert pos == len_s yield EOFToken(pos) class TokenStream(object): def __init__(self, tokens, source=None): self.used = [] self.tokens = iter(tokens) self.source = source self.peeked = None self._peeking = False try: self.next_token = self.tokens.next except AttributeError: # Python 3 self.next_token = self.tokens.__next__ def next(self): if self._peeking: self._peeking = False self.used.append(self.peeked) return self.peeked else: next = self.next_token() self.used.append(next) return next def peek(self): if not self._peeking: self.peeked = self.next_token() self._peeking = True return self.peeked def next_ident(self): next = self.next() if next.type != 'IDENT': raise SelectorSyntaxError('Expected ident, got %s' % (next,)) return next.value def next_ident_or_star(self): next = self.next() if next.type == 'IDENT': return next.value elif next == ('DELIM', '*'): return None else: raise SelectorSyntaxError( "Expected ident or '*', got %s" % (next,)) def skip_whitespace(self): peek = self.peek() if peek.type == 'S': self.next() PK@N#]$t ^ ^!site-packages/cssselect/xpath.pycnu[ ǁaWc@s dZddlZddlZddlmZmZmZejddkr\eZ e Z n e Z e Z e dZdeefdYZd efd YZejd jZejd jZejd jZdefdYZdefdYZdS(s cssselect.xpath =============== Translation of parsed CSS selectors to XPath expressions. :copyright: (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. :license: BSD, see LICENSE for more details. iN(tparset parse_seriest SelectorErroriicCs+|jddjd}t|||S(Ntasciitreplace(tencodetdecodetgetattr(tobjtnametdefault((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt_unicode_safe_getattrstExpressionErrorcBseZdZRS(s3Unknown or unsupported selector (eg. pseudo-class).(t__name__t __module__t__doc__(((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyR #st XPathExprcBsSeZdddedZdZdZdZdZdZdZ RS( tt*cCs||_||_||_dS(N(tpathtelementt condition(tselfRRRt star_prefix((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt__init__+s  cCs=t|jt|j}|jr9|d|j7}n|S(Ns[%s](t_unicodeRRR(RR((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt__str__0s cCsd|jj|fS(Ns%s[%s](t __class__R (R((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt__repr__6scCs/|jr"d|j|f|_n ||_|S(Ns %s and (%s)(R(RR((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt add_condition9s  cCs=|jdkrdS|jdtj|jd|_dS(NRs name() = %s(RRtGenericTranslatort xpath_literal(R((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt add_name_test@s cCs|jd7_dS(se Append '*/' to the path to keep the context constrained to a single parent. s*/N(R(R((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytadd_star_prefixHscCsTt||}|jdkr/||j7}n||_|j|_|j|_|S(Ns*/(RRRR(RtcombinertotherR((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytjoinOs   ( R RtFalseRRRRR R!R$(((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyR)s     s('+)s^[a-zA-Z_][a-zA-Z0-9_.-]*$s^[^ \t\r\n\f]+$RcBsEeZdZidd6dd6dd6dd6Zid d 6d d 6d d 6dd6dd6dd6dd6dd6ZdZdZeZeZ eZ e Z ddZ dedZdZedZdZd Zd!Zd"Zd#Zd$Zd%Zd&Zd'Zd(Zd)Zd*Zd+Zeed,Z d-Z!d.Z"d/Z#d0Z$d1Z%d2Z&d3Z'd4Z(d5Z)d6Z*d7Z+d8Z,d9Z-d:Z.e.Z/e.Z0e.Z1e.Z2e.Z3e.Z4e.Z5e.Z6e.Z7d;Z8d<Z9d=Z:d>Z;d?Z<d@Z=dAZ>dBZ?RS(Cs Translator for "generic" XML documents. Everything is case-sensitive, no assumption is made on the meaning of element names and attribute names. t descendantt tchildt>tdirect_adjacentt+tindirect_adjacentt~texiststequalst=tincludess~=t dashmatchs|=t prefixmatchs^=t suffixmatchs$=tsubstringmatchs*=t differents!=tidsxml:langsdescendant-or-self::cs&djfdt|DS(sTranslate a *group of selectors* to XPath. Pseudo-elements are not supported here since XPath only knows about "real" elements. :param css: A *group of selectors* as an Unicode string. :param prefix: This string is prepended to the XPath expression for each selector. The default makes selectors scoped to the context node’s subtree. :raises: :class:`SelectorSyntaxError` on invalid selectors, :class:`ExpressionError` on unknown/unsupported selectors, including pseudo-elements. :returns: The equivalent XPath 1.0 expression as an Unicode string. s | c3s'|]}j|dtVqdS(ttranslate_pseudo_elementsN(tselector_to_xpathtTrue(t.0tselector(tprefixR(s3/usr/lib/python2.7/site-packages/cssselect/xpath.pys s(R$R(RtcssR=((R=Rs3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt css_to_xpathscCst|dd}|s.td|fn|j|}t||jsUt|r||jr||j||j}n|pdt |S(s4Translate a parsed selector to XPath. :param selector: A parsed :class:`Selector` object. :param prefix: This string is prepended to the resulting XPath expression. The default makes selectors scoped to the context node’s subtree. :param translate_pseudo_elements: Unless this is set to ``True`` (as :meth:`css_to_xpath` does), the :attr:`~Selector.pseudo_element` attribute of the selector is ignored. It is the caller's responsibility to reject selectors with pseudo-elements, or to account for them somehow. :raises: :class:`ExpressionError` on unknown/unsupported selectors. :returns: The equivalent XPath 1.0 expression as an Unicode string. t parsed_trees"Expected a parsed selector, got %rRN( RtNonet TypeErrortxpatht isinstancet xpathexpr_clstAssertionErrortpseudo_elementtxpath_pseudo_elementR(RR<R=R8ttreeRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyR9scCstddS(sTranslate a pseudo-element. Defaults to not supporting pseudo-elements at all, but can be overridden by sub-classes. s"Pseudo-elements are not supported.N(R (RRCRG((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRHscCst|}d|kr%d|}nad|kr>d|}nHddjgt|D](}|rTd|krrdpud|^qT}|S(Nt's'%s't"s"%s"s concat(%s)t,(RR$tsplit_at_single_quotes(tstpart((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRs      <cCsTt|j}t|d|jd}|dkrJtd|n||S(s%Translate any parsed selector object.sxpath_%ss%s is not supported.N(ttypeR RtlowerRAR (Rtparsed_selectort type_nametmethod((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRCs  cCsH|j|j}t|d|}||j|j|j|jS(sTranslate a combined selector.sxpath_%s_combinator(tcombinator_mappingt combinatorRRCR<t subselector(RtcombinedRVRT((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_combinedselectorscCs\|j|j}|j|j}|j|jrK|jd|jS|jdSdS(Nsnot(%s)t0(RCR<RWR RR(RtnegationRCt sub_xpath((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_negation s   cCs`d|jjdd}t||d}|sGtd|jn||j|j|S(s$Translate a functional pseudo-class.sxpath_%s_functiont-t_s!The pseudo-class :%s() is unknownN(R RR RAR RCR<(RtfunctionRT((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_functions cCs]d|jjdd}t||d}|sGtd|jn||j|jS(sTranslate a pseudo-class.sxpath_%s_pseudoR^R_sThe pseudo-class :%s is unknownN(tidentRR RAR RCR<(RtpseudoRT((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt xpath_pseudos cCs|j|j}t|d|}|jr>|jj}n |j}t|}|jrd|j|f}|ot|j}n|rd|}nd|j|}|j r|j j}n |j }||j |j ||S(s Translate an attribute selector.sxpath_attrib_%ss%s:%st@sattribute::*[name() = %s]( tattribute_operator_mappingtoperatorRtlower_case_attribute_namestattribRQt is_safe_namet namespaceRtlower_case_attribute_valuestvalueRCR<(RR<RgRTR tsafeRiRm((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt xpath_attrib's        cCs(|j|j}|j|d|jS(sTranslate a class selector.s@class(RCR<txpath_attrib_includest class_name(Rtclass_selectorRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt xpath_class=scCs(|j|j}|j|d|jS(sTranslate an ID selector.s@id(RCR<txpath_attrib_equalsR7(Rt id_selectorRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt xpath_hashDscCs|j}|sd}t}n$t|}|jrB|j}n|jrvd|j|f}|opt|j}n|jd|}|s|jn|S(s'Translate a type or universal selector.Rs%s:%sR(RR:Rjtlower_case_element_namesRQRkRER (RR<RRnRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt xpath_elementIs      cCs|jd|S(s;right is a child, grand-child or further descendant of lefts/descendant-or-self::*/(R$(Rtlefttright((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_descendant_combinator`scCs|jd|S(s#right is an immediate child of leftt/(R$(RRyRz((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_child_combinatordscCs)|jd|}|j|jdS(s)right is a sibling immediately after lefts/following-sibling::sposition() = 1(R$R R(RRyRzRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt xpath_direct_adjacent_combinatorhs cCs|jd|S(s1right is a sibling after left, immediately or nots/following-sibling::(R$(RRyRz((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt"xpath_indirect_adjacent_combinatornsc Csbyt|j\}}Wn$tk r?td|jnX|rS|jn|j|dkr|r|d|}n|jd|S|r| }| }n|dkrt| }n d| }|dkrd||fg}ng}|dkr|jd|n&|dkr9|r9|jd |nd j |}|r^|j|n|S( NsInvalid series: '%r'is last() - %ssposition() = %ss+%sis(position() %s) mod %s = 0sposition() >= %ssposition() < (last() %s)s and ( Rt argumentst ValueErrorR R R!RtstrtappendR$( RRCR`tlastR tatbtb_negtexpr((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_nth_child_functionus8          cCs|j||dtS(NR(RR:(RRCR`((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_nth_last_child_functionscCs4|jdkrtdn|j||dtS(NRs"*:nth-of-type() is not implementedR (RR RR%(RRCR`((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_nth_of_type_functions  cCs:|jdkrtdn|j||dtdtS(NRs"*:nth-of-type() is not implementedRR (RR RR:R%(RRCR`((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_nth_last_of_type_functions  cCs^|jdgdgfkr4td|jn|jdj}|jd|j|S(NtSTRINGtIDENTs9Expected a single string or ident for :contains(), got %riscontains(., %s)(targument_typesR RRmRR(RRCR`Rm((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_contains_functionscCs^|jdgdgfkr4td|jn|jdj}|jd|j|S(NRRs5Expected a single string or ident for :lang(), got %rislang(%s)(RR RRmRR(RRCR`Rm((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_lang_functionscCs |jdS(Nsnot(parent::*)(R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_root_pseudoscCs!|j|j|jdS(Nsposition() = 1(R!R R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_first_child_pseudos  cCs!|j|j|jdS(Nsposition() = last()(R!R R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_last_child_pseudos  cCs5|jdkrtdn|j|jdS(NRs"*:first-of-type is not implementedsposition() = 1(RR R!R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_first_of_type_pseudos   cCs5|jdkrtdn|j|jdS(NRs!*:last-of-type is not implementedsposition() = last()(RR R!R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_last_of_type_pseudos   cCs!|j|j|jdS(Ns last() = 1(R R!R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_only_child_pseudos  cCs+|jdkrtdn|jdS(NRs!*:only-of-type is not implementeds last() = 1(RR R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_only_of_type_pseudos cCs |jdS(Nsnot(*) and not(string-length())(R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_empty_pseudoscCs |jdS(s:Common implementation for pseudo-classes that never match.RZ(R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytpseudo_never_matchesscCs| s t|j||S(N(RFR(RRCR Rm((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_attrib_existss  cCs$|jd||j|f|S(Ns%s = %s(RR(RRCR Rm((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRts cCsP|r,|jd|||j|fn |jd||j|f|S(Nsnot(%s) or %s != %ss%s != %s(RR(RRCR Rm((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_attrib_differents   cCsKt|r:|jd|||jd|dfn |jd|S(Ns:%s and contains(concat(' ', normalize-space(%s), ' '), %s)R'RZ(tis_non_whitespaceRR(RRCR Rm((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRps  % c Cs:|jd|||j|||j|df|S(Ns'%s and (%s = %s or starts-with(%s, %s))R^(RR(RRCR Rm((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_attrib_dashmatchs  cCs=|r,|jd|||j|fn |jd|S(Ns%s and starts-with(%s, %s)RZ(RR(RRCR Rm((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_attrib_prefixmatch#s   cCsM|r<|jd|||t|d|j|fn |jd|S(Ns/%s and substring(%s, string-length(%s)-%s) = %siRZ(RtlenR(RRCR Rm((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_attrib_suffixmatch+s - cCs=|r,|jd|||j|fn |jd|S(Ns%s and contains(%s, %s)RZ(RR(RRCR Rm((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pytxpath_attrib_substringmatch5s   (@R RRRURft id_attributetlang_attributeR%RwRhRlRRER?R9RHt staticmethodRRCRYR]RaRdRoRsRvRxR{R}R~RR:RRRRRRRRRRRRRRRtxpath_link_pseudotxpath_visited_pseudotxpath_hover_pseudotxpath_active_pseudotxpath_focus_pseudotxpath_target_pseudotxpath_enabled_pseudotxpath_disabled_pseudotxpath_checked_pseudoRRtRRpRRRR(((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRgs               (                 tHTMLTranslatorcBsMeZdZdZedZdZdZdZdZ dZ RS(s Translator for (X)HTML documents. Has a more useful implementation of some pseudo-classes based on HTML-specific element names and attribute names, as described in the `HTML5 specification`_. It assumes no-quirks mode. The API is the same as :class:`GenericTranslator`. .. _HTML5 specification: http://www.w3.org/TR/html5/links.html#selectors :param xhtml: If false (the default), element names and attribute names are case-insensitive. tlangcCs(||_|s$t|_t|_ndS(N(txhtmlR:RwRh(RR((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRRs  cCs |jdS(Ns(@selected and name(.) = 'option') or (@checked and (name(.) = 'input' or name(.) = 'command')and (@type = 'checkbox' or @type = 'radio'))(R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRYscCsq|jdgdgfkr4td|jn|jdj}|jd|j|j|jdfS(NRRs5Expected a single string or ident for :lang(), got %risancestor-or-self::*[@lang][1][starts-with(concat(translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-'), %s)]R^(RR RRmRRRRQ(RRCR`Rm((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRascCs |jdS(NsA@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area')(R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRoscCs |jdS(Ns ( @disabled and ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' or name(.) = 'command' or name(.) = 'fieldset' or name(.) = 'optgroup' or name(.) = 'option' ) ) or ( ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' ) and ancestor::fieldset[@disabled] ) (R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRvscCs |jdS(Ns' ( @href and ( name(.) = 'a' or name(.) = 'link' or name(.) = 'area' ) ) or ( ( name(.) = 'command' or name(.) = 'fieldset' or name(.) = 'optgroup' ) and not(@disabled) ) or ( ( (name(.) = 'input' and @type != 'hidden') or name(.) = 'button' or name(.) = 'select' or name(.) = 'textarea' or name(.) = 'keygen' ) and not (@disabled or ancestor::fieldset[@disabled]) ) or ( name(.) = 'option' and not( @disabled or ancestor::optgroup[@disabled] ) ) (R(RRC((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyRs( R RRRR%RRRRRR(((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyR?s     (Rtsystretcssselect.parserRRRt version_infot basestringt _basestringtunicodeRRRAR t RuntimeErrorR tobjectRtcompiletsplitRMtmatchRjRRR(((s3/usr/lib/python2.7/site-packages/cssselect/xpath.pyt s"    1PK@N#]1R#site-packages/cssselect/__init__.pynu[# -*- coding: utf-8 -*- """ CSS Selectors based on XPath ============================ This module supports selecting XML/HTML elements based on CSS selectors. See the `CSSSelector` class for details. :copyright: (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. :license: BSD, see LICENSE for more details. """ from cssselect.parser import (parse, Selector, FunctionalPseudoElement, SelectorError, SelectorSyntaxError) from cssselect.xpath import GenericTranslator, HTMLTranslator, ExpressionError VERSION = '0.9.2' __version__ = VERSION PK@N#]' xx$site-packages/cssselect/__init__.pycnu[ ǁaWc@sZdZddlmZmZmZmZmZddlmZm Z m Z dZ e Z dS(s\ CSS Selectors based on XPath ============================ This module supports selecting XML/HTML elements based on CSS selectors. See the `CSSSelector` class for details. :copyright: (c) 2007-2012 Ian Bicking and contributors. See AUTHORS for more details. :license: BSD, see LICENSE for more details. i(tparsetSelectortFunctionalPseudoElementt SelectorErrortSelectorSyntaxError(tGenericTranslatortHTMLTranslatortExpressionErrors0.9.2N( t__doc__tcssselect.parserRRRRRtcssselect.xpathRRRtVERSIONt __version__(((s6/usr/lib/python2.7/site-packages/cssselect/__init__.pyts(PK@N#]\OE~~site-packages/easy_install.pynu["""Run the EasyInstall command""" if __name__ == '__main__': from setuptools.command.easy_install import main main() PK@N#]ܵ7kWkWsite-packages/bs4/dammit.pyonu[ o\[c@sOdZdZddlZddlmZddlZddlZddlZdZ yddl Z dZ WnGe k ryddl Z dZ Wqe k rdZ qXnXyddlZWne k rnXejdjejZejd jejZd efd YZd dd YZdddYZdS(sBBeautiful Soup bonus library: Unicode, Dammit This library converts a bytestream to Unicode through any means necessary. It is heavily based on code from Mark Pilgrim's Universal Feed Parser. It works best on XML and HTML, but it does not rewrite the XML or HTML to reflect a new encoding; that's the tree builder's job. tMITiN(tcodepoint2namecCstj|dS(Ntencoding(tcchardettdetect(ts((s./usr/lib/python2.7/site-packages/bs4/dammit.pytchardet_dammitscCstj|dS(NR(tchardetR(R((s./usr/lib/python2.7/site-packages/bs4/dammit.pyR!scCsdS(N(tNone(R((s./usr/lib/python2.7/site-packages/bs4/dammit.pyR'ss!^<\?.*encoding=['"](.*?)['"].*\?>s0<\s*meta[^>]+charset\s*=\s*["']?([^>]*?)[ /;'">]tEntitySubstitutioncBseZdZdZe\ZZZidd6dd6dd6dd 6d d 6Zej d Z ej d Z e dZ e dZe dZe edZe edZe dZRS(sASubstitute XML or HTML entities for the corresponding characters.cCsi}i}g}x\ttjD]H\}}t|}|dkrc|j||||s&([<>]|&(?!#\d+;|#x[0-9a-fA-F]+;|\w+;))s([<>&])cCs#|jj|jd}d|S(Nis&%s;(tCHARACTER_TO_HTML_ENTITYtgettgroup(tclstmatchobjtentity((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt_substitute_html_entityZscCs|j|jd}d|S(smUsed with a regular expression to substitute the appropriate XML entity for an XML special character.is&%s;(tCHARACTER_TO_XML_ENTITYR&(R'R(R)((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt_substitute_xml_entity_scCsNd}d|krBd|kr9d}|jd|}qBd}n|||S(s*Make a value into a quoted XML attribute, possibly escaping it. Most strings will be quoted using double quotes. Bob's Bar -> "Bob's Bar" If a string contains double quotes, it will be quoted using single quotes. Welcome to "my bar" -> 'Welcome to "my bar"' If a string contains both single and double quotes, the double quotes will be escaped, and the string will be quoted using double quotes. Welcome to "Bob's Bar" -> "Welcome to "Bob's bar" RRs"(treplace(tselftvaluet quote_witht replace_with((s./usr/lib/python2.7/site-packages/bs4/dammit.pytquoted_attribute_valuefs   cCs4|jj|j|}|r0|j|}n|S(s Substitute XML entities for special XML characters. :param value: A string to be substituted. The less-than sign will become <, the greater-than sign will become >, and any ampersands will become &. If you want ampersands that appear to be part of an entity definition to be left alone, use substitute_xml_containing_entities() instead. :param make_quoted_attribute: If True, then the string will be quoted, as befits an attribute value. (tAMPERSAND_OR_BRACKETtsubR,R2(R'R/tmake_quoted_attribute((s./usr/lib/python2.7/site-packages/bs4/dammit.pytsubstitute_xmls  cCs4|jj|j|}|r0|j|}n|S(sSubstitute XML entities for special XML characters. :param value: A string to be substituted. The less-than sign will become <, the greater-than sign will become >, and any ampersands that are not part of an entity defition will become &. :param make_quoted_attribute: If True, then the string will be quoted, as befits an attribute value. (tBARE_AMPERSAND_OR_BRACKETR4R,R2(R'R/R5((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt"substitute_xml_containing_entitiess  cCs|jj|j|S(sReplace certain Unicode characters with named HTML entities. This differs from data.encode(encoding, 'xmlcharrefreplace') in that the goal is to make the result more readable (to those with ASCII displays) rather than to recover from errors. There's absolutely nothing wrong with a UTF-8 string containg a LATIN SMALL LETTER E WITH ACUTE, but replacing that character with "é" will make it more readable to some people. (tCHARACTER_TO_HTML_ENTITY_RER4R*(R'R((s./usr/lib/python2.7/site-packages/bs4/dammit.pytsubstitute_htmls (t__name__t __module__t__doc__RR$tHTML_ENTITY_TO_CHARACTERR9R+RRR7R3t classmethodR*R,R2tFalseR6R8R:(((s./usr/lib/python2.7/site-packages/bs4/dammit.pyR 5s&  %tEncodingDetectorcBs\eZdZdeddZdZedZe dZ e eedZ RS(s^Suggests a number of possible encodings for a bytestring. Order of precedence: 1. Encodings you specifically tell EncodingDetector to try first (the override_encodings argument to the constructor). 2. An encoding declared within the bytestring itself, either in an XML declaration (if the bytestring is to be interpreted as an XML document), or in a tag (if the bytestring is to be interpreted as an HTML document.) 3. An encoding detected through textual analysis by chardet, cchardet, or a similar external library. 4. UTF-8. 5. Windows-1252. cCs}|p g|_|pg}tg|D]}|j^q%|_d|_||_d|_|j|\|_ |_ dS(N( toverride_encodingstsettlowertexclude_encodingsRtchardet_encodingtis_htmltdeclared_encodingtstrip_byte_order_marktmarkuptsniffed_encoding(R.RJRBRGREtx((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt__init__s (   cCsO|dk rK|j}||jkr+tS||krK|j|tSntS(N(RRDRER@taddtTrue(R.Rttried((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt_usables    ccst}x+|jD] }|j||r|VqqW|j|j|rW|jVn|jdkr|j|j|j|_n|j|j|r|jVn|j dkrt |j|_ n|j|j |r|j Vnx(dD] }|j||r|VqqWdS(s<Yield a number of encodings that might work for this markup.sutf-8s windows-1252N(sutf-8s windows-1252( RCRBRQRKRHRtfind_declared_encodingRJRGRFR(R.RPte((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt encodingss$      cCs"d}t|tr||fSt|dkrg|d dkrg|dd!dkrgd}|d}nt|dkr|d dkr|dd!dkrd}|d}ni|d d krd }|d}nF|d d krd }|d}n#|d d krd}|d}n||fS(sMIf a byte-order mark is present, strip it and return the encoding it implies.iisssutf-16bessutf-16leissutf-8ssutf-32bessutf-32leN(Rt isinstancetunicodetlen(R'tdataR((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRIs* " "    cCs|rt|}}n%d}tdtt|d}d}tj|d|}| r~|r~tj|d|}n|dk r|jdjdd}n|r|j SdS( sGiven a document, tries to find its declared encoding. An XML encoding is declared at the beginning of the document. An HTML encoding is declared in a tag, hopefully near the beginning of the document. iig?tendpositasciiR-N( RWtmaxtintRtxml_encoding_retsearcht html_meta_retgroupstdecodeRD(R'RJRGtsearch_entire_documentt xml_endpost html_endposRHtdeclared_encoding_match((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRR+s    N( R;R<R=RR@RMRQtpropertyRTR?RIRR(((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRAs !t UnicodeDammitcBseZdZidd6dd6ZdddgZgdegdZd Zd d Z d d Z e d Z dZ dZi dd6dd6dd6dd6dd6d d 6d d#6d d&6d d)6d d,6dd/6dd26dd56d6d76dd:6d6d;6d6d<6dd?6ddB6ddE6ddH6ddK6ddN6ddQ6ddT6ddW6ddZ6dd]6dd`6d6da6ddd6ddg6Zidhd6dd6did6djd6dkd6dld 6dmd#6dnd&6dod)6dpd,6dqd/6drd26dsd56d6d76dtd:6d6d;6d6d<6dud?6dudB6dvdE6dvdH6dwdK6dxdN6dydQ6dzdT6d{dW6d|dZ6d}d]6d~d`6d6da6ddd6ddg6dd6dd6dd6dd6dd6dd6dd6dqd6dd6dfd6dd6dd6dd6dd6dd6dxd6dd6dd6dd6dd6d d6dd6dd6dwd6did6dd6dd6dd6dd6dd6dd6d6d6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dwd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6Zizd d 6d d 6d d6dd6dd6dd6dd6dd6dd6dd6dd6dd 6d!d"6d#d$6d%d&6d'd(6d)d*6d+d,6d-d.6d/d06d1d26d3d46d5d66d7d86d9d:6d;d<6d=d>6d?d@6dAdB6dCdD6dEdF6dGdH6dIdJ6dKdL6dMdN6dOdP6dQdR6dSdT6dUdV6dWdX6dYdZ6d[d\6d]d^6d_d`6dadb6dcdd6dedf6dgdh6didj6dkdl6dmdn6dodp6dqdr6dsdt6dudv6dwdx6dydz6d{d|6d}d~6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6Zd!d"d#gZeddZeddZedddZRS($sA class for detecting the encoding of a *ML document and converting it to a Unicode string. If the source encoding is windows-1252, can replace MS smart quotes with their HTML or XML equivalents.s mac-romant macintoshs shift-jissx-sjiss windows-1252s iso-8859-1s iso-8859-2cCsn||_g|_t|_||_tjt|_t |||||_ t |t si|dkr||_ t ||_d|_dS|j j |_ d}x?|j jD]1}|j j }|j|}|dk rPqqW|sOxa|j jD]P}|dkr|j|d}n|dk r|jjdt|_PqqWn||_|sjd|_ndS(NR RZR-sSSome characters could not be decoded, and were replaced with REPLACEMENT CHARACTER.(tsmart_quotes_tottried_encodingsR@tcontains_replacement_charactersRGtloggingt getLoggerR;tlogRAtdetectorRURVRJtunicode_markupRtoriginal_encodingRTt _convert_fromtwarningRO(R.RJRBRiRGREtuR((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRMXs>              cCs|jd}|jdkr9|jj|j}n|jj|}t|tkr|jdkrdj|djdj}qdj|djdj}n |j}|S(s[Changes a MS smart quote character to an XML or HTML entity, or an ASCII character.iRZtxmls&#xt;Ri(R&RitMS_CHARS_TO_ASCIIR%tencodetMS_CHARSttypettuple(R.tmatchtorigR4((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt _sub_ms_chars'' tstrictcCs|j|}| s+||f|jkr/dS|jj||f|j}|jdk r||jkrd}tj|}|j |j |}ny+|j |||}||_||_ Wnt k r}dSX|jS(Ns([-])(t find_codecRjRRRJRitENCODINGS_WITH_SMART_QUOTESRRR4R~t _to_unicodeRqt Exception(R.tproposedterrorsRJtsmart_quotes_retsmart_quotes_compiledRtRS((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRrs"   cCst|||S(sGiven a string and its encoding, decodes the string into Unicode. %encoding is a string recognized by encodings.aliases(RV(R.RXRR((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRscCs|js dS|jjS(N(RGRRoRH(R.((s./usr/lib/python2.7/site-packages/bs4/dammit.pytdeclared_html_encodings cCs|j|jj||pu|r?|j|jddpu|r`|j|jddpu|rr|jpu|}|r|jSdS(Nt-R t_(t_codectCHARSET_ALIASESR%R-RDR(R.tcharsetR/((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRs!! cCsE|s |Sd}ytj||}Wnttfk r@nX|S(N(RtcodecsRt LookupErrort ValueError(R.Rtcodec((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRs  teurot20ACst stsbquot201Astfnoft192stbdquot201Esthellipt2026stdaggert2020stDaggert2021stcirct2C6stpermilt2030stScaront160stlsaquot2039stOEligt152st?ss#x17Dt17Dssstlsquot2018strsquot2019stldquot201Cstrdquot201Dstbullt2022stndasht2013stmdasht2014sttildet2DCsttradet2122stscaront161strsaquot203Astoeligt153sss#x17Et17EstYumlR stEURt,tfs,,s...t+s++t^t%tSR!tOEtZRRt*Rs--t~s(TM)RR#toetztYst!stcstGBPst$stYENst|sss..sss(th)ss<>ss1/4ss1/2ss3/4sstAsssssstAEstCstEsssstIsssstDstNstOssssssstUssssstbstBstasssssstaessRSsssstissssstnsssssst/sssssstyssss€is‚isƒis„is…is†is‡isˆis‰isŠis‹isŒisŽis‘is’is“is”is•is–is—is˜is™isšis›isœisžisŸis is¡is¢is£is¤is¥is¦is§is¨is©isªis«is¬is­is®is¯is°is±is²is³is´isµis¶is·is¸is¹isºis»is¼is½is¾is¿isÀisÁisÂisÃisÄisÅisÆisÇisÈisÉisÊisËisÌisÍisÎisÏisÐisÑisÒisÓisÔisÕisÖis×isØisÙisÚisÛisÜisÝisÞisßisàiisâisãisäisåisæisçisèiséisêisëisìisíisîisïisðisñisòisóisôisõisöis÷isøisùisúisûisüisýisþiiiiiiitutf8c Cs|jddjd kr-tdn|jdkrNtdng}d }d }x|t|krd||}t|tst|}n||jkr||jkrx|j D]5\}} } ||kr|| kr|| 7}PqqWqc|d krW||j krW|j |||!|j |j ||d 7}|}qc|d 7}qcW|d kru|S|j ||d j |S(sFix characters from one encoding embedded in some other encoding. Currently the only situation supported is Windows-1252 (or its subset ISO-8859-1), embedded in UTF-8. The input must be a bytestring. If you've already converted the document to Unicode, you're too late. The output is a bytestring in which `embedded_encoding` characters have been converted to their `main_encoding` equivalents. RRs windows-1252t windows_1252sPWindows-1252 and ISO-8859-1 are the only currently supported embedded encodings.Rsutf-8s4UTF-8 is the only currently supported main encoding.iiiR (s windows-1252R(Rsutf-8( R-RDtNotImplementedErrorRWRUR\tordtFIRST_MULTIBYTE_MARKERtLAST_MULTIBYTE_MARKERtMULTIBYTE_MARKERS_AND_SIZEStWINDOWS_1252_TO_UTF8RR( R'tin_bytest main_encodingtembedded_encodingt byte_chunkst chunk_starttpostbytetstarttendtsize((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt detwingle s<         N(RR(RR(RR(RR(RR(RR(RR(RR(RR(RR(RR(RR(s#x17DR(RR(RR(RR(RR(RR(RR(RR(RR(RR(RR(RR(RR(s#x17ER(RR (RR(iii(iii(iii(R;R<R=RRRR@RMR~RrRRfRRRRyRwRRRRR?R(((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRgEsd   1        (((R=t __license__RthtmlentitydefsRRRltstringRt chardet_typeRRt ImportErrorRt iconv_codecRRxRR]R_tobjectR RARg(((s./usr/lib/python2.7/site-packages/bs4/dammit.pyts6           PK@N#]ȧnIIsite-packages/bs4/__init__.pyonu[ qap[c@s|dZdZdZdZdZdgZddlZddlZddlZddl Z ddl Z dd l m Z m Z dd lmZdd lmZmZmZmZmZmZmZmZmZmZmZd d kdefdYZeZeZdefdYZde fdYZ!de"fdYZ#e$dkrxddlZeej%Z&e&j'GHndS(sHBeautiful Soup Elixir and Tonic "The Screen-Scraper's Friend" http://www.crummy.com/software/BeautifulSoup/ Beautiful Soup uses a pluggable XML or HTML parser to parse a (possibly invalid) document into a tree representation. Beautiful Soup provides methods and Pythonic idioms that make it easy to navigate, search, and modify the parse tree. Beautiful Soup works with Python 2.7 and up. It works better if lxml and/or html5lib is installed. For more than you ever wanted to know about Beautiful Soup, see the documentation: http://www.crummy.com/software/BeautifulSoup/bs4/doc/ s*Leonard Richardson (leonardr@segfault.org)s4.6.3s*Copyright (c) 2004-2018 Leonard RichardsontMITt BeautifulSoupiNi(tbuilder_registrytParserRejectedMarkup(t UnicodeDammit( tCDatatCommenttDEFAULT_OUTPUT_ENCODINGt DeclarationtDoctypetNavigableStringt PageElementtProcessingInstructiont ResultSett SoupStrainertTags`You are trying to run the Python 2 version of Beautiful Soup under Python 3. This will not work.suYou need to convert the code, either by installing it (`python setup.py install`) or by running 2to3 (`2to3 -w bs4`).cBseZdZdZddgZdZdZdddddddZdZ d Z e d Z d Z d Zddid ZedZdZdZdZdZedZdddZdedZdZddZdZeeddZRS(s This class defines the basic interface called by the tree builders. These methods will be called by the parser: reset() feed(markup) The tree builder may call these methods from its feed() implementation: handle_starttag(name, attrs) # See note about return value handle_endtag(name) handle_data(data) # Appends to the current data node endData(containerClass=NavigableString) # Ends the current data node No matter how complicated the underlying parser is, you should be able to build a tree using 'start tag' events, 'end tag' events, 'data' events, and "done with data" events. If you encounter an empty-element tag (aka a self-closing tag, like HTML's
tag), call handle_starttag and then handle_endtag. u [document]thtmltfasts sNo parser was explicitly specified, so I'm using the best available %(markup_type)s parser for this system ("%(parser)s"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently. The code that caused this warning is on line %(line_number)s of the file %(filename)s. To get rid of this warning, pass the additional argument 'features="%(parser)s"' to the BeautifulSoup constructor. tc sdkrtjdndkr?d=tjdndkrbd=tjdndkrd=tjdnd krd =tjd nfd }|p|d d }|p|dd}|r t|tr tjdd)}ntdkrCjj} td| n|d)kr|} t|t rp|g}n|d)kst|dkr|j }nt j |} | d)krt ddj|n| }| |jkp| |jks|jr d} nd} d)} ytjd} Wntk r<nX| rX| j}| j}ntj}d}|jd}|r|j}|jd*r|d }qn|rtd|d|d|jd| }tj|j|d d!qqn||_|j|_|j|_||j_||_ t!|d"rH|j"}nt|d#krAt|t#rud$|kst|trAd%|krAt|trt$j%j& r|j'd&}n|}t(}yt$j%j)|}Wnt*k r}nX|r1t|tr|j'd&}ntjd'|n|j+|nxh|jj,||d(|D]K\|_-|_.|_/|_0|j1y|j2PWq]t3k rq]Xq]Wd)|_-d)|j_d)S(+s_Constructor. :param markup: A string or a file-like object representing markup to be parsed. :param features: Desirable features of the parser to be used. This may be the name of a specific parser ("lxml", "lxml-xml", "html.parser", or "html5lib") or it may be the type of markup to be used ("html", "html5", "xml"). It's recommended that you name a specific parser, so that Beautiful Soup gives you the same results across platforms and virtual environments. :param builder: A specific TreeBuilder to use instead of looking one up based on `features`. You shouldn't need to use this. :param parse_only: A SoupStrainer. Only parts of the document matching the SoupStrainer will be considered. This is useful when parsing part of a document that would otherwise be too large to fit into memory. :param from_encoding: A string indicating the encoding of the document to be parsed. Pass this in if Beautiful Soup is guessing wrongly about the document's encoding. :param exclude_encodings: A list of strings indicating encodings known to be wrong. Pass this in if you don't know the document's encoding but you know Beautiful Soup's guess is wrong. :param kwargs: For backwards compatibility purposes, the constructor accepts certain keyword arguments used in Beautiful Soup 3. None of these arguments do anything in Beautiful Soup 4 and there's no need to actually pass keyword arguments into the constructor. tconvertEntitiessBS4 does not respect the convertEntities argument to the BeautifulSoup constructor. Entities are always converted to Unicode characters.t markupMassagesBS4 does not respect the markupMassage argument to the BeautifulSoup constructor. The tree builder is responsible for any necessary markup massage.t smartQuotesTosBS4 does not respect the smartQuotesTo argument to the BeautifulSoup constructor. Smart quotes are always converted to Unicode characters.tselfClosingTagssBS4 does not respect the selfClosingTags argument to the BeautifulSoup constructor. The tree builder is responsible for understanding self-closing tags.tisHTMLsBS4 does not respect the isHTML argument to the BeautifulSoup constructor. Suggest you use features='lxml' for HTML and features='lxml-xml' for XML.cs<|kr8tjd||f|}|=|SdS(NsLThe "%s" argument to the BeautifulSoup constructor has been renamed to "%s."(twarningstwarntNone(told_nametnew_nametvalue(tkwargs(s0/usr/lib/python2.7/site-packages/bs4/__init__.pytdeprecated_arguments  tparseOnlyTheset parse_onlyt fromEncodingt from_encodingslYou provided Unicode markup but also provided a value for from_encoding. Your from_encoding will be ignored.is2__init__() got an unexpected keyword argument '%s'sjCouldn't find a tree builder with the features you requested: %s. Do you need to install a parser library?t,tXMLtHTMLit__file__s.pycs.pyoitfilenamet line_numbertparsert markup_typet stacklevelitreaditFssutf-8treplaces"%s" looks like a URL. Beautiful Soup is not an HTTP client. You should probably use an HTTP client like requests to get the document behind the URL, and feed that document to Beautiful Soup.(shttp:shttps:(uhttp:uhttps:(R1RNR2tanytdecodeRR(RXtspacetcant_start_withtdecoded_markup((RXs0/usr/lib/python2.7/site-packages/bs4/__init__.pyRV7s   cCsT|jj|jj|j|jx#|jj|jkrO|jq-WdS(N( RJR\tfeedRXtendDatat currentTagtnamet ROOT_TAG_NAMEtpopTag(R^((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyR]Ss   cCsgtj|||j|jd|_|jjg|_d|_g|_ g|_ |j |dS(Ni( RRjRJRthiddenR\t current_dataRR}ttagStacktpreserve_whitespace_tag_stacktpushTag(R^((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyR\]s      cKs)|j|td|j||||S(s+Create a new tag associated with this soup.N(tupdateRRRJ(R^R~t namespacetnsprefixtattrstkwattrs((s0/usr/lib/python2.7/site-packages/bs4/__init__.pytnew_taggs cCs ||S(s7Create a new NavigableString associated with this soup.((R^tstsubclass((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyt new_stringlscCstddS(Ns4BeautifulSoup objects don't support insert_before().(tNotImplementedError(R^t successor((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyt insert_beforepscCstddS(Ns3BeautifulSoup objects don't support insert_after().(R(R^R((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyt insert_aftersscCs^|jj}|jr;||jdkr;|jjn|jrW|jd|_n|jS(Ni(RR5RR}(R^ttag((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyRvs  cCsk|jr|jjj|n|jj||jd|_|j|jjkrg|jj|ndS(Ni(R}tcontentstappendRR~RJtpreserve_whitespace_tagsR(R^R((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyRs  cCs|jrdj|j}|js{t}x'|D]}||jkr1t}Pq1q1W|r{d|krod}qxd}q{ng|_|jrt|jdkr|jj s|jj | rdS||}|j |ndS(Nus Rqi( RR;RtTruet ASCII_SPACESRSR!R3Rttexttsearchtobject_was_parsed(R^tcontainerClassRt strippabletito((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyR|s&         c Cs|p |j}|p|j}d}}}t|trk|j}|j}|j}|sk|j}qkn|j |||||||_|j j ||jrt |j d}xG|dkr|j ||krPn|d8}qWt d||f|dkr|}d}n|j |d}}|t |j dkr^|j}d}n|j |d}}||_|r||_n||_|r||_n||_|r||_n||_|r||_qndS(s Add an object to the parse tree.iis[Error building tree: supposedly %r was inserted into %r after the fact, but I don't see it!N(R}t_most_recent_elementRR1Rt next_elementt next_siblingtprevious_siblingtprevious_elementtsetupRRR3RA( R^Rtparenttmost_recent_elementRRRRtindex((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyRsR                cCs||jkrdSd}t|j}xnt|dddD]V}|j|}||jkr||jkr|r|j}nPn|j}q?W|S(sPops the tag stack up to and including the most recent instance of the given tag. If inclusivePop is false, pops the tag stack up to but *not* including the most recent instqance of the given tag.Niii(RRR3RtrangeR~RtR(R^R~Rt inclusivePoptmost_recently_poppedt stack_sizeRtt((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyt _popToTags c Cs|j|jrNt|jdkrN|jjsJ|jj|| rNdSt||j|||||j |j }|dkr|S|j r||j _ n||_ |j ||S(sPush a start tag on to the stack. If this method returns None, the tag was rejected by the SoupStrainer. You should proceed as if the tag had not occurred in the document. For instance, if this was a self-closing tag, don't call handle_endtag. iN( R|R!R3RRt search_tagRRRJR}RRR(R^R~RRRR((s0/usr/lib/python2.7/site-packages/bs4/__init__.pythandle_starttags      cCs|j|j||dS(N(R|R(R^R~R((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyt handle_endtags cCs|jj|dS(N(RR(R^tdata((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyt handle_datastminimalcCsp|jr5d}|dkr(d|}nd|}nd}|sJd}nd}|tt|j|||S(slReturns a string or Unicode representation of this document. To get Unicode, pass None for encoding.Rs encoding="%s"u uiN(R>RtsuperRRw(R^t pretty_printteventual_encodingt formattert encoding_partRtt indent_level((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyRws     N( t__name__t __module__t__doc__RR8RRIRRjRmRpt staticmethodRVR]R\RR RRRRRR|RRRRRRRSRRw(((s0/usr/lib/python2.7/site-packages/bs4/__init__.pyR8s6        9   tBeautifulStoneSoupcBseZdZdZRS(s&Deprecated interface to an XML parser.cOs4d|ds2      L    PK@N#]ܵ7kWkWsite-packages/bs4/dammit.pycnu[ o\[c@sOdZdZddlZddlmZddlZddlZddlZdZ yddl Z dZ WnGe k ryddl Z dZ Wqe k rdZ qXnXyddlZWne k rnXejdjejZejd jejZd efd YZd dd YZdddYZdS(sBBeautiful Soup bonus library: Unicode, Dammit This library converts a bytestream to Unicode through any means necessary. It is heavily based on code from Mark Pilgrim's Universal Feed Parser. It works best on XML and HTML, but it does not rewrite the XML or HTML to reflect a new encoding; that's the tree builder's job. tMITiN(tcodepoint2namecCstj|dS(Ntencoding(tcchardettdetect(ts((s./usr/lib/python2.7/site-packages/bs4/dammit.pytchardet_dammitscCstj|dS(NR(tchardetR(R((s./usr/lib/python2.7/site-packages/bs4/dammit.pyR!scCsdS(N(tNone(R((s./usr/lib/python2.7/site-packages/bs4/dammit.pyR'ss!^<\?.*encoding=['"](.*?)['"].*\?>s0<\s*meta[^>]+charset\s*=\s*["']?([^>]*?)[ /;'">]tEntitySubstitutioncBseZdZdZe\ZZZidd6dd6dd6dd 6d d 6Zej d Z ej d Z e dZ e dZe dZe edZe edZe dZRS(sASubstitute XML or HTML entities for the corresponding characters.cCsi}i}g}x\ttjD]H\}}t|}|dkrc|j||||s&([<>]|&(?!#\d+;|#x[0-9a-fA-F]+;|\w+;))s([<>&])cCs#|jj|jd}d|S(Nis&%s;(tCHARACTER_TO_HTML_ENTITYtgettgroup(tclstmatchobjtentity((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt_substitute_html_entityZscCs|j|jd}d|S(smUsed with a regular expression to substitute the appropriate XML entity for an XML special character.is&%s;(tCHARACTER_TO_XML_ENTITYR&(R'R(R)((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt_substitute_xml_entity_scCsNd}d|krBd|kr9d}|jd|}qBd}n|||S(s*Make a value into a quoted XML attribute, possibly escaping it. Most strings will be quoted using double quotes. Bob's Bar -> "Bob's Bar" If a string contains double quotes, it will be quoted using single quotes. Welcome to "my bar" -> 'Welcome to "my bar"' If a string contains both single and double quotes, the double quotes will be escaped, and the string will be quoted using double quotes. Welcome to "Bob's Bar" -> "Welcome to "Bob's bar" RRs"(treplace(tselftvaluet quote_witht replace_with((s./usr/lib/python2.7/site-packages/bs4/dammit.pytquoted_attribute_valuefs   cCs4|jj|j|}|r0|j|}n|S(s Substitute XML entities for special XML characters. :param value: A string to be substituted. The less-than sign will become <, the greater-than sign will become >, and any ampersands will become &. If you want ampersands that appear to be part of an entity definition to be left alone, use substitute_xml_containing_entities() instead. :param make_quoted_attribute: If True, then the string will be quoted, as befits an attribute value. (tAMPERSAND_OR_BRACKETtsubR,R2(R'R/tmake_quoted_attribute((s./usr/lib/python2.7/site-packages/bs4/dammit.pytsubstitute_xmls  cCs4|jj|j|}|r0|j|}n|S(sSubstitute XML entities for special XML characters. :param value: A string to be substituted. The less-than sign will become <, the greater-than sign will become >, and any ampersands that are not part of an entity defition will become &. :param make_quoted_attribute: If True, then the string will be quoted, as befits an attribute value. (tBARE_AMPERSAND_OR_BRACKETR4R,R2(R'R/R5((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt"substitute_xml_containing_entitiess  cCs|jj|j|S(sReplace certain Unicode characters with named HTML entities. This differs from data.encode(encoding, 'xmlcharrefreplace') in that the goal is to make the result more readable (to those with ASCII displays) rather than to recover from errors. There's absolutely nothing wrong with a UTF-8 string containg a LATIN SMALL LETTER E WITH ACUTE, but replacing that character with "é" will make it more readable to some people. (tCHARACTER_TO_HTML_ENTITY_RER4R*(R'R((s./usr/lib/python2.7/site-packages/bs4/dammit.pytsubstitute_htmls (t__name__t __module__t__doc__RR$tHTML_ENTITY_TO_CHARACTERR9R+RRR7R3t classmethodR*R,R2tFalseR6R8R:(((s./usr/lib/python2.7/site-packages/bs4/dammit.pyR 5s&  %tEncodingDetectorcBs\eZdZdeddZdZedZe dZ e eedZ RS(s^Suggests a number of possible encodings for a bytestring. Order of precedence: 1. Encodings you specifically tell EncodingDetector to try first (the override_encodings argument to the constructor). 2. An encoding declared within the bytestring itself, either in an XML declaration (if the bytestring is to be interpreted as an XML document), or in a tag (if the bytestring is to be interpreted as an HTML document.) 3. An encoding detected through textual analysis by chardet, cchardet, or a similar external library. 4. UTF-8. 5. Windows-1252. cCs}|p g|_|pg}tg|D]}|j^q%|_d|_||_d|_|j|\|_ |_ dS(N( toverride_encodingstsettlowertexclude_encodingsRtchardet_encodingtis_htmltdeclared_encodingtstrip_byte_order_marktmarkuptsniffed_encoding(R.RJRBRGREtx((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt__init__s (   cCsO|dk rK|j}||jkr+tS||krK|j|tSntS(N(RRDRER@taddtTrue(R.Rttried((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt_usables    ccst}x+|jD] }|j||r|VqqW|j|j|rW|jVn|jdkr|j|j|j|_n|j|j|r|jVn|j dkrt |j|_ n|j|j |r|j Vnx(dD] }|j||r|VqqWdS(s<Yield a number of encodings that might work for this markup.sutf-8s windows-1252N(sutf-8s windows-1252( RCRBRQRKRHRtfind_declared_encodingRJRGRFR(R.RPte((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt encodingss$      cCs"d}t|tr||fSt|dkrg|d dkrg|dd!dkrgd}|d}nt|dkr|d dkr|dd!dkrd}|d}ni|d d krd }|d}nF|d d krd }|d}n#|d d krd}|d}n||fS(sMIf a byte-order mark is present, strip it and return the encoding it implies.iisssutf-16bessutf-16leissutf-8ssutf-32bessutf-32leN(Rt isinstancetunicodetlen(R'tdataR((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRIs* " "    cCs|rt|}}n%d}tdtt|d}d}tj|d|}| r~|r~tj|d|}n|dk r|jdjdd}n|r|j SdS( sGiven a document, tries to find its declared encoding. An XML encoding is declared at the beginning of the document. An HTML encoding is declared in a tag, hopefully near the beginning of the document. iig?tendpositasciiR-N( RWtmaxtintRtxml_encoding_retsearcht html_meta_retgroupstdecodeRD(R'RJRGtsearch_entire_documentt xml_endpost html_endposRHtdeclared_encoding_match((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRR+s    N( R;R<R=RR@RMRQtpropertyRTR?RIRR(((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRAs !t UnicodeDammitcBseZdZidd6dd6ZdddgZgdegdZd Zd d Z d d Z e d Z dZ dZi dd6dd6dd6dd6dd6d d 6d d#6d d&6d d)6d d,6dd/6dd26dd56d6d76dd:6d6d;6d6d<6dd?6ddB6ddE6ddH6ddK6ddN6ddQ6ddT6ddW6ddZ6dd]6dd`6d6da6ddd6ddg6Zidhd6dd6did6djd6dkd6dld 6dmd#6dnd&6dod)6dpd,6dqd/6drd26dsd56d6d76dtd:6d6d;6d6d<6dud?6dudB6dvdE6dvdH6dwdK6dxdN6dydQ6dzdT6d{dW6d|dZ6d}d]6d~d`6d6da6ddd6ddg6dd6dd6dd6dd6dd6dd6dd6dqd6dd6dfd6dd6dd6dd6dd6dd6dxd6dd6dd6dd6dd6d d6dd6dd6dwd6did6dd6dd6dd6dd6dd6dd6d6d6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dwd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6Zizd d 6d d 6d d6dd6dd6dd6dd6dd6dd6dd6dd6dd 6d!d"6d#d$6d%d&6d'd(6d)d*6d+d,6d-d.6d/d06d1d26d3d46d5d66d7d86d9d:6d;d<6d=d>6d?d@6dAdB6dCdD6dEdF6dGdH6dIdJ6dKdL6dMdN6dOdP6dQdR6dSdT6dUdV6dWdX6dYdZ6d[d\6d]d^6d_d`6dadb6dcdd6dedf6dgdh6didj6dkdl6dmdn6dodp6dqdr6dsdt6dudv6dwdx6dydz6d{d|6d}d~6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6dd6Zd!d"d#gZeddZeddZedddZRS($sA class for detecting the encoding of a *ML document and converting it to a Unicode string. If the source encoding is windows-1252, can replace MS smart quotes with their HTML or XML equivalents.s mac-romant macintoshs shift-jissx-sjiss windows-1252s iso-8859-1s iso-8859-2cCsn||_g|_t|_||_tjt|_t |||||_ t |t si|dkr||_ t ||_d|_dS|j j |_ d}x?|j jD]1}|j j }|j|}|dk rPqqW|sOxa|j jD]P}|dkr|j|d}n|dk r|jjdt|_PqqWn||_|sjd|_ndS(NR RZR-sSSome characters could not be decoded, and were replaced with REPLACEMENT CHARACTER.(tsmart_quotes_tottried_encodingsR@tcontains_replacement_charactersRGtloggingt getLoggerR;tlogRAtdetectorRURVRJtunicode_markupRtoriginal_encodingRTt _convert_fromtwarningRO(R.RJRBRiRGREtuR((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRMXs>              cCs|jd}|jdkr9|jj|j}n|jj|}t|tkr|jdkrdj|djdj}qdj|djdj}n |j}|S(s[Changes a MS smart quote character to an XML or HTML entity, or an ASCII character.iRZtxmls&#xt;Ri(R&RitMS_CHARS_TO_ASCIIR%tencodetMS_CHARSttypettuple(R.tmatchtorigR4((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt _sub_ms_chars'' tstrictcCs|j|}| s+||f|jkr/dS|jj||f|j}|jdk r||jkrd}tj|}|j |j |}ny+|j |||}||_||_ Wnt k r}dSX|jS(Ns([-])(t find_codecRjRRRJRitENCODINGS_WITH_SMART_QUOTESRRR4R~t _to_unicodeRqt Exception(R.tproposedterrorsRJtsmart_quotes_retsmart_quotes_compiledRtRS((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRrs"   cCst|||S(sGiven a string and its encoding, decodes the string into Unicode. %encoding is a string recognized by encodings.aliases(RV(R.RXRR((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRscCs|js dS|jjS(N(RGRRoRH(R.((s./usr/lib/python2.7/site-packages/bs4/dammit.pytdeclared_html_encodings cCs|j|jj||pu|r?|j|jddpu|r`|j|jddpu|rr|jpu|}|r|jSdS(Nt-R t_(t_codectCHARSET_ALIASESR%R-RDR(R.tcharsetR/((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRs!! cCsE|s |Sd}ytj||}Wnttfk r@nX|S(N(RtcodecsRt LookupErrort ValueError(R.Rtcodec((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRs  teurot20ACst stsbquot201Astfnoft192stbdquot201Esthellipt2026stdaggert2020stDaggert2021stcirct2C6stpermilt2030stScaront160stlsaquot2039stOEligt152st?ss#x17Dt17Dssstlsquot2018strsquot2019stldquot201Cstrdquot201Dstbullt2022stndasht2013stmdasht2014sttildet2DCsttradet2122stscaront161strsaquot203Astoeligt153sss#x17Et17EstYumlR stEURt,tfs,,s...t+s++t^t%tSR!tOEtZRRt*Rs--t~s(TM)RR#toetztYst!stcstGBPst$stYENst|sss..sss(th)ss<>ss1/4ss1/2ss3/4sstAsssssstAEstCstEsssstIsssstDstNstOssssssstUssssstbstBstasssssstaessRSsssstissssstnsssssst/sssssstyssss€is‚isƒis„is…is†is‡isˆis‰isŠis‹isŒisŽis‘is’is“is”is•is–is—is˜is™isšis›isœisžisŸis is¡is¢is£is¤is¥is¦is§is¨is©isªis«is¬is­is®is¯is°is±is²is³is´isµis¶is·is¸is¹isºis»is¼is½is¾is¿isÀisÁisÂisÃisÄisÅisÆisÇisÈisÉisÊisËisÌisÍisÎisÏisÐisÑisÒisÓisÔisÕisÖis×isØisÙisÚisÛisÜisÝisÞisßisàiisâisãisäisåisæisçisèiséisêisëisìisíisîisïisðisñisòisóisôisõisöis÷isøisùisúisûisüisýisþiiiiiiitutf8c Cs|jddjd kr-tdn|jdkrNtdng}d }d }x|t|krd||}t|tst|}n||jkr||jkrx|j D]5\}} } ||kr|| kr|| 7}PqqWqc|d krW||j krW|j |||!|j |j ||d 7}|}qc|d 7}qcW|d kru|S|j ||d j |S(sFix characters from one encoding embedded in some other encoding. Currently the only situation supported is Windows-1252 (or its subset ISO-8859-1), embedded in UTF-8. The input must be a bytestring. If you've already converted the document to Unicode, you're too late. The output is a bytestring in which `embedded_encoding` characters have been converted to their `main_encoding` equivalents. RRs windows-1252t windows_1252sPWindows-1252 and ISO-8859-1 are the only currently supported embedded encodings.Rsutf-8s4UTF-8 is the only currently supported main encoding.iiiR (s windows-1252R(Rsutf-8( R-RDtNotImplementedErrorRWRUR\tordtFIRST_MULTIBYTE_MARKERtLAST_MULTIBYTE_MARKERtMULTIBYTE_MARKERS_AND_SIZEStWINDOWS_1252_TO_UTF8RR( R'tin_bytest main_encodingtembedded_encodingt byte_chunkst chunk_starttpostbytetstarttendtsize((s./usr/lib/python2.7/site-packages/bs4/dammit.pyt detwingle s<         N(RR(RR(RR(RR(RR(RR(RR(RR(RR(RR(RR(RR(s#x17DR(RR(RR(RR(RR(RR(RR(RR(RR(RR(RR(RR(RR(s#x17ER(RR (RR(iii(iii(iii(R;R<R=RRRR@RMR~RrRRfRRRRyRwRRRRR?R(((s./usr/lib/python2.7/site-packages/bs4/dammit.pyRgEsd   1        (((R=t __license__RthtmlentitydefsRRRltstringRt chardet_typeRRt ImportErrorRt iconv_codecRRxRR]R_tobjectR RARg(((s./usr/lib/python2.7/site-packages/bs4/dammit.pyts6           PK@N#]Dsite-packages/bs4/testing.pycnu[ \[c@sdZdZddlZddlZddlZddlZddlmZddlmZddl m Z m Z m Z m Z mZddlmZeZdejfd YZd efd YZd efd YZdefdYZdZdS(sHelper classes for tests.tMITiN(tTestCase(t BeautifulSoup(tCharsetMetaAttributeValuetCommenttContentMetaAttributeValuetDoctypet SoupStrainer(tHTMLParserTreeBuildertSoupTestcBs>eZedZdZdZddZdZRS(cCstS(N(tdefault_builder(tself((s//usr/lib/python2.7/site-packages/bs4/testing.pyR scKs(|jd|j}t|d||S(s*Build a Beautiful Soup object from markup.tbuilder(tpopR R(R tmarkuptkwargsR ((s//usr/lib/python2.7/site-packages/bs4/testing.pytsoup scCs|jj|S(s[Turn an HTML fragment into a document. The details depend on the builder. (R ttest_fragment_to_document(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyt document_for%scCsS|j}t|d|}|dkr0|}n|j|j|j|dS(NR (R RtNonet assertEqualtdecodeR(R tto_parsetcompare_parsed_toR tobj((s//usr/lib/python2.7/site-packages/bs4/testing.pytassertSoupEquals,s    cCsSd}xF|jD];}|rE|j||j|j||jn|}qWdS(syEnsure that next_element and previous_element are properly set for all descendants of the given element. N(Rt descendantsRt next_elementtprevious_element(R telementtearlierte((s//usr/lib/python2.7/site-packages/bs4/testing.pytassertConnectedness4s N( t__name__t __module__tpropertyR RRRRR (((s//usr/lib/python2.7/site-packages/bs4/testing.pyR s    tHTMLTreeBuilderSmokeTestcBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!d Z"d!Z#d"Z$d#Zd$Z%d%Z&d&Z'd'Z(d(Z)d)Z*d*Z+d+Z,d,Z-d-Z.d.Z/d/Z0d0Z1d1Z2d2Z3d3Z4d4Z5d5Z6d6Z7d7Z8d8Z9RS(9sCA basic test of a treebuilder's competence. Any HTML treebuilder, present or future, should be able to pass these tests. With invalid markup, there's room for interpretation, and different parsers can handle it differently. But with the markup in these tests, there's not much room for interpretation. cCs|xuddddddddd d d d d dddddgD]7}|jd}|j|}|jt|jq=WdS(smVerify that all HTML4 and HTML5 empty element (aka void element) tags are handled correctly. tareatbasetbrtcoltembedthrtimgtinputtkeygentlinktmenuitemtmetatparamtsourcettracktwbrtspacertframetN(Rtnew_tagRtTruetis_empty_element(R tnameRR8((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_empty_element_tagsIs 0cCsc|jd}tj|d}tj|}|j|jt|j|j|jdS(Ns fooi(RtpickletdumpstloadsRt __class__RR(R ttreetdumpedtloaded((s//usr/lib/python2.7/site-packages/bs4/testing.pyt!test_pickle_and_unpickle_identityUs cCs|j|\}}|jd}|j|jt|j|||jt|t| ||j|jjdddS(s8Assert that a given doctype string is handled correctly.itfooN(t_document_with_doctypetcontentsRR@Rtstrtlentp(R tdoctype_fragmentt doctype_strRtdoctype((s//usr/lib/python2.7/site-packages/bs4/testing.pytassertDoctypeHandled^s   cCs-d|}|d}|j|}||fS(s5Generate and parse a document with the given doctype.s s

foo

(R(R RKRMRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyRFls  cCs|jd|jddS(s?Make sure normal, everyday HTML doctypes are handled correctly.thtmls4html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"N(RN(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_normal_doctypesss cCs6|jd}|jd}|jd|jdS(Ns iR7(RRGRtstrip(R RRM((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_empty_doctypeys cCsd}|j|dS(Nsnhtml PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"(RN(R RM((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_public_doctype_with_url~scCs|jddS(Ns$foo SYSTEM "http://www.example.com/"(RN(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_system_doctypescCs|jddS(Ns#xsl:stylesheet SYSTEM "htmlent.dtd"(RN(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_namespaced_system_doctypescCs|jddS(Ns#xsl:stylesheet PUBLIC "htmlent.dtd"(RN(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_namespaced_public_doctypescCsJd}|j|}|j|jdjdd|jdddS(sJA real XHTML document should come out more or less the same as it went in.s Hello. Goodbye. sutf-8s R7N(RRtencodetreplace(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_real_xhtml_documents cCs8d}|j|}|jdt|jddS(stWhen a namespaced XML document is parsed as HTML it should be treated as HTML with weird tag names. s.contentisns1:fooN(RRRItfind_all(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_namespaced_htmlscCs]d}|j|}|j||jd}|j|}|j||jddS(Nustutf8(RRRRW(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_processing_instructions cCstj|jdS(sMake sure you can copy the tree builder. This is important because the builder is part of a BeautifulSoup object, and we want to be able to copy that. N(tcopytdeepcopyR (R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt test_deepcopyscCs?|jd}|j|jj|jt|jddS(sA

tag is never designated as an empty-element tag. Even if the markup shows it as an empty-element tag, it shouldn't be presented that way. s

s

N(Rt assertFalseRJR:RRH(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyt!test_p_tag_is_never_empty_elementscCs4|jdd|jdd|jdddS(sA tag that's not closed by the end of the document should be closed. This applies to all tags except empty-element tags. s

s

sss
s
N(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_unclosed_tags_get_closedscCs?|jd}|j|jj|jt|jddS(sA
tag is designated as an empty-element tag. Some parsers treat

as one
tag, some parsers as two tags, but it should always be an empty-element tag. s

s
N(Rt assertTrueR'R:RRH(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyt#test_br_is_always_empty_element_tagscCs|jddS(Ns(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_nested_formatting_elementsscCs6d}|j|}|jd|jdddS(Ns Ordinary HEAD element test Hello, world! stext/javascripttscriptttype(RRtfind(R ROR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_double_heads cCsd}|j||j|}|jdd}|j|jt|jdd}|j||j|jdd}|j||jdS(Ns

foobaz

ttexttfoobarREtbaz(RRRiRR@RRR(R RRtcommentRERm((s//usr/lib/python2.7/site-packages/bs4/testing.pyt test_comments cCsd}d}|j||j||j|}|j|jj||j|}|j|jj||jd}|j|jjddS(sWhitespace must be preserved in
 and sN(RRRtpretprettifyttextarea(Rt
pre_markupttextarea_markupR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt-test_preserved_whitespace_in_pre_and_textareas

cCs=d}|j|d}|j|d}|j|dS(s+Inline elements can be nested indefinitely.sInside a B tags!

A nested tag

s/

A doubly nested tag

N(R(R tb_tagt nested_b_tagtdouble_nested_b_tag((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_nested_inline_elements s   cCsK|jd}|j}|j|jjjd|j|jjddS(sBlock elements can be nested.s*

Foo

tFooN(Rt blockquoteRRJtbtstring(R RR{((s//usr/lib/python2.7/site-packages/bs4/testing.pyt test_nested_block_level_elementss cCs'd}|j|d|jddS(s$One table can go inside another one.s[sh
Here's another table:
foo
Here's another table:
foo
s{
Foo
Bar
Baz
N(R(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_correctly_nested_tabless cCs6d}|j|}|jdg|jjddS(Ns1
tcsstclass(RRtdiv(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt(test_deeply_nested_multivalued_attribute0scCs6d}|j|}|jddg|jddS(NstaR|R(RRRO(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt"test_multivalued_attribute_on_html8scCs|jdddS(Nss(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt3test_angle_brackets_in_attribute_values_are_escaped@scCs|jdddS(Nu$

• AT&T is in the s&p 500

u)

• AT&T is in the s&p 500

(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt3test_strings_resembling_character_entity_referencesCscCs/d}|j|}|jd|jjdS(Ns%

“Hello” -☃

u“Hello” -☃(Rt assertEqualsRJR}(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt*test_entities_in_foreign_document_encodingKscCsJd}|jd||jd||jd||jd|dS(Nu

s

s

s

s

(R(R texpect((s//usr/lib/python2.7/site-packages/bs4/testing.pyt0test_entities_in_attributes_converted_to_unicodeWs cCsJd}|jd||jd||jd||jd|dS(Nu

piñata

s

piñata

s

piñata

s

piñata

s

piñata

(R(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyt*test_entities_in_text_converted_to_unicode^s cCs|jdddS(Ns#

I said "good day!"

s

I said "good day!"

(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt,test_quot_entity_converted_to_quotation_markes cCs:d}|jd||jd||jd|dS(Nu�s�s�s �(R(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_out_of_range_entityiscCsR|jd}|jd|jjjj|jd|jj|j|dS(sDMostly to prevent a recurrence of a bug in the html5lib treebuilder.s!

foo

RJN(RRth2R}RR;RJR (R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_multipart_stringsoscCs$|jdd|jdddS(sqVerify consistent handling of empty-element tags, no matter how they come in through the markup. s


s


N(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyR<vscCs<d}|j|}|jd|jj|j|dS(s8Prevent recurrence of a bug in the html5lib treebuilder.s? foo N(RtassertNotEqualRROtbodyR (R tcontentR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt#test_head_tag_between_head_and_body}scCs)d}|j|}|j|jdS(s8Prevent recurrence of a bug in the html5lib treebuilder.s N(RR tarticle(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_multiple_copies_of_a_tags cCs}d}|j|}|j||j|j}|jd|jd|jd|jd|jd|jddS( sParsers don't need to *understand* namespaces, but at the very least they should not choke on namespaces or lose data.s4shttp://www.w3.org/1999/xhtmltxmlnss"http://www.w3.org/1998/Math/MathMLs xmlns:mathmlshttp://www.w3.org/2000/svgs xmlns:svgN(RRRWRO(R RRRO((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_basic_namespacess cCs6d}|j|}|jddg|jddS(NsREtbarR(RRR(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt-test_multivalued_attribute_value_becomes_listscCs/d}|j|}|jd|jjdS(NuDSacré bleu!u Sacré bleu!(RRRR}(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_can_parse_unicode_documentscCs;td}|jdd|}|j|jddS(s2Parsers should be able to work with SoupStrainers.R|s&A bold statementt parse_onlys boldN(RRRR(R tstrainerR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_soupstrainers   cCs|jdddS(Nss(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt7test_single_quote_attribute_values_become_double_quotess cCsd}|j|dS(Ns'a(R(R Rk((s//usr/lib/python2.7/site-packages/bs4/testing.pyt7test_attribute_values_with_nested_quotes_are_left_alonescCs?d}|j|}d|jd<|j|jjddS(Ns'asBrawls happen at "Bob's Bar"tattrs:a(RRERR(R RkR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt:test_attribute_values_with_double_nested_quotes_get_quoteds   cCs$|jdd|jdddS(Ns+s/s.foos2foo(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt.test_ampersand_in_attribute_value_gets_escapeds  cCs|jddS(Ns/(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt7test_escaped_ampersand_in_attribute_value_is_left_alonescCs d}d}|j||dS(Ns-

<<sacré bleu!>>

u#

<<sacré bleu!>>

(R(R Rktexpected((s//usr/lib/python2.7/site-packages/bs4/testing.pyt1test_entities_in_strings_converted_during_parsingscCs/d}|j|}|j|jjddS(Ns

Foo

u ‘Foo’(RRRJR}(R tquoteR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt)test_smart_quotes_converted_on_the_way_ins  cCs)|jd}|j|jjddS(Ns  u iu  (RRRR}(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyt0test_non_breaking_spaces_converted_on_the_way_inscCsDd}djd}|j|}|j|jjd|dS(Ns-

<<sacré bleu!>>

u#

<<sacré bleu!>>

sutf-8(RWRRRJ(R RkRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt&test_entities_converted_on_the_way_outscCshd}|jd}|j|}|jd}|jdd}|jd}|j||dS(Nu

Sacré bleu!

s iso-8859-1sutf-8s ISO-Latin-1(RWRRXR(R t unicode_htmltiso_latin_htmlRtresultR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_real_iso_latin_documentscCsld}|jd}|j|}|j|jd|jd|j|jd|jddS(Nsk
Shift-JISŃR[fBOꂽ{̃t@CłB
s shift-jissutf-8teuc_jp(RRRRW(R tshift_jis_htmlRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_real_shift_jis_documents "cCs_d}|j|dd}|jdks0t|j|jd|jdjddS(NsHebrew (ISO 8859-8) in Visual Directionality

Hebrew (ISO 8859-8) in Visual Directionality

t from_encodings iso8859-8s iso-8859-8sutf-8(s iso8859-8s iso-8859-8(Rtoriginal_encodingtAssertionErrorRRWR(R thebrew_documentR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_real_hebrew_document$s cCsd}d|}|j|}|jdidd6}|d}|jd||jt|t|jd|jd dS( NsEsj %s Shift-JIS markup goes here.R0s Content-types http-equivRstext/html; charset=x-sjisstext/html; charset=utf8R\(RRiRRdt isinstanceRRW(R tmeta_tagRRt parsed_metaR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt'test_meta_tag_reflects_current_encoding1s cCsd}d|}|j|}|jddd}|d}|jd||jt|t|jd|jddS( Ns'sj %s Shift-JIS markup goes here.R0tidtencodingtcharsetsx-sjisR\(RRiRRdRRRW(R RRRRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt3test_html5_style_meta_tag_reflects_current_encodingMs cCs9|jd}d|jd<|jd|jjdS(Ns textRREstext(RRRR(R tdata((s//usr/lib/python2.7/site-packages/bs4/testing.pyt5test_tag_with_no_attributes_can_have_attributes_addedes (:R!R"t__doc__R<RDRNRFRPRRRSRTRURVRYR[R]R`RbRcReRfRjRoRuRyR~RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR(((s//usr/lib/python2.7/site-packages/bs4/testing.pyR$?sr                                          tXMLTreeBuilderSmokeTestcBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZRS(cCsc|jd}tj|d}tj|}|j|jt|j|j|jdS(Ns fooi(RR=R>R?RR@RR(R RARBRC((s//usr/lib/python2.7/site-packages/bs4/testing.pyRDls cCs)|jd}|j|jddS(Nss. (RRRW(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_docstring_generateduscCs2d}|j|}|j||jddS(Ns, R\(RRRW(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_xml_declarationzscCs2d}|j|}|j||jddS(Ns< R\(RRRW(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyR]scCs2d}|j|}|j|jd|dS(sGA real XHTML document should come out *exactly* the same as it went in.s Hello. Goodbye. sutf-8N(RRRW(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyRYscCs/d}|j|}|j||jdS(Ns (RRRW(R tdocR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_nested_namespacesscCsDd}t|d}d|j_|j}|jd|kdS(Ns/ slxml-xmlsconsole.log("< < hey > > ");s< < hey > >(RRgR}RWRd(R RRtencoded((s//usr/lib/python2.7/site-packages/bs4/testing.pyt5test_formatter_processes_script_tag_for_xml_documentss   cCs/d}|j|}|jd|jjdS(Nu?Sacré bleu!u Sacré bleu!(RRtrootR}(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyRscCs2d}|j|}|jt|j|dS(Nsb2012-07-02T20:33:42Zcd(RRtunicodetrss(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_popping_namespaced_tagscCs,|jd}|j|jdddS(Nstlatin1s/ (RRRW(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyt(test_docstring_includes_correct_encodings cCs>dddd}|j|}|j|jd|dS( s<A large XML document should come out the same as it went in.s- t0ii ssutf-8Ni(RRRW(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_large_xml_documentscCs!|jdd|jddS(Ns

s

s

foo

(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt9test_tags_are_empty_element_if_and_only_if_they_are_emptyscCsJd}|j|}|j}|jd|d|jd|ddS(NsThis tag is in the a namespaceThis tag is in the b namespaceshttp://example.com/sxmlns:ashttp://example.net/sxmlns:b(RRR(R RRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_namespaces_are_preserveds  cCs2d}|j|}|jt|j|dS(NsN

20010504

(RRRRJ(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_closing_namespaced_tagscCs2d}|j|}|jt|j|dS(Nss(RRRRE(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_namespaced_attributesscCs2d}|j|}|jt|j|dS(Nsbar(RRRRE(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt(test_namespaced_attributes_xml_namespacescCsd}|j|}|jdt|jd|jdt|jd|jdt|jd|jdt|jddd |jdt|jddgdS( Ns foo bar baz ittagisns1:tagisns2:tagtkeytvalue(RRRIRZ(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_find_by_prefixed_names %cCsGd}|j|}|j}tj|}|j|j|jdS(Nsf (RtdocumentR^Rtprefix(R txmlRRt duplicate((s//usr/lib/python2.7/site-packages/bs4/testing.pyt!test_copy_tag_preserves_namespaces  (R!R"RDRRR]RYRRRRRRRRRRRRR(((s//usr/lib/python2.7/site-packages/bs4/testing.pyRjs$            tHTML5TreeBuilderSmokeTestcBs;eZdZdZdZdZdZdZRS(s2Smoke test for a tree builder that supports HTML5.cCsdS(N((R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyRYscCs/d}|j|}|jd|jjdS(Nsshttp://www.w3.org/1999/xhtml(RRRt namespace(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_html_tags_have_namespacescCsKd}|j|}d}|j||jj|j||jjdS(Nsshttp://www.w3.org/2000/svg(RRtsvgRtcircle(R RRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_svg_tags_have_namespace s cCsKd}|j|}d}|j||jj|j||jjdS(Ns5s"http://www.w3.org/1998/Math/MathML(RRtmathRtmsqrt(R RRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_mathml_tags_have_namespaces cCsjd}|j|}|jt|jdt|j|jdd|jd|jdjjdS(Ns3is$?xml version="1.0" encoding="utf-8"?RO(RRdRRGRRRR;(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt$test_xml_declaration_becomes_comments (R!R"RRYRRRR(((s//usr/lib/python2.7/site-packages/bs4/testing.pyRs     csdfd}|S(Nc_sdS(N(R(ttesttargsR((s//usr/lib/python2.7/site-packages/bs4/testing.pytnothing!scsr S|SdS(N((t test_item(t conditionR(s//usr/lib/python2.7/site-packages/bs4/testing.pyt decorator$s((RtreasonR((RRs//usr/lib/python2.7/site-packages/bs4/testing.pytskipIf s (Rt __license__R=R^t functoolstunittestRtbs4Rt bs4.elementRRRRRt bs4.builderRR R tobjectR$RRR(((s//usr/lib/python2.7/site-packages/bs4/testing.pyts"    (%-#PK@N#] [/DDsite-packages/bs4/testing.pyonu[ \[c@sdZdZddlZddlZddlZddlZddlmZddlmZddl m Z m Z m Z m Z mZddlmZeZdejfd YZd efd YZd efd YZdefdYZdZdS(sHelper classes for tests.tMITiN(tTestCase(t BeautifulSoup(tCharsetMetaAttributeValuetCommenttContentMetaAttributeValuetDoctypet SoupStrainer(tHTMLParserTreeBuildertSoupTestcBs>eZedZdZdZddZdZRS(cCstS(N(tdefault_builder(tself((s//usr/lib/python2.7/site-packages/bs4/testing.pyR scKs(|jd|j}t|d||S(s*Build a Beautiful Soup object from markup.tbuilder(tpopR R(R tmarkuptkwargsR ((s//usr/lib/python2.7/site-packages/bs4/testing.pytsoup scCs|jj|S(s[Turn an HTML fragment into a document. The details depend on the builder. (R ttest_fragment_to_document(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyt document_for%scCsS|j}t|d|}|dkr0|}n|j|j|j|dS(NR (R RtNonet assertEqualtdecodeR(R tto_parsetcompare_parsed_toR tobj((s//usr/lib/python2.7/site-packages/bs4/testing.pytassertSoupEquals,s    cCsSd}xF|jD];}|rE|j||j|j||jn|}qWdS(syEnsure that next_element and previous_element are properly set for all descendants of the given element. N(Rt descendantsRt next_elementtprevious_element(R telementtearlierte((s//usr/lib/python2.7/site-packages/bs4/testing.pytassertConnectedness4s N( t__name__t __module__tpropertyR RRRRR (((s//usr/lib/python2.7/site-packages/bs4/testing.pyR s    tHTMLTreeBuilderSmokeTestcBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!d Z"d!Z#d"Z$d#Zd$Z%d%Z&d&Z'd'Z(d(Z)d)Z*d*Z+d+Z,d,Z-d-Z.d.Z/d/Z0d0Z1d1Z2d2Z3d3Z4d4Z5d5Z6d6Z7d7Z8d8Z9RS(9sCA basic test of a treebuilder's competence. Any HTML treebuilder, present or future, should be able to pass these tests. With invalid markup, there's room for interpretation, and different parsers can handle it differently. But with the markup in these tests, there's not much room for interpretation. cCs|xuddddddddd d d d d dddddgD]7}|jd}|j|}|jt|jq=WdS(smVerify that all HTML4 and HTML5 empty element (aka void element) tags are handled correctly. tareatbasetbrtcoltembedthrtimgtinputtkeygentlinktmenuitemtmetatparamtsourcettracktwbrtspacertframetN(Rtnew_tagRtTruetis_empty_element(R tnameRR8((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_empty_element_tagsIs 0cCsc|jd}tj|d}tj|}|j|jt|j|j|jdS(Ns fooi(RtpickletdumpstloadsRt __class__RR(R ttreetdumpedtloaded((s//usr/lib/python2.7/site-packages/bs4/testing.pyt!test_pickle_and_unpickle_identityUs cCs|j|\}}|jd}|j|jt|j|||jt|t| ||j|jjdddS(s8Assert that a given doctype string is handled correctly.itfooN(t_document_with_doctypetcontentsRR@Rtstrtlentp(R tdoctype_fragmentt doctype_strRtdoctype((s//usr/lib/python2.7/site-packages/bs4/testing.pytassertDoctypeHandled^s   cCs-d|}|d}|j|}||fS(s5Generate and parse a document with the given doctype.s s

foo

(R(R RKRMRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyRFls  cCs|jd|jddS(s?Make sure normal, everyday HTML doctypes are handled correctly.thtmls4html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"N(RN(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_normal_doctypesss cCs6|jd}|jd}|jd|jdS(Ns iR7(RRGRtstrip(R RRM((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_empty_doctypeys cCsd}|j|dS(Nsnhtml PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"(RN(R RM((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_public_doctype_with_url~scCs|jddS(Ns$foo SYSTEM "http://www.example.com/"(RN(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_system_doctypescCs|jddS(Ns#xsl:stylesheet SYSTEM "htmlent.dtd"(RN(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_namespaced_system_doctypescCs|jddS(Ns#xsl:stylesheet PUBLIC "htmlent.dtd"(RN(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_namespaced_public_doctypescCsJd}|j|}|j|jdjdd|jdddS(sJA real XHTML document should come out more or less the same as it went in.s Hello. Goodbye. sutf-8s R7N(RRtencodetreplace(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_real_xhtml_documents cCs8d}|j|}|jdt|jddS(stWhen a namespaced XML document is parsed as HTML it should be treated as HTML with weird tag names. s.contentisns1:fooN(RRRItfind_all(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_namespaced_htmlscCs]d}|j|}|j||jd}|j|}|j||jddS(Nustutf8(RRRRW(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_processing_instructions cCstj|jdS(sMake sure you can copy the tree builder. This is important because the builder is part of a BeautifulSoup object, and we want to be able to copy that. N(tcopytdeepcopyR (R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt test_deepcopyscCs?|jd}|j|jj|jt|jddS(sA

tag is never designated as an empty-element tag. Even if the markup shows it as an empty-element tag, it shouldn't be presented that way. s

s

N(Rt assertFalseRJR:RRH(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyt!test_p_tag_is_never_empty_elementscCs4|jdd|jdd|jdddS(sA tag that's not closed by the end of the document should be closed. This applies to all tags except empty-element tags. s

s

sss
s
N(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_unclosed_tags_get_closedscCs?|jd}|j|jj|jt|jddS(sA
tag is designated as an empty-element tag. Some parsers treat

as one
tag, some parsers as two tags, but it should always be an empty-element tag. s

s
N(Rt assertTrueR'R:RRH(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyt#test_br_is_always_empty_element_tagscCs|jddS(Ns(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_nested_formatting_elementsscCs6d}|j|}|jd|jdddS(Ns Ordinary HEAD element test Hello, world! stext/javascripttscriptttype(RRtfind(R ROR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_double_heads cCsd}|j||j|}|jdd}|j|jt|jdd}|j||j|jdd}|j||jdS(Ns

foobaz

ttexttfoobarREtbaz(RRRiRR@RRR(R RRtcommentRERm((s//usr/lib/python2.7/site-packages/bs4/testing.pyt test_comments cCsd}d}|j||j||j|}|j|jj||j|}|j|jj||jd}|j|jjddS(sWhitespace must be preserved in
 and sN(RRRtpretprettifyttextarea(Rt
pre_markupttextarea_markupR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt-test_preserved_whitespace_in_pre_and_textareas

cCs=d}|j|d}|j|d}|j|dS(s+Inline elements can be nested indefinitely.sInside a B tags!

A nested tag

s/

A doubly nested tag

N(R(R tb_tagt nested_b_tagtdouble_nested_b_tag((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_nested_inline_elements s   cCsK|jd}|j}|j|jjjd|j|jjddS(sBlock elements can be nested.s*

Foo

tFooN(Rt blockquoteRRJtbtstring(R RR{((s//usr/lib/python2.7/site-packages/bs4/testing.pyt test_nested_block_level_elementss cCs'd}|j|d|jddS(s$One table can go inside another one.s[sh
Here's another table:
foo
Here's another table:
foo
s{
Foo
Bar
Baz
N(R(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_correctly_nested_tabless cCs6d}|j|}|jdg|jjddS(Ns1
tcsstclass(RRtdiv(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt(test_deeply_nested_multivalued_attribute0scCs6d}|j|}|jddg|jddS(NstaR|R(RRRO(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt"test_multivalued_attribute_on_html8scCs|jdddS(Nss(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt3test_angle_brackets_in_attribute_values_are_escaped@scCs|jdddS(Nu$

• AT&T is in the s&p 500

u)

• AT&T is in the s&p 500

(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt3test_strings_resembling_character_entity_referencesCscCs/d}|j|}|jd|jjdS(Ns%

“Hello” -☃

u“Hello” -☃(Rt assertEqualsRJR}(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt*test_entities_in_foreign_document_encodingKscCsJd}|jd||jd||jd||jd|dS(Nu

s

s

s

s

(R(R texpect((s//usr/lib/python2.7/site-packages/bs4/testing.pyt0test_entities_in_attributes_converted_to_unicodeWs cCsJd}|jd||jd||jd||jd|dS(Nu

piñata

s

piñata

s

piñata

s

piñata

s

piñata

(R(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyt*test_entities_in_text_converted_to_unicode^s cCs|jdddS(Ns#

I said "good day!"

s

I said "good day!"

(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt,test_quot_entity_converted_to_quotation_markes cCs:d}|jd||jd||jd|dS(Nu�s�s�s �(R(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_out_of_range_entityiscCsR|jd}|jd|jjjj|jd|jj|j|dS(sDMostly to prevent a recurrence of a bug in the html5lib treebuilder.s!

foo

RJN(RRth2R}RR;RJR (R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_multipart_stringsoscCs$|jdd|jdddS(sqVerify consistent handling of empty-element tags, no matter how they come in through the markup. s


s


N(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyR<vscCs<d}|j|}|jd|jj|j|dS(s8Prevent recurrence of a bug in the html5lib treebuilder.s? foo N(RtassertNotEqualRROtbodyR (R tcontentR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt#test_head_tag_between_head_and_body}scCs)d}|j|}|j|jdS(s8Prevent recurrence of a bug in the html5lib treebuilder.s N(RR tarticle(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_multiple_copies_of_a_tags cCs}d}|j|}|j||j|j}|jd|jd|jd|jd|jd|jddS( sParsers don't need to *understand* namespaces, but at the very least they should not choke on namespaces or lose data.s4shttp://www.w3.org/1999/xhtmltxmlnss"http://www.w3.org/1998/Math/MathMLs xmlns:mathmlshttp://www.w3.org/2000/svgs xmlns:svgN(RRRWRO(R RRRO((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_basic_namespacess cCs6d}|j|}|jddg|jddS(NsREtbarR(RRR(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt-test_multivalued_attribute_value_becomes_listscCs/d}|j|}|jd|jjdS(NuDSacré bleu!u Sacré bleu!(RRRR}(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_can_parse_unicode_documentscCs;td}|jdd|}|j|jddS(s2Parsers should be able to work with SoupStrainers.R|s&A bold statementt parse_onlys boldN(RRRR(R tstrainerR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_soupstrainers   cCs|jdddS(Nss(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt7test_single_quote_attribute_values_become_double_quotess cCsd}|j|dS(Ns'a(R(R Rk((s//usr/lib/python2.7/site-packages/bs4/testing.pyt7test_attribute_values_with_nested_quotes_are_left_alonescCs?d}|j|}d|jd<|j|jjddS(Ns'asBrawls happen at "Bob's Bar"tattrs:a(RRERR(R RkR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt:test_attribute_values_with_double_nested_quotes_get_quoteds   cCs$|jdd|jdddS(Ns+s/s.foos2foo(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt.test_ampersand_in_attribute_value_gets_escapeds  cCs|jddS(Ns/(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt7test_escaped_ampersand_in_attribute_value_is_left_alonescCs d}d}|j||dS(Ns-

<<sacré bleu!>>

u#

<<sacré bleu!>>

(R(R Rktexpected((s//usr/lib/python2.7/site-packages/bs4/testing.pyt1test_entities_in_strings_converted_during_parsingscCs/d}|j|}|j|jjddS(Ns

Foo

u ‘Foo’(RRRJR}(R tquoteR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt)test_smart_quotes_converted_on_the_way_ins  cCs)|jd}|j|jjddS(Ns  u iu  (RRRR}(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyt0test_non_breaking_spaces_converted_on_the_way_inscCsDd}djd}|j|}|j|jjd|dS(Ns-

<<sacré bleu!>>

u#

<<sacré bleu!>>

sutf-8(RWRRRJ(R RkRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt&test_entities_converted_on_the_way_outscCshd}|jd}|j|}|jd}|jdd}|jd}|j||dS(Nu

Sacré bleu!

s iso-8859-1sutf-8s ISO-Latin-1(RWRRXR(R t unicode_htmltiso_latin_htmlRtresultR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_real_iso_latin_documentscCsld}|jd}|j|}|j|jd|jd|j|jd|jddS(Nsk
Shift-JISŃR[fBOꂽ{̃t@CłB
s shift-jissutf-8teuc_jp(RRRRW(R tshift_jis_htmlRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_real_shift_jis_documents "cCsJd}|j|dd}|j|jd|jdjddS(NsHebrew (ISO 8859-8) in Visual Directionality

Hebrew (ISO 8859-8) in Visual Directionality

t from_encodings iso8859-8sutf-8(RRRWR(R thebrew_documentR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_real_hebrew_document$s  cCsd}d|}|j|}|jdidd6}|d}|jd||jt|t|jd|jd dS( NsEsj %s Shift-JIS markup goes here.R0s Content-types http-equivRstext/html; charset=x-sjisstext/html; charset=utf8R\(RRiRRdt isinstanceRRW(R tmeta_tagRRt parsed_metaR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt'test_meta_tag_reflects_current_encoding1s cCsd}d|}|j|}|jddd}|d}|jd||jt|t|jd|jddS( Ns'sj %s Shift-JIS markup goes here.R0tidtencodingtcharsetsx-sjisR\(RRiRRdRRRW(R RRRRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt3test_html5_style_meta_tag_reflects_current_encodingMs cCs9|jd}d|jd<|jd|jjdS(Ns textRREstext(RRRR(R tdata((s//usr/lib/python2.7/site-packages/bs4/testing.pyt5test_tag_with_no_attributes_can_have_attributes_addedes (:R!R"t__doc__R<RDRNRFRPRRRSRTRURVRYR[R]R`RbRcReRfRjRoRuRyR~RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR(((s//usr/lib/python2.7/site-packages/bs4/testing.pyR$?sr                                          tXMLTreeBuilderSmokeTestcBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZRS(cCsc|jd}tj|d}tj|}|j|jt|j|j|jdS(Ns fooi(RR=R>R?RR@RR(R RARBRC((s//usr/lib/python2.7/site-packages/bs4/testing.pyRDls cCs)|jd}|j|jddS(Nss. (RRRW(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_docstring_generateduscCs2d}|j|}|j||jddS(Ns, R\(RRRW(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_xml_declarationzscCs2d}|j|}|j||jddS(Ns< R\(RRRW(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyR]scCs2d}|j|}|j|jd|dS(sGA real XHTML document should come out *exactly* the same as it went in.s Hello. Goodbye. sutf-8N(RRRW(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyRYscCs/d}|j|}|j||jdS(Ns (RRRW(R tdocR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_nested_namespacesscCsDd}t|d}d|j_|j}|jd|kdS(Ns/ slxml-xmlsconsole.log("< < hey > > ");s< < hey > >(RRgR}RWRd(R RRtencoded((s//usr/lib/python2.7/site-packages/bs4/testing.pyt5test_formatter_processes_script_tag_for_xml_documentss   cCs/d}|j|}|jd|jjdS(Nu?Sacré bleu!u Sacré bleu!(RRtrootR}(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyRscCs2d}|j|}|jt|j|dS(Nsb2012-07-02T20:33:42Zcd(RRtunicodetrss(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_popping_namespaced_tagscCs,|jd}|j|jdddS(Nstlatin1s/ (RRRW(R R((s//usr/lib/python2.7/site-packages/bs4/testing.pyt(test_docstring_includes_correct_encodings cCs>dddd}|j|}|j|jd|dS( s<A large XML document should come out the same as it went in.s- t0ii ssutf-8Ni(RRRW(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_large_xml_documentscCs!|jdd|jddS(Ns

s

s

foo

(R(R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyt9test_tags_are_empty_element_if_and_only_if_they_are_emptyscCsJd}|j|}|j}|jd|d|jd|ddS(NsThis tag is in the a namespaceThis tag is in the b namespaceshttp://example.com/sxmlns:ashttp://example.net/sxmlns:b(RRR(R RRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_namespaces_are_preserveds  cCs2d}|j|}|jt|j|dS(NsN

20010504

(RRRRJ(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_closing_namespaced_tagscCs2d}|j|}|jt|j|dS(Nss(RRRRE(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_namespaced_attributesscCs2d}|j|}|jt|j|dS(Nsbar(RRRRE(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt(test_namespaced_attributes_xml_namespacescCsd}|j|}|jdt|jd|jdt|jd|jdt|jd|jdt|jddd |jdt|jddgdS( Ns foo bar baz ittagisns1:tagisns2:tagtkeytvalue(RRRIRZ(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_find_by_prefixed_names %cCsGd}|j|}|j}tj|}|j|j|jdS(Nsf (RtdocumentR^Rtprefix(R txmlRRt duplicate((s//usr/lib/python2.7/site-packages/bs4/testing.pyt!test_copy_tag_preserves_namespaces  (R!R"RDRRR]RYRRRRRRRRRRRRR(((s//usr/lib/python2.7/site-packages/bs4/testing.pyRjs$            tHTML5TreeBuilderSmokeTestcBs;eZdZdZdZdZdZdZRS(s2Smoke test for a tree builder that supports HTML5.cCsdS(N((R ((s//usr/lib/python2.7/site-packages/bs4/testing.pyRYscCs/d}|j|}|jd|jjdS(Nsshttp://www.w3.org/1999/xhtml(RRRt namespace(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_html_tags_have_namespacescCsKd}|j|}d}|j||jj|j||jjdS(Nsshttp://www.w3.org/2000/svg(RRtsvgRtcircle(R RRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_svg_tags_have_namespace s cCsKd}|j|}d}|j||jj|j||jjdS(Ns5s"http://www.w3.org/1998/Math/MathML(RRtmathRtmsqrt(R RRR((s//usr/lib/python2.7/site-packages/bs4/testing.pyttest_mathml_tags_have_namespaces cCsjd}|j|}|jt|jdt|j|jdd|jd|jdjjdS(Ns3is$?xml version="1.0" encoding="utf-8"?RO(RRdRRGRRRR;(R RR((s//usr/lib/python2.7/site-packages/bs4/testing.pyt$test_xml_declaration_becomes_comments (R!R"RRYRRRR(((s//usr/lib/python2.7/site-packages/bs4/testing.pyRs     csdfd}|S(Nc_sdS(N(R(ttesttargsR((s//usr/lib/python2.7/site-packages/bs4/testing.pytnothing!scsr S|SdS(N((t test_item(t conditionR(s//usr/lib/python2.7/site-packages/bs4/testing.pyt decorator$s((RtreasonR((RRs//usr/lib/python2.7/site-packages/bs4/testing.pytskipIf s (Rt __license__R=R^t functoolstunittestRtbs4Rt bs4.elementRRRRRt bs4.builderRR R tobjectR$RRR(((s//usr/lib/python2.7/site-packages/bs4/testing.pyts"    (%-#PK@N#]N~~site-packages/bs4/testing.pynu[# encoding: utf-8 """Helper classes for tests.""" # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. __license__ = "MIT" import pickle import copy import functools import unittest from unittest import TestCase from bs4 import BeautifulSoup from bs4.element import ( CharsetMetaAttributeValue, Comment, ContentMetaAttributeValue, Doctype, SoupStrainer, ) from bs4.builder import HTMLParserTreeBuilder default_builder = HTMLParserTreeBuilder class SoupTest(unittest.TestCase): @property def default_builder(self): return default_builder() def soup(self, markup, **kwargs): """Build a Beautiful Soup object from markup.""" builder = kwargs.pop('builder', self.default_builder) return BeautifulSoup(markup, builder=builder, **kwargs) def document_for(self, markup): """Turn an HTML fragment into a document. The details depend on the builder. """ return self.default_builder.test_fragment_to_document(markup) def assertSoupEquals(self, to_parse, compare_parsed_to=None): builder = self.default_builder obj = BeautifulSoup(to_parse, builder=builder) if compare_parsed_to is None: compare_parsed_to = to_parse self.assertEqual(obj.decode(), self.document_for(compare_parsed_to)) def assertConnectedness(self, element): """Ensure that next_element and previous_element are properly set for all descendants of the given element. """ earlier = None for e in element.descendants: if earlier: self.assertEqual(e, earlier.next_element) self.assertEqual(earlier, e.previous_element) earlier = e class HTMLTreeBuilderSmokeTest(object): """A basic test of a treebuilder's competence. Any HTML treebuilder, present or future, should be able to pass these tests. With invalid markup, there's room for interpretation, and different parsers can handle it differently. But with the markup in these tests, there's not much room for interpretation. """ def test_empty_element_tags(self): """Verify that all HTML4 and HTML5 empty element (aka void element) tags are handled correctly. """ for name in [ 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr', 'spacer', 'frame' ]: soup = self.soup("") new_tag = soup.new_tag(name) self.assertEqual(True, new_tag.is_empty_element) def test_pickle_and_unpickle_identity(self): # Pickling a tree, then unpickling it, yields a tree identical # to the original. tree = self.soup("foo") dumped = pickle.dumps(tree, 2) loaded = pickle.loads(dumped) self.assertEqual(loaded.__class__, BeautifulSoup) self.assertEqual(loaded.decode(), tree.decode()) def assertDoctypeHandled(self, doctype_fragment): """Assert that a given doctype string is handled correctly.""" doctype_str, soup = self._document_with_doctype(doctype_fragment) # Make sure a Doctype object was created. doctype = soup.contents[0] self.assertEqual(doctype.__class__, Doctype) self.assertEqual(doctype, doctype_fragment) self.assertEqual(str(soup)[:len(doctype_str)], doctype_str) # Make sure that the doctype was correctly associated with the # parse tree and that the rest of the document parsed. self.assertEqual(soup.p.contents[0], 'foo') def _document_with_doctype(self, doctype_fragment): """Generate and parse a document with the given doctype.""" doctype = '' % doctype_fragment markup = doctype + '\n

foo

' soup = self.soup(markup) return doctype, soup def test_normal_doctypes(self): """Make sure normal, everyday HTML doctypes are handled correctly.""" self.assertDoctypeHandled("html") self.assertDoctypeHandled( 'html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"') def test_empty_doctype(self): soup = self.soup("") doctype = soup.contents[0] self.assertEqual("", doctype.strip()) def test_public_doctype_with_url(self): doctype = 'html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"' self.assertDoctypeHandled(doctype) def test_system_doctype(self): self.assertDoctypeHandled('foo SYSTEM "http://www.example.com/"') def test_namespaced_system_doctype(self): # We can handle a namespaced doctype with a system ID. self.assertDoctypeHandled('xsl:stylesheet SYSTEM "htmlent.dtd"') def test_namespaced_public_doctype(self): # Test a namespaced doctype with a public id. self.assertDoctypeHandled('xsl:stylesheet PUBLIC "htmlent.dtd"') def test_real_xhtml_document(self): """A real XHTML document should come out more or less the same as it went in.""" markup = b""" Hello. Goodbye. """ soup = self.soup(markup) self.assertEqual( soup.encode("utf-8").replace(b"\n", b""), markup.replace(b"\n", b"")) def test_namespaced_html(self): """When a namespaced XML document is parsed as HTML it should be treated as HTML with weird tag names. """ markup = b"""content""" soup = self.soup(markup) self.assertEqual(2, len(soup.find_all("ns1:foo"))) def test_processing_instruction(self): # We test both Unicode and bytestring to verify that # process_markup correctly sets processing_instruction_class # even when the markup is already Unicode and there is no # need to process anything. markup = u"""""" soup = self.soup(markup) self.assertEqual(markup, soup.decode()) markup = b"""""" soup = self.soup(markup) self.assertEqual(markup, soup.encode("utf8")) def test_deepcopy(self): """Make sure you can copy the tree builder. This is important because the builder is part of a BeautifulSoup object, and we want to be able to copy that. """ copy.deepcopy(self.default_builder) def test_p_tag_is_never_empty_element(self): """A

tag is never designated as an empty-element tag. Even if the markup shows it as an empty-element tag, it shouldn't be presented that way. """ soup = self.soup("

") self.assertFalse(soup.p.is_empty_element) self.assertEqual(str(soup.p), "

") def test_unclosed_tags_get_closed(self): """A tag that's not closed by the end of the document should be closed. This applies to all tags except empty-element tags. """ self.assertSoupEquals("

", "

") self.assertSoupEquals("", "") self.assertSoupEquals("
", "
") def test_br_is_always_empty_element_tag(self): """A
tag is designated as an empty-element tag. Some parsers treat

as one
tag, some parsers as two tags, but it should always be an empty-element tag. """ soup = self.soup("

") self.assertTrue(soup.br.is_empty_element) self.assertEqual(str(soup.br), "
") def test_nested_formatting_elements(self): self.assertSoupEquals("") def test_double_head(self): html = ''' Ordinary HEAD element test Hello, world! ''' soup = self.soup(html) self.assertEqual("text/javascript", soup.find('script')['type']) def test_comment(self): # Comments are represented as Comment objects. markup = "

foobaz

" self.assertSoupEquals(markup) soup = self.soup(markup) comment = soup.find(text="foobar") self.assertEqual(comment.__class__, Comment) # The comment is properly integrated into the tree. foo = soup.find(text="foo") self.assertEqual(comment, foo.next_element) baz = soup.find(text="baz") self.assertEqual(comment, baz.previous_element) def test_preserved_whitespace_in_pre_and_textarea(self): """Whitespace must be preserved in
 and "
        self.assertSoupEquals(pre_markup)
        self.assertSoupEquals(textarea_markup)

        soup = self.soup(pre_markup)
        self.assertEqual(soup.pre.prettify(), pre_markup)

        soup = self.soup(textarea_markup)
        self.assertEqual(soup.textarea.prettify(), textarea_markup)

        soup = self.soup("")
        self.assertEqual(soup.textarea.prettify(), "")

    def test_nested_inline_elements(self):
        """Inline elements can be nested indefinitely."""
        b_tag = "Inside a B tag"
        self.assertSoupEquals(b_tag)

        nested_b_tag = "

A nested tag

" self.assertSoupEquals(nested_b_tag) double_nested_b_tag = "

A doubly nested tag

" self.assertSoupEquals(nested_b_tag) def test_nested_block_level_elements(self): """Block elements can be nested.""" soup = self.soup('

Foo

') blockquote = soup.blockquote self.assertEqual(blockquote.p.b.string, 'Foo') self.assertEqual(blockquote.b.string, 'Foo') def test_correctly_nested_tables(self): """One table can go inside another one.""" markup = ('' '' "') self.assertSoupEquals( markup, '
Here's another table:" '' '' '
foo
Here\'s another table:' '
foo
' '
') self.assertSoupEquals( "" "" "
Foo
Bar
Baz
") def test_deeply_nested_multivalued_attribute(self): # html5lib can set the attributes of the same tag many times # as it rearranges the tree. This has caused problems with # multivalued attributes. markup = '
' soup = self.soup(markup) self.assertEqual(["css"], soup.div.div['class']) def test_multivalued_attribute_on_html(self): # html5lib uses a different API to set the attributes ot the # tag. This has caused problems with multivalued # attributes. markup = '' soup = self.soup(markup) self.assertEqual(["a", "b"], soup.html['class']) def test_angle_brackets_in_attribute_values_are_escaped(self): self.assertSoupEquals('', '') def test_strings_resembling_character_entity_references(self): # "&T" and "&p" look like incomplete character entities, but they are # not. self.assertSoupEquals( u"

• AT&T is in the s&p 500

", u"

\u2022 AT&T is in the s&p 500

" ) def test_entities_in_foreign_document_encoding(self): # “ and ” are invalid numeric entities referencing # Windows-1252 characters. - references a character common # to Windows-1252 and Unicode, and ☃ references a # character only found in Unicode. # # All of these entities should be converted to Unicode # characters. markup = "

“Hello” -☃

" soup = self.soup(markup) self.assertEquals(u"“Hello” -☃", soup.p.string) def test_entities_in_attributes_converted_to_unicode(self): expect = u'

' self.assertSoupEquals('

', expect) self.assertSoupEquals('

', expect) self.assertSoupEquals('

', expect) self.assertSoupEquals('

', expect) def test_entities_in_text_converted_to_unicode(self): expect = u'

pi\N{LATIN SMALL LETTER N WITH TILDE}ata

' self.assertSoupEquals("

piñata

", expect) self.assertSoupEquals("

piñata

", expect) self.assertSoupEquals("

piñata

", expect) self.assertSoupEquals("

piñata

", expect) def test_quot_entity_converted_to_quotation_mark(self): self.assertSoupEquals("

I said "good day!"

", '

I said "good day!"

') def test_out_of_range_entity(self): expect = u"\N{REPLACEMENT CHARACTER}" self.assertSoupEquals("�", expect) self.assertSoupEquals("�", expect) self.assertSoupEquals("�", expect) def test_multipart_strings(self): "Mostly to prevent a recurrence of a bug in the html5lib treebuilder." soup = self.soup("

\nfoo

") self.assertEqual("p", soup.h2.string.next_element.name) self.assertEqual("p", soup.p.name) self.assertConnectedness(soup) def test_empty_element_tags(self): """Verify consistent handling of empty-element tags, no matter how they come in through the markup. """ self.assertSoupEquals('


', "


") self.assertSoupEquals('


', "


") def test_head_tag_between_head_and_body(self): "Prevent recurrence of a bug in the html5lib treebuilder." content = """ foo """ soup = self.soup(content) self.assertNotEqual(None, soup.html.body) self.assertConnectedness(soup) def test_multiple_copies_of_a_tag(self): "Prevent recurrence of a bug in the html5lib treebuilder." content = """ """ soup = self.soup(content) self.assertConnectedness(soup.article) def test_basic_namespaces(self): """Parsers don't need to *understand* namespaces, but at the very least they should not choke on namespaces or lose data.""" markup = b'4' soup = self.soup(markup) self.assertEqual(markup, soup.encode()) html = soup.html self.assertEqual('http://www.w3.org/1999/xhtml', soup.html['xmlns']) self.assertEqual( 'http://www.w3.org/1998/Math/MathML', soup.html['xmlns:mathml']) self.assertEqual( 'http://www.w3.org/2000/svg', soup.html['xmlns:svg']) def test_multivalued_attribute_value_becomes_list(self): markup = b'' soup = self.soup(markup) self.assertEqual(['foo', 'bar'], soup.a['class']) # # Generally speaking, tests below this point are more tests of # Beautiful Soup than tests of the tree builders. But parsers are # weird, so we run these tests separately for every tree builder # to detect any differences between them. # def test_can_parse_unicode_document(self): # A seemingly innocuous document... but it's in Unicode! And # it contains characters that can't be represented in the # encoding found in the declaration! The horror! markup = u'Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!' soup = self.soup(markup) self.assertEqual(u'Sacr\xe9 bleu!', soup.body.string) def test_soupstrainer(self): """Parsers should be able to work with SoupStrainers.""" strainer = SoupStrainer("b") soup = self.soup("A bold statement", parse_only=strainer) self.assertEqual(soup.decode(), "bold") def test_single_quote_attribute_values_become_double_quotes(self): self.assertSoupEquals("", '') def test_attribute_values_with_nested_quotes_are_left_alone(self): text = """a""" self.assertSoupEquals(text) def test_attribute_values_with_double_nested_quotes_get_quoted(self): text = """a""" soup = self.soup(text) soup.foo['attr'] = 'Brawls happen at "Bob\'s Bar"' self.assertSoupEquals( soup.foo.decode(), """a""") def test_ampersand_in_attribute_value_gets_escaped(self): self.assertSoupEquals('', '') self.assertSoupEquals( 'foo', 'foo') def test_escaped_ampersand_in_attribute_value_is_left_alone(self): self.assertSoupEquals('') def test_entities_in_strings_converted_during_parsing(self): # Both XML and HTML entities are converted to Unicode characters # during parsing. text = "

<<sacré bleu!>>

" expected = u"

<<sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!>>

" self.assertSoupEquals(text, expected) def test_smart_quotes_converted_on_the_way_in(self): # Microsoft smart quotes are converted to Unicode characters during # parsing. quote = b"

\x91Foo\x92

" soup = self.soup(quote) self.assertEqual( soup.p.string, u"\N{LEFT SINGLE QUOTATION MARK}Foo\N{RIGHT SINGLE QUOTATION MARK}") def test_non_breaking_spaces_converted_on_the_way_in(self): soup = self.soup("  ") self.assertEqual(soup.a.string, u"\N{NO-BREAK SPACE}" * 2) def test_entities_converted_on_the_way_out(self): text = "

<<sacré bleu!>>

" expected = u"

<<sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!>>

".encode("utf-8") soup = self.soup(text) self.assertEqual(soup.p.encode("utf-8"), expected) def test_real_iso_latin_document(self): # Smoke test of interrelated functionality, using an # easy-to-understand document. # Here it is in Unicode. Note that it claims to be in ISO-Latin-1. unicode_html = u'

Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!

' # That's because we're going to encode it into ISO-Latin-1, and use # that to test. iso_latin_html = unicode_html.encode("iso-8859-1") # Parse the ISO-Latin-1 HTML. soup = self.soup(iso_latin_html) # Encode it to UTF-8. result = soup.encode("utf-8") # What do we expect the result to look like? Well, it would # look like unicode_html, except that the META tag would say # UTF-8 instead of ISO-Latin-1. expected = unicode_html.replace("ISO-Latin-1", "utf-8") # And, of course, it would be in UTF-8, not Unicode. expected = expected.encode("utf-8") # Ta-da! self.assertEqual(result, expected) def test_real_shift_jis_document(self): # Smoke test to make sure the parser can handle a document in # Shift-JIS encoding, without choking. shift_jis_html = ( b'
'
            b'\x82\xb1\x82\xea\x82\xcdShift-JIS\x82\xc5\x83R\x81[\x83f'
            b'\x83B\x83\x93\x83O\x82\xb3\x82\xea\x82\xbd\x93\xfa\x96{\x8c'
            b'\xea\x82\xcc\x83t\x83@\x83C\x83\x8b\x82\xc5\x82\xb7\x81B'
            b'
') unicode_html = shift_jis_html.decode("shift-jis") soup = self.soup(unicode_html) # Make sure the parse tree is correctly encoded to various # encodings. self.assertEqual(soup.encode("utf-8"), unicode_html.encode("utf-8")) self.assertEqual(soup.encode("euc_jp"), unicode_html.encode("euc_jp")) def test_real_hebrew_document(self): # A real-world test to make sure we can convert ISO-8859-9 (a # Hebrew encoding) to UTF-8. hebrew_document = b'Hebrew (ISO 8859-8) in Visual Directionality

Hebrew (ISO 8859-8) in Visual Directionality

\xed\xe5\xec\xf9' soup = self.soup( hebrew_document, from_encoding="iso8859-8") # Some tree builders call it iso8859-8, others call it iso-8859-9. # That's not a difference we really care about. assert soup.original_encoding in ('iso8859-8', 'iso-8859-8') self.assertEqual( soup.encode('utf-8'), hebrew_document.decode("iso8859-8").encode("utf-8")) def test_meta_tag_reflects_current_encoding(self): # Here's the tag saying that a document is # encoded in Shift-JIS. meta_tag = ('') # Here's a document incorporating that meta tag. shift_jis_html = ( '\n%s\n' '' 'Shift-JIS markup goes here.') % meta_tag soup = self.soup(shift_jis_html) # Parse the document, and the charset is seemingly unaffected. parsed_meta = soup.find('meta', {'http-equiv': 'Content-type'}) content = parsed_meta['content'] self.assertEqual('text/html; charset=x-sjis', content) # But that value is actually a ContentMetaAttributeValue object. self.assertTrue(isinstance(content, ContentMetaAttributeValue)) # And it will take on a value that reflects its current # encoding. self.assertEqual('text/html; charset=utf8', content.encode("utf8")) # For the rest of the story, see TestSubstitutions in # test_tree.py. def test_html5_style_meta_tag_reflects_current_encoding(self): # Here's the tag saying that a document is # encoded in Shift-JIS. meta_tag = ('') # Here's a document incorporating that meta tag. shift_jis_html = ( '\n%s\n' '' 'Shift-JIS markup goes here.') % meta_tag soup = self.soup(shift_jis_html) # Parse the document, and the charset is seemingly unaffected. parsed_meta = soup.find('meta', id="encoding") charset = parsed_meta['charset'] self.assertEqual('x-sjis', charset) # But that value is actually a CharsetMetaAttributeValue object. self.assertTrue(isinstance(charset, CharsetMetaAttributeValue)) # And it will take on a value that reflects its current # encoding. self.assertEqual('utf8', charset.encode("utf8")) def test_tag_with_no_attributes_can_have_attributes_added(self): data = self.soup("text") data.a['foo'] = 'bar' self.assertEqual('text', data.a.decode()) class XMLTreeBuilderSmokeTest(object): def test_pickle_and_unpickle_identity(self): # Pickling a tree, then unpickling it, yields a tree identical # to the original. tree = self.soup("foo") dumped = pickle.dumps(tree, 2) loaded = pickle.loads(dumped) self.assertEqual(loaded.__class__, BeautifulSoup) self.assertEqual(loaded.decode(), tree.decode()) def test_docstring_generated(self): soup = self.soup("") self.assertEqual( soup.encode(), b'\n') def test_xml_declaration(self): markup = b"""\n""" soup = self.soup(markup) self.assertEqual(markup, soup.encode("utf8")) def test_processing_instruction(self): markup = b"""\n""" soup = self.soup(markup) self.assertEqual(markup, soup.encode("utf8")) def test_real_xhtml_document(self): """A real XHTML document should come out *exactly* the same as it went in.""" markup = b""" Hello. Goodbye. """ soup = self.soup(markup) self.assertEqual( soup.encode("utf-8"), markup) def test_nested_namespaces(self): doc = b""" """ soup = self.soup(doc) self.assertEqual(doc, soup.encode()) def test_formatter_processes_script_tag_for_xml_documents(self): doc = """ """ soup = BeautifulSoup(doc, "lxml-xml") # lxml would have stripped this while parsing, but we can add # it later. soup.script.string = 'console.log("< < hey > > ");' encoded = soup.encode() self.assertTrue(b"< < hey > >" in encoded) def test_can_parse_unicode_document(self): markup = u'Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!' soup = self.soup(markup) self.assertEqual(u'Sacr\xe9 bleu!', soup.root.string) def test_popping_namespaced_tag(self): markup = 'b2012-07-02T20:33:42Zcd' soup = self.soup(markup) self.assertEqual( unicode(soup.rss), markup) def test_docstring_includes_correct_encoding(self): soup = self.soup("") self.assertEqual( soup.encode("latin1"), b'\n') def test_large_xml_document(self): """A large XML document should come out the same as it went in.""" markup = (b'\n' + b'0' * (2**12) + b'') soup = self.soup(markup) self.assertEqual(soup.encode("utf-8"), markup) def test_tags_are_empty_element_if_and_only_if_they_are_empty(self): self.assertSoupEquals("

", "

") self.assertSoupEquals("

foo

") def test_namespaces_are_preserved(self): markup = 'This tag is in the a namespaceThis tag is in the b namespace' soup = self.soup(markup) root = soup.root self.assertEqual("http://example.com/", root['xmlns:a']) self.assertEqual("http://example.net/", root['xmlns:b']) def test_closing_namespaced_tag(self): markup = '

20010504

' soup = self.soup(markup) self.assertEqual(unicode(soup.p), markup) def test_namespaced_attributes(self): markup = '' soup = self.soup(markup) self.assertEqual(unicode(soup.foo), markup) def test_namespaced_attributes_xml_namespace(self): markup = 'bar' soup = self.soup(markup) self.assertEqual(unicode(soup.foo), markup) def test_find_by_prefixed_name(self): doc = """ foo bar baz """ soup = self.soup(doc) # There are three tags. self.assertEqual(3, len(soup.find_all('tag'))) # But two of them are ns1:tag and one of them is ns2:tag. self.assertEqual(2, len(soup.find_all('ns1:tag'))) self.assertEqual(1, len(soup.find_all('ns2:tag'))) self.assertEqual(1, len(soup.find_all('ns2:tag', key='value'))) self.assertEqual(3, len(soup.find_all(['ns1:tag', 'ns2:tag']))) def test_copy_tag_preserves_namespace(self): xml = """ """ soup = self.soup(xml) tag = soup.document duplicate = copy.copy(tag) # The two tags have the same namespace prefix. self.assertEqual(tag.prefix, duplicate.prefix) class HTML5TreeBuilderSmokeTest(HTMLTreeBuilderSmokeTest): """Smoke test for a tree builder that supports HTML5.""" def test_real_xhtml_document(self): # Since XHTML is not HTML5, HTML5 parsers are not tested to handle # XHTML documents in any particular way. pass def test_html_tags_have_namespace(self): markup = "" soup = self.soup(markup) self.assertEqual("http://www.w3.org/1999/xhtml", soup.a.namespace) def test_svg_tags_have_namespace(self): markup = '' soup = self.soup(markup) namespace = "http://www.w3.org/2000/svg" self.assertEqual(namespace, soup.svg.namespace) self.assertEqual(namespace, soup.circle.namespace) def test_mathml_tags_have_namespace(self): markup = '5' soup = self.soup(markup) namespace = 'http://www.w3.org/1998/Math/MathML' self.assertEqual(namespace, soup.math.namespace) self.assertEqual(namespace, soup.msqrt.namespace) def test_xml_declaration_becomes_comment(self): markup = '' soup = self.soup(markup) self.assertTrue(isinstance(soup.contents[0], Comment)) self.assertEqual(soup.contents[0], '?xml version="1.0" encoding="utf-8"?') self.assertEqual("html", soup.contents[0].next_element.name) def skipIf(condition, reason): def nothing(test, *args, **kwargs): return None def decorator(test_item): if condition: return nothing else: return test_item return decorator PK@N#]j0site-packages/bs4/tests/test_builder_registry.pynu["""Tests of the builder registry.""" import unittest import warnings from bs4 import BeautifulSoup from bs4.builder import ( builder_registry as registry, HTMLParserTreeBuilder, TreeBuilderRegistry, ) try: from bs4.builder import HTML5TreeBuilder HTML5LIB_PRESENT = True except ImportError: HTML5LIB_PRESENT = False try: from bs4.builder import ( LXMLTreeBuilderForXML, LXMLTreeBuilder, ) LXML_PRESENT = True except ImportError: LXML_PRESENT = False class BuiltInRegistryTest(unittest.TestCase): """Test the built-in registry with the default builders registered.""" def test_combination(self): if LXML_PRESENT: self.assertEqual(registry.lookup('fast', 'html'), LXMLTreeBuilder) if LXML_PRESENT: self.assertEqual(registry.lookup('permissive', 'xml'), LXMLTreeBuilderForXML) self.assertEqual(registry.lookup('strict', 'html'), HTMLParserTreeBuilder) if HTML5LIB_PRESENT: self.assertEqual(registry.lookup('html5lib', 'html'), HTML5TreeBuilder) def test_lookup_by_markup_type(self): if LXML_PRESENT: self.assertEqual(registry.lookup('html'), LXMLTreeBuilder) self.assertEqual(registry.lookup('xml'), LXMLTreeBuilderForXML) else: self.assertEqual(registry.lookup('xml'), None) if HTML5LIB_PRESENT: self.assertEqual(registry.lookup('html'), HTML5TreeBuilder) else: self.assertEqual(registry.lookup('html'), HTMLParserTreeBuilder) def test_named_library(self): if LXML_PRESENT: self.assertEqual(registry.lookup('lxml', 'xml'), LXMLTreeBuilderForXML) self.assertEqual(registry.lookup('lxml', 'html'), LXMLTreeBuilder) if HTML5LIB_PRESENT: self.assertEqual(registry.lookup('html5lib'), HTML5TreeBuilder) self.assertEqual(registry.lookup('html.parser'), HTMLParserTreeBuilder) def test_beautifulsoup_constructor_does_lookup(self): with warnings.catch_warnings(record=True) as w: # This will create a warning about not explicitly # specifying a parser, but we'll ignore it. # You can pass in a string. BeautifulSoup("", features="html") # Or a list of strings. BeautifulSoup("", features=["html", "fast"]) # You'll get an exception if BS can't find an appropriate # builder. self.assertRaises(ValueError, BeautifulSoup, "", features="no-such-feature") class RegistryTest(unittest.TestCase): """Test the TreeBuilderRegistry class in general.""" def setUp(self): self.registry = TreeBuilderRegistry() def builder_for_features(self, *feature_list): cls = type('Builder_' + '_'.join(feature_list), (object,), {'features' : feature_list}) self.registry.register(cls) return cls def test_register_with_no_features(self): builder = self.builder_for_features() # Since the builder advertises no features, you can't find it # by looking up features. self.assertEqual(self.registry.lookup('foo'), None) # But you can find it by doing a lookup with no features, if # this happens to be the only registered builder. self.assertEqual(self.registry.lookup(), builder) def test_register_with_features_makes_lookup_succeed(self): builder = self.builder_for_features('foo', 'bar') self.assertEqual(self.registry.lookup('foo'), builder) self.assertEqual(self.registry.lookup('bar'), builder) def test_lookup_fails_when_no_builder_implements_feature(self): builder = self.builder_for_features('foo', 'bar') self.assertEqual(self.registry.lookup('baz'), None) def test_lookup_gets_most_recent_registration_when_no_feature_specified(self): builder1 = self.builder_for_features('foo') builder2 = self.builder_for_features('bar') self.assertEqual(self.registry.lookup(), builder2) def test_lookup_fails_when_no_tree_builders_registered(self): self.assertEqual(self.registry.lookup(), None) def test_lookup_gets_most_recent_builder_supporting_all_features(self): has_one = self.builder_for_features('foo') has_the_other = self.builder_for_features('bar') has_both_early = self.builder_for_features('foo', 'bar', 'baz') has_both_late = self.builder_for_features('foo', 'bar', 'quux') lacks_one = self.builder_for_features('bar') has_the_other = self.builder_for_features('foo') # There are two builders featuring 'foo' and 'bar', but # the one that also features 'quux' was registered later. self.assertEqual(self.registry.lookup('foo', 'bar'), has_both_late) # There is only one builder featuring 'foo', 'bar', and 'baz'. self.assertEqual(self.registry.lookup('foo', 'bar', 'baz'), has_both_early) def test_lookup_fails_when_cannot_reconcile_requested_features(self): builder1 = self.builder_for_features('foo', 'bar') builder2 = self.builder_for_features('foo', 'baz') self.assertEqual(self.registry.lookup('bar', 'baz'), None) PK@N#]llA`A`%site-packages/bs4/tests/test_soup.pycnu[ Wc@sdZddlmZddlZddlZddlZddlZddlmZm Z ddl m Z m Z m Z mZddlZddlmZmZmZddlmZmZddlZy ddlmZmZeZWnek rZeZnXejd d ko#ejdkZ d efd YZ!defdYZ"defdYZ"defdYZ#dej$fdYZ%defdYZ&dej$fdYZ'defdYZ(dej$fdYZ)dS(s#Tests of Beautiful Soup as a whole.i(t set_traceN(t BeautifulSouptBeautifulStoneSoup(tCharsetMetaAttributeValuetContentMetaAttributeValuet SoupStrainertNamespacedAttribute(tEntitySubstitutiont UnicodeDammittEncodingDetector(tSoupTesttskipIf(tLXMLTreeBuildertLXMLTreeBuilderForXMLiiitTestConstructorcBs#eZdZdZdZRS(cCs/d}|j|}|jd|jjdS(Nu

éé

uéé(tsoupt assertEqualth1tstring(tselftdataR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_short_unicode_input*scCs/d}|j|}|jd|jjdS(Nu

foobar

ufoobar(RRRR(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_embedded_null/scCs>djd}|j|ddg}|jd|jdS(Nu Räksmörgåssutf-8texclude_encodingss windows-1252(tencodeRRtoriginal_encoding(Rt utf8_dataR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_exclude_encodings4s(t__name__t __module__RRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyR(s  t TestWarningscBsJeZedZdZdZdZdZdZdZ RS(cCs'|jtjd }|j|dS(NiP(t startswithRtNO_PARSER_SPECIFIED_WARNINGt assertTrue(Rtstis_theretv((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt_no_parser_specified<scCsNtjdt}|jd}WdQXt|dj}|j|dS(Ntrecords
i(twarningstcatch_warningstTrueRtstrtmessaget_assert_no_parser_specified(RtwRtmsg((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt#test_warning_if_no_parser_specified@scCsQtjdt}|jdd}WdQXt|dj}|j|dS(NR&sthtmli(R'R(R)RR*R+R,(RR-RR.((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt*test_warning_if_parser_specified_too_vagueFscCsAtjdt}|jdd}WdQX|jg|dS(NR&ss html.parser(R'R(R)RR(RR-R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt,test_no_warning_if_explicit_parser_specifiedLsc Cstjdt"}|jddtd}WdQXt|dj}|jd|k|jd|k|jd|j dS(NR&stparseOnlyThesetbit parse_onlys( R'R(R)RRR*R+R!RR(RR-RR.((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt)test_parseOnlyThese_renamed_to_parse_onlyQs !cCstjdt"}d}|j|dd}WdQXt|dj}|jd|k|jd|k|jd|jdS(NR&sét fromEncodingtutf8it from_encoding( R'R(R)RR*R+R!RR(RR-R8RR.((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt*test_fromEncoding_renamed_to_from_encodingYscCs |jt|jddtdS(Nstno_such_argument(t assertRaisest TypeErrorRR)(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt"test_unrecognized_keyword_argumentbs( RRR)R%R/R1R2R6R:R>(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyR:s      cBs5eZdZdZdZdZdZRS(cCstj}|j}zTtjdt}|j|}WdQXt|dj}|j d|kWd|j Xtjdt}|j|}WdQX|j dt |dS(NR&islooks like a filename( ttempfiletNamedTemporaryFiletnameR'R(R)RR*R+R!tcloseRtlen(Rt filehandletfilenameR-RR.((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_disk_file_warninghs   cCsKtjdt}|jd}WdQX|jtd|DdS(NR&shttp://www.crummybytes.com/css$|]}dt|jkVqdS(slooks like a URLN(R*R+(t.0R-((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pys }s(R'R(R)RR!tany(Rt warning_listR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_url_warning_with_bytes_urlxscCsKtjdt}|jd}WdQX|jtd|DdS(NR&uhttp://www.crummyunicode.com/css$|]}dt|jkVqdS(slooks like a URLN(R*R+(RGR-((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pys s(R'R(R)RR!RH(RRIR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt!test_url_warning_with_unicode_urlscCsKtjdt}|jd}WdQX|jtd|DdS(NR&s$http://www.crummybytes.com/ is greatcss$|]}dt|jkVqdS(slooks like a URLN(R*R+(RGR-((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pys s(R'R(R)Rt assertFalseRH(RRIR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt%test_url_warning_with_bytes_and_spacescCsKtjdt}|jd}WdQX|jtd|DdS(NR&u%http://www.crummyuncode.com/ is greatcss$|]}dt|jkVqdS(slooks like a URLN(R*R+(RGR-((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pys s(R'R(R)RRLRH(RRIR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt'test_url_warning_with_unicode_and_spaces(RRRFRJRKRMRN(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRfs     tTestSelectiveParsingcBseZdZRS(cCsAd}td}|j|d|}|j|jddS(Ns&NoYesNoYes YesR4R5sYesYes Yes(RRRR(RtmarkuptstrainerR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_parse_with_soupstrainers (RRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyROstTestEntitySubstitutioncBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZRS(s1Standalone tests of the EntitySubstitution class.cCs t|_dS(N(Rtsub(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytsetUpscCs&d}|j|jj|ddS(Nufoo∀☃õbarufoo∀☃õbar(RRTtsubstitute_html(RR"((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_simple_html_substitutionscCs5d}t|}|j|jj|jddS(Nsfoos‘’foo“”(RRRTRVRP(Rtquotestdammit((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_smart_quote_substitutions cCs)d}|j|jj|t|dS(NsWelcome to "my bar"(RRTtsubstitute_xmltFalse(RR"((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytItest_xml_converstion_includes_no_quotes_if_make_quoted_attribute_is_falsescCsB|j|jjdtd|j|jjdtddS(NtWelcomes "Welcome"s Bob's Bars "Bob's Bar"(RRTR[R)(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt6test_xml_attribute_quoting_normally_uses_double_quotesscCs)d}|j|jj|tddS(NsWelcome to "my bar"s'Welcome to "my bar"'(RRTR[R)(RR"((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytOtest_xml_attribute_quoting_uses_single_quotes_when_value_contains_double_quotesscCs)d}|j|jj|tddS(NsWelcome to "Bob's Bar"s""Welcome to "Bob's Bar""(RRTR[R)(RR"((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytbtest_xml_attribute_quoting_escapes_single_quotes_when_value_contains_both_single_and_double_quotesscCs&d}|j|jj||dS(NsWelcome to "Bob's Bar"(RRTR[(Rtquoted((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt<test_xml_quotes_arent_escaped_when_value_is_not_being_quotedscCs |j|jjdddS(Nsfoosfoo<bar>(RRTR[(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt'test_xml_quoting_handles_angle_bracketsscCs |j|jjdddS(NsAT&TsAT&T(RRTR[(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt#test_xml_quoting_handles_ampersandsscCs |j|jjdddS(Ns ÁT&Ts&Aacute;T&T(RRTR[(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytEtest_xml_quoting_including_ampersands_when_they_are_part_of_an_entityscCs |j|jjdddS(Ns ÁT&TsÁT&T(RRTt"substitute_xml_containing_entities(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytDtest_xml_quoting_ignoring_ampersands_when_they_are_part_of_an_entityscCs&d}|j|jj||dS(s:There's no need to do this except inside attribute values.s Bob's "bar"N(RRTRV(Rttext((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt test_quotes_not_html_substituteds(RRt__doc__RURWRZR]R_R`RaRcRdReRfRhRj(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRSs            tTestEncodingConversioncBsMeZdZdZdZdZdZeeddZ RS(cCsHtt|jd|_|jjd|_|j|jddS(NuUSacré bleu!sutf-8sUSacré bleu!(tsuperRlRUt unicode_dataRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRUs  cCstjj}tjtjzd}|tj_d}|j|}|j}|jt |t |j ||j |j|j |j jdWdtjtj|tj_XdS(NcSsdS(N(tNone(R*((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytnoopss asutf-8(tbs4RYtchardet_dammittloggingtdisabletWARNINGRtdecodeR!t isinstancetunicodeRt document_forRtlowertNOTSET(RtchardetRptasciitsoup_from_asciitunicode_output((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_ascii_in_unicode_outs    cCsX|j|j}|j|j|j|j|jjd|j|jddS(Nu Sacré bleu!(RRnRRvtfooRRRo(Rtsoup_from_unicode((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_unicode_in_unicode_outscCsE|j|j}|j|j|j|j|jjddS(Nu Sacré bleu!(RRRRvRnRR(Rtsoup_from_utf8((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_utf8_in_unicode_out scCs2|j|j}|j|jd|jdS(Nsutf-8(RRnRRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt test_utf8_outssQBad HTMLParser detected; skipping test of non-ASCII characters in attribute name.cCs8d}|j|j|jjd|jddS(Nu
R8(RRtdivR(RRP((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt1test_attribute_name_containing_unicode_characterss( RRRURRRRR tPYTHON_3_PRE_3_2R(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRls    tTestUnicodeDammitcBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZRS(s"Standalone tests of UnicodeDammit.cCs)d}t|}|j|j|dS(NuI'm already Unicode! ☃(RRtunicode_markup(RRPRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_unicode_input"s cCs)d}t|}|j|jddS(Nsu‘’“”(RRR(RRPRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_smart_quotes_to_unicode's cCs/d}t|dd}|j|jddS(Nstsmart_quotes_totxmls+‘’“”(RRR(RRPRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt!test_smart_quotes_to_xml_entities-scCs/d}t|dd}|j|jddS(NsRR0s'‘’“”(RRR(RRPRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt"test_smart_quotes_to_html_entities3scCs/d}t|dd}|j|jddS(NsRR}s''""(RRR(RRPRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_smart_quotes_to_ascii9scCsBd}t|}|j|jjd|j|jddS(NsSacré bleu! ☃sutf-8uSacré bleu! ☃(RRRRzR(RR8RY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_detect_utf8?s cCsHd}t|dg}|j|jjd|j|jddS(Nss iso-8859-8uםולש(RRRRzR(RthebrewRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_convert_hebrewFscCsKd}t|}|j|jjd|j|jjd|dS(Nsケータイ Watchsutf-8(RRRRzRR(Rtutf_8RY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt/test_dont_see_smart_quotes_where_there_are_noneLs cCs>djd}t|dg}|j|jjddS(Nu Räksmörgåssutf-8s iso-8859-8(RRRRRz(RRRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt test_ignore_inappropriate_codecsRscCsXdjd}xBdddgD]1}t||g}|j|jjdqWdS(Nu Räksmörgåssutf-8s.utf8s...s utF---16.!(RRRRRz(RRt bad_encodingRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_ignore_invalid_codecsWscCsldjd}t|ddg}|j|jjdt|dddg}|j|jddS(Nu Räksmörgåssutf-8Rs windows-1252(RRRRRzRo(RRRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyR]s cCs1td}t|j}d|ks-tdS(Ns'uutf-�(R tlistt encodingstAssertionError(RtdetectedR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytPtest_encoding_detector_replaces_junk_in_encoding_name_with_replacement_characterks cCs:x3dD]+}t|dt}|jd|jqWdS(Ns&s&s$s#tis_htmlseuc-jp(s&s&s$s#(RR)RR(RRRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt test_detect_html5_style_meta_tagqs cCsd}tjj}tjtjzmd}|tj_t|}|jt|j |j d|j kt |d}|j |j Wdtjtj |tj_XdS(NsT بتر ѐcSsdS(N(Ro(R*((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRpsu�s html.parser(RqRYRrRsRtRuRRR)tcontains_replacement_charactersR!RRR{(RtdocR|RpRYR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt"test_last_ditch_entity_replacement|s    cCs<d}t|}|jd|j|jd|jdS(Ns<a></a>u áésutf-16le(RRRR(RRRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_byte_order_mark_removeds cCsndjd}djd}|||}|jt|jdtj|}|jd|jddS(Nu☃iR8u“Hi, I like Windows!”t windows_1252u+☃☃☃“Hi, I like Windows!”☃☃☃u ☃☃☃(RR<tUnicodeDecodeErrorRvRt detwingleR(RR8RRtfixed((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_detwingles cCsYxRdD]J}|jd}|j|jdtj|}|j||qWdS(Nuœuₓu𐐓R8s(uœuₓu𐐓(RR!tendswithRRR(Rttricky_unicode_chartinputtoutput((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt+test_detwingle_ignores_multibyte_characterss (RRRkRRRRRRRRRRRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRs$             #  tTestNamedspacedAttributecBs#eZdZdZdZRS(cCs#tdd}|j|ddS(Ntxmlns(RRoR(Rta((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_name_may_be_nonescCs#tdd}|jd|dS(NRR4sa:b(RR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt6test_attribute_is_equivalent_to_colon_separated_stringscCstddd}tddd}|j||tddd}|j||tddd}|j||tddd}|j||dS(NRR4tctz(RRRotassertNotEqual(RRR4Rtdte((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt;test_attributes_are_equivalent_if_prefix_and_name_identicals(RRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRs  t)TestAttributeValueWithCharsetSubstitutioncBseZdZdZRS(cCsLtd}|jd||jd|j|jd|jddS(Nseuc-jpR8(RRtoriginal_valueR(Rtvalue((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt!test_content_meta_attribute_values cCsLtd}|jd||jd|j|jd|jddS(Nstext/html; charset=euc-jpstext/html; charset=utf8R8(RRRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRs (RRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRs (ii(*RktpdbRRstunittesttsysR?RqRRt bs4.elementRRRRt bs4.dammitRRR t bs4.testingR R R't bs4.builderR R R)t LXML_PRESENTt ImportErrorRR\t version_infoRRRROtTestCaseRSRlRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyts4    "    ",/ E<PK@N#]5M``%site-packages/bs4/tests/test_soup.pyonu[ Wc@sdZddlmZddlZddlZddlZddlZddlmZm Z ddl m Z m Z m Z mZddlZddlmZmZmZddlmZmZddlZy ddlmZmZeZWnek rZeZnXejd d ko#ejdkZ d efd YZ!defdYZ"defdYZ"defdYZ#dej$fdYZ%defdYZ&dej$fdYZ'defdYZ(dej$fdYZ)dS(s#Tests of Beautiful Soup as a whole.i(t set_traceN(t BeautifulSouptBeautifulStoneSoup(tCharsetMetaAttributeValuetContentMetaAttributeValuet SoupStrainertNamespacedAttribute(tEntitySubstitutiont UnicodeDammittEncodingDetector(tSoupTesttskipIf(tLXMLTreeBuildertLXMLTreeBuilderForXMLiiitTestConstructorcBs#eZdZdZdZRS(cCs/d}|j|}|jd|jjdS(Nu

éé

uéé(tsoupt assertEqualth1tstring(tselftdataR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_short_unicode_input*scCs/d}|j|}|jd|jjdS(Nu

foobar

ufoobar(RRRR(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_embedded_null/scCs>djd}|j|ddg}|jd|jdS(Nu Räksmörgåssutf-8texclude_encodingss windows-1252(tencodeRRtoriginal_encoding(Rt utf8_dataR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_exclude_encodings4s(t__name__t __module__RRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyR(s  t TestWarningscBsJeZedZdZdZdZdZdZdZ RS(cCs'|jtjd }|j|dS(NiP(t startswithRtNO_PARSER_SPECIFIED_WARNINGt assertTrue(Rtstis_theretv((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt_no_parser_specified<scCsNtjdt}|jd}WdQXt|dj}|j|dS(Ntrecordsi(twarningstcatch_warningstTrueRtstrtmessaget_assert_no_parser_specified(RtwRtmsg((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt#test_warning_if_no_parser_specified@scCsQtjdt}|jdd}WdQXt|dj}|j|dS(NR&sthtmli(R'R(R)RR*R+R,(RR-RR.((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt*test_warning_if_parser_specified_too_vagueFscCsAtjdt}|jdd}WdQX|jg|dS(NR&ss html.parser(R'R(R)RR(RR-R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt,test_no_warning_if_explicit_parser_specifiedLsc Cstjdt"}|jddtd}WdQXt|dj}|jd|k|jd|k|jd|j dS(NR&stparseOnlyThesetbit parse_onlys( R'R(R)RRR*R+R!RR(RR-RR.((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt)test_parseOnlyThese_renamed_to_parse_onlyQs !cCstjdt"}d}|j|dd}WdQXt|dj}|jd|k|jd|k|jd|jdS(NR&sét fromEncodingtutf8it from_encoding( R'R(R)RR*R+R!RR(RR-R8RR.((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt*test_fromEncoding_renamed_to_from_encodingYscCs |jt|jddtdS(Nstno_such_argument(t assertRaisest TypeErrorRR)(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt"test_unrecognized_keyword_argumentbs( RRR)R%R/R1R2R6R:R>(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyR:s      cBs5eZdZdZdZdZdZRS(cCstj}|j}zTtjdt}|j|}WdQXt|dj}|j d|kWd|j Xtjdt}|j|}WdQX|j dt |dS(NR&islooks like a filename( ttempfiletNamedTemporaryFiletnameR'R(R)RR*R+R!tcloseRtlen(Rt filehandletfilenameR-RR.((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_disk_file_warninghs   cCsKtjdt}|jd}WdQX|jtd|DdS(NR&shttp://www.crummybytes.com/css$|]}dt|jkVqdS(slooks like a URLN(R*R+(t.0R-((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pys }s(R'R(R)RR!tany(Rt warning_listR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_url_warning_with_bytes_urlxscCsKtjdt}|jd}WdQX|jtd|DdS(NR&uhttp://www.crummyunicode.com/css$|]}dt|jkVqdS(slooks like a URLN(R*R+(RGR-((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pys s(R'R(R)RR!RH(RRIR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt!test_url_warning_with_unicode_urlscCsKtjdt}|jd}WdQX|jtd|DdS(NR&s$http://www.crummybytes.com/ is greatcss$|]}dt|jkVqdS(slooks like a URLN(R*R+(RGR-((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pys s(R'R(R)Rt assertFalseRH(RRIR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt%test_url_warning_with_bytes_and_spacescCsKtjdt}|jd}WdQX|jtd|DdS(NR&u%http://www.crummyuncode.com/ is greatcss$|]}dt|jkVqdS(slooks like a URLN(R*R+(RGR-((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pys s(R'R(R)RRLRH(RRIR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt'test_url_warning_with_unicode_and_spaces(RRRFRJRKRMRN(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRfs     tTestSelectiveParsingcBseZdZRS(cCsAd}td}|j|d|}|j|jddS(Ns&NoYesNoYes YesR4R5sYesYes Yes(RRRR(RtmarkuptstrainerR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_parse_with_soupstrainers (RRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyROstTestEntitySubstitutioncBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZRS(s1Standalone tests of the EntitySubstitution class.cCs t|_dS(N(Rtsub(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytsetUpscCs&d}|j|jj|ddS(Nufoo∀☃õbarufoo∀☃õbar(RRTtsubstitute_html(RR"((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_simple_html_substitutionscCs5d}t|}|j|jj|jddS(Nsfoos‘’foo“”(RRRTRVRP(Rtquotestdammit((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_smart_quote_substitutions cCs)d}|j|jj|t|dS(NsWelcome to "my bar"(RRTtsubstitute_xmltFalse(RR"((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytItest_xml_converstion_includes_no_quotes_if_make_quoted_attribute_is_falsescCsB|j|jjdtd|j|jjdtddS(NtWelcomes "Welcome"s Bob's Bars "Bob's Bar"(RRTR[R)(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt6test_xml_attribute_quoting_normally_uses_double_quotesscCs)d}|j|jj|tddS(NsWelcome to "my bar"s'Welcome to "my bar"'(RRTR[R)(RR"((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytOtest_xml_attribute_quoting_uses_single_quotes_when_value_contains_double_quotesscCs)d}|j|jj|tddS(NsWelcome to "Bob's Bar"s""Welcome to "Bob's Bar""(RRTR[R)(RR"((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytbtest_xml_attribute_quoting_escapes_single_quotes_when_value_contains_both_single_and_double_quotesscCs&d}|j|jj||dS(NsWelcome to "Bob's Bar"(RRTR[(Rtquoted((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt<test_xml_quotes_arent_escaped_when_value_is_not_being_quotedscCs |j|jjdddS(Nsfoosfoo<bar>(RRTR[(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt'test_xml_quoting_handles_angle_bracketsscCs |j|jjdddS(NsAT&TsAT&T(RRTR[(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt#test_xml_quoting_handles_ampersandsscCs |j|jjdddS(Ns ÁT&Ts&Aacute;T&T(RRTR[(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytEtest_xml_quoting_including_ampersands_when_they_are_part_of_an_entityscCs |j|jjdddS(Ns ÁT&TsÁT&T(RRTt"substitute_xml_containing_entities(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytDtest_xml_quoting_ignoring_ampersands_when_they_are_part_of_an_entityscCs&d}|j|jj||dS(s:There's no need to do this except inside attribute values.s Bob's "bar"N(RRTRV(Rttext((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt test_quotes_not_html_substituteds(RRt__doc__RURWRZR]R_R`RaRcRdReRfRhRj(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRSs            tTestEncodingConversioncBsMeZdZdZdZdZdZeeddZ RS(cCsHtt|jd|_|jjd|_|j|jddS(NuUSacré bleu!sutf-8sUSacré bleu!(tsuperRlRUt unicode_dataRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRUs  cCstjj}tjtjzd}|tj_d}|j|}|j}|jt |t |j ||j |j|j |j jdWdtjtj|tj_XdS(NcSsdS(N(tNone(R*((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytnoopss asutf-8(tbs4RYtchardet_dammittloggingtdisabletWARNINGRtdecodeR!t isinstancetunicodeRt document_forRtlowertNOTSET(RtchardetRptasciitsoup_from_asciitunicode_output((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_ascii_in_unicode_outs    cCsX|j|j}|j|j|j|j|jjd|j|jddS(Nu Sacré bleu!(RRnRRvtfooRRRo(Rtsoup_from_unicode((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_unicode_in_unicode_outscCsE|j|j}|j|j|j|j|jjddS(Nu Sacré bleu!(RRRRvRnRR(Rtsoup_from_utf8((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_utf8_in_unicode_out scCs2|j|j}|j|jd|jdS(Nsutf-8(RRnRRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt test_utf8_outssQBad HTMLParser detected; skipping test of non-ASCII characters in attribute name.cCs8d}|j|j|jjd|jddS(Nu
R8(RRtdivR(RRP((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt1test_attribute_name_containing_unicode_characterss( RRRURRRRR tPYTHON_3_PRE_3_2R(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRls    tTestUnicodeDammitcBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZRS(s"Standalone tests of UnicodeDammit.cCs)d}t|}|j|j|dS(NuI'm already Unicode! ☃(RRtunicode_markup(RRPRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_unicode_input"s cCs)d}t|}|j|jddS(Nsu‘’“”(RRR(RRPRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_smart_quotes_to_unicode's cCs/d}t|dd}|j|jddS(Nstsmart_quotes_totxmls+‘’“”(RRR(RRPRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt!test_smart_quotes_to_xml_entities-scCs/d}t|dd}|j|jddS(NsRR0s'‘’“”(RRR(RRPRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt"test_smart_quotes_to_html_entities3scCs/d}t|dd}|j|jddS(NsRR}s''""(RRR(RRPRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_smart_quotes_to_ascii9scCsBd}t|}|j|jjd|j|jddS(NsSacré bleu! ☃sutf-8uSacré bleu! ☃(RRRRzR(RR8RY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_detect_utf8?s cCsHd}t|dg}|j|jjd|j|jddS(Nss iso-8859-8uםולש(RRRRzR(RthebrewRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_convert_hebrewFscCsKd}t|}|j|jjd|j|jjd|dS(Nsケータイ Watchsutf-8(RRRRzRR(Rtutf_8RY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt/test_dont_see_smart_quotes_where_there_are_noneLs cCs>djd}t|dg}|j|jjddS(Nu Räksmörgåssutf-8s iso-8859-8(RRRRRz(RRRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt test_ignore_inappropriate_codecsRscCsXdjd}xBdddgD]1}t||g}|j|jjdqWdS(Nu Räksmörgåssutf-8s.utf8s...s utF---16.!(RRRRRz(RRt bad_encodingRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_ignore_invalid_codecsWscCsldjd}t|ddg}|j|jjdt|dddg}|j|jddS(Nu Räksmörgåssutf-8Rs windows-1252(RRRRRzRo(RRRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyR]s cCstd}t|j}dS(Ns'(R tlistt encodings(RtdetectedR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pytPtest_encoding_detector_replaces_junk_in_encoding_name_with_replacement_characterks cCs:x3dD]+}t|dt}|jd|jqWdS(Ns&s&s$s#tis_htmlseuc-jp(s&s&s$s#(RR)RR(RRRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt test_detect_html5_style_meta_tagqs cCsd}tjj}tjtjzmd}|tj_t|}|jt|j |j d|j kt |d}|j |j Wdtjtj |tj_XdS(NsT بتر ѐcSsdS(N(Ro(R*((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRpsu�s html.parser(RqRYRrRsRtRuRRR)tcontains_replacement_charactersR!RRR{(RtdocR|RpRYR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt"test_last_ditch_entity_replacement|s    cCs<d}t|}|jd|j|jd|jdS(Ns<a></a>u áésutf-16le(RRRR(RRRY((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_byte_order_mark_removeds cCsndjd}djd}|||}|jt|jdtj|}|jd|jddS(Nu☃iR8u“Hi, I like Windows!”t windows_1252u+☃☃☃“Hi, I like Windows!”☃☃☃u ☃☃☃(RR<tUnicodeDecodeErrorRvRt detwingleR(RR8RRtfixed((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_detwingles cCsYxRdD]J}|jd}|j|jdtj|}|j||qWdS(Nuœuₓu𐐓R8s(uœuₓu𐐓(RR!tendswithRRR(Rttricky_unicode_chartinputtoutput((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt+test_detwingle_ignores_multibyte_characterss (RRRkRRRRRRRRRRRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRs$             #  tTestNamedspacedAttributecBs#eZdZdZdZRS(cCs#tdd}|j|ddS(Ntxmlns(RRoR(Rta((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyttest_name_may_be_nonescCs#tdd}|jd|dS(NRR4sa:b(RR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt6test_attribute_is_equivalent_to_colon_separated_stringscCstddd}tddd}|j||tddd}|j||tddd}|j||tddd}|j||dS(NRR4tctz(RRRotassertNotEqual(RRR4Rtdte((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt;test_attributes_are_equivalent_if_prefix_and_name_identicals(RRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRs  t)TestAttributeValueWithCharsetSubstitutioncBseZdZdZRS(cCsLtd}|jd||jd|j|jd|jddS(Nseuc-jpR8(RRtoriginal_valueR(Rtvalue((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyt!test_content_meta_attribute_values cCsLtd}|jd||jd|j|jd|jddS(Nstext/html; charset=euc-jpstext/html; charset=utf8R8(RRRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRs (RRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyRs (ii(*RktpdbRRstunittesttsysR?RqRRt bs4.elementRRRRt bs4.dammitRRR t bs4.testingR R R't bs4.builderR R R)t LXML_PRESENTt ImportErrorRR\t version_infoRRRROtTestCaseRSRlRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_soup.pyts4    "    ",/ E<PK@N#]B!$site-packages/bs4/tests/__init__.pyonu[ CNc@s dZdS(sThe beautifulsoup tests.N(t__doc__(((s6/usr/lib/python2.7/site-packages/bs4/tests/__init__.pytsPK@N#]S%site-packages/bs4/tests/test_tree.pyonu[ _[c@sdZddlmZddlZddlZddlZddlZddlmZddl m Z m Z ddl m Z mZmZmZmZmZmZmZddlmZmZe jdek Ze jd ek Zd efd YZd efd YZdefdYZdefdYZdefdYZ defdYZ!defdYZ"defdYZ#defdYZ$de$fdYZ%de$fdYZ&d efd!YZ'd"e'fd#YZ(d$e'fd%YZ)d&efd'YZ*d(efd)YZ+d*efd+YZ,d,efd-YZ-d.efd/YZ.d0efd1YZ/d2efd3YZ0d4efd5YZ1d6efd7YZ2dS(8s8Tests for Beautiful Soup's tree traversal methods. The tree traversal methods are the main advantage of using Beautiful Soup over just using a parser. Different parsers will build different Beautiful Soup trees given the same markup, but all Beautiful Soup trees can be traversed with the methods tested here. i(t set_traceN(t BeautifulSoup(tbuilder_registrytHTMLParserTreeBuilder(tPY3KtCDatatCommentt DeclarationtDoctypetNavigableStringt SoupStrainertTag(tSoupTesttskipIftxmltlxmltTreeTestcBseZdZdZRS(cCs*|jg|D]}|j^q |dS(sMake sure that the given tags have the correct text. This is used in tests that define a bunch of tags, each containing a single string, and then select certain strings by some mechanism. N(t assertEqualtstring(tselfttagst should_matchttag((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt assertSelects+scCs+|jg|D]}|d^q |dS(sMake sure that the given tags have the correct IDs. This is used in tests that define a bunch of tags, each containing a single string, and then select certain strings by some mechanism. tidN(R(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytassertSelectsIDs4s(t__name__t __module__RR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR)s tTestFindcBs;eZdZdZdZdZdZdZRS(sBasic tests of the find() method. find() just calls find_all() with limit=1, so it's not tested all that thouroughly here. cCs/|jd}|j|jdjddS(Ns 1234tbt2(tsoupRtfindR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_find_tagEscCs/|jd}|j|jddddS(Nu

Räksmörgås

Ru Räksmörgås(RRR (RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_unicode_text_findIscCs<|jd}t||jd|jddjdS(Nu&

here it is

s here it isRu Räksmörgås(RtstrRR ttext(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_unicode_attribute_findMs cCs/|jd}|jdt|jdS(s)Test an optimization that finds all tags.sfoobariN(RRtlentfind_all(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_everythingSscCs2|jd}|jdt|jddS(s;Test an optimization that finds all tags with a given name.sfoobarbazitaN(RRR&R'(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_everything_with_nameXs(RRt__doc__R!R"R%R(R*(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR>s     t TestFindAllcBs;eZdZdZdZdZdZdZRS(s%Basic tests of the find_all() method.cCs|jd}|j|jdddg|j|jdddg|j|jdddgddg|j|jdtjdddd g|j|jdtddd gd S( s'You can search the tree for text nodes.sFoobarRtbarubarR$tFoouFoos.*u»N(RRR'tretcompiletTrue(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_text_nodes`s"cCs|jd}|j|jddddddg|j|jddddg|j|jddd dddd d g|j|jddd dddd d gd S(s7You can limit the number of items returned by find_all.s(12345R)tlimitit1Rt3ii t4t5iN(RRR'(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_limitps("(cCsQ|jd}|j|ddddg|j|jdddgdS( Ns!123R)R3iR4RtfooR5(RRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_calling_a_tag_is_calling_findall|scCs?|jd}g}|j||jg|j|dS(Ns(RtappendRR'(RRtl((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytTtest_find_all_with_self_referential_data_structure_does_not_cause_infinite_recursions cCs|jd}|jd}|jt|d|jt}|jt|d|jdd}|jt|ddS(s%All find_all calls return a ResultSetsR)tsourceR$R9N(RR't assertTruethasattrR1(RRtresult((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_resultsets(RRR+R2R8R:R=RB(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR,]s    tTestFindAllBasicNamespacescBseZdZRS(cCsU|jd}|jd|jdj|jd|jdidd6jdS(Ns04R6s mathml:msqrtR)tattrstredssvg:fill(RRR Rtname(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_by_namespaced_names(RRRG(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRCstTestFindAllByNamecBsqeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z RS( s&Test ways of finding tags by tag name.cCs)tt|j|jd|_dS(NsFirst tag. Second tag. Third Nested tag. tag.(tsuperRtsetUpRttree(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJscCs&|j|jjdddgdS(NR)s First tag.s Nested tag.(RRKR'(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_tag_namescCs|j|jjddddg|j|jjddtddg|j|jjddtjdddgdS(NR)R$s First tag.s Nested tag.R(RRKR'R1R/R0(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_name_and_texts"cCs&|j|jjjddgdS(NR)s Nested tag.(RRKtcR'(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_find_all_on_non_root_elementscCs#|j|jdddgdS(NR)s First tag.s Nested tag.(RRK(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_calling_element_invokes_find_allscCs,|j|jjtdddgdS(NR)s First tag.s Nested tag.(RRKR'R (R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_tag_strainerscCs/|j|jjddgdddgdS(NR)Rs First tag.s Second tag.s Nested tag.(RRKR'(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_tag_namesscCs7|j|jjitd6td6dddgdS(NR)Rs First tag.s Second tag.s Nested tag.(RRKR'R1(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_tag_dictscCs2|j|jjtjddddgdS(Ns^[ab]$s First tag.s Second tag.s Nested tag.(RRKR'R/R0(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_tag_rescCs;d}|jd}|j|j|ddgdS(NcSs|j|jdkS(NR(RFtget(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytid_matches_namessMatch 1. Does not match. Match 2.sMatch 1.sMatch 2.(RRR'(RRVRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt'test_find_all_with_tags_matching_methods   cCs|jd}|jdd}|jdtjd}|jdddg\}}|jd|j|jd|j|jd|j|jd|jdS(NsH
1
2
3
tdivsa dsa bR5R4(RR R/R0R'RR(RRtr1tr2tr3tr4((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_find_with_multi_valued_attributes (RRR+RJRLRMRORPRQRRRSRTRWR](((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRHs         tTestFindAllByAttributecBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZRS(cCs5|jd}|j|jddddgdS(Ns Matching a. Non-matching Matching b.a. Rtfirsts Matching a.s Matching b.(RRR'(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_attribute_names cCsdjd}djd}|j|}|j|jg|jd||j|jg|jd|jd|j|jg|jd|dgdS(Nuםולשtutf8uttitlessomething else(tencodeRRR)R'tdecode(RtpeacetdataR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_find_all_by_utf8_attribute_values "+cCs~|jd}|j|jdddg|j|jdidd6dg|j|jdidd6d gdS( Ns0 Name match. Class match. Non-match. A tag called 'name1'. RFtname1sA tag called 'name1'.RDs Name match.tclass2tclasss Class match.(RRR'(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_attribute_dicts   cCs|jd}|j|jddddg|j|jddddg|j|jddd dg|j|jdddg|j|jd dddg|j|jdddg|j|jdd dgdS( Ns Class 1. Class 2. Class 1. Class 3 and 4. R)tclass_R4sClass 1.RNR5sClass 3 and 4.R6RD(RRR'(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_classs """"cCs|jd}|jddtjd}|j|dg|jddtjd}|j|dg|jddtjd}|j|dgdS(Ns#Found ittgarRltosFound itR)so b(RR'R/R0R(RRKtf((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt0test_find_by_class_when_multiple_classes_present-scCs|jd}|j|jdtjddgd}|j|jd|gd}|j|jd|dgdS(NsFound itR)tbasFound itcSst|dkS(Ni(R&(tvalue((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytbig_attribute_value@scSst|dkS(Ni(R&(Rs((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytsmall_attribute_valueEs(RRR'R/R0(RRRtRu((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt:test_find_all_with_non_dictionary_for_attrs_finds_by_class;s(  cCs|jd}|jd\}}|j||g|jdd|j|g|jdd|j|g|jddd|j|g|jdd|jg|jdddS(Ns*R)R9R-Rlsfoo barsbar foo(RR'R(RRR)ta2((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt:test_find_all_with_string_for_attrs_finds_multiple_classesKs""cCsE|jd}tdidd6}|j|j|dgdS(Nsi Match. Non-match.RDR_RsMatch.(RR RR'(RRKtstrainer((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt'test_find_all_by_attribute_soupstrainerWs cCs5|jd}|j|jddddgdS(NsID present. No ID present. ID is empty.R)RsNo ID present.(RRR'tNone(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt$test_find_all_with_missing_attribute_s cCs5|jd}|j|jdtddgdS(NsID present. No ID present. ID is empty.Rs ID present.s ID is empty.(RRR'R1(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt$test_find_all_with_defined_attributegs cCsW|jd}ddg}|j|jdd||j|jdd|dS(Ns[Unquoted attribute. Quoted attribute.sUnquoted attribute.sQuoted attribute.RiR4(RRR'(RRKtexpected((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt$test_find_all_with_numeric_attributeps   cCs>|jd}|j|jddddgddgdS(Ns1 2 3 No ID.RR4R5R6(RRR'(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt(test_find_all_with_list_attribute_valuesys cCs>|jd}|j|jdtjdddgdS(NsOne a. Two as. Mixed as and bs. One b. No ID.Rs^a+$sOne a.sTwo as.(RRR'R/R0(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt5test_find_all_with_regular_expression_attribute_values cCs||jd}|j}|j|g|jddd|jg|jddd|jg|jddddS(NsfoobarfooR)R$R9R-(RR)RR'(RRR)((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt'test_find_by_name_and_containing_strings  "cCs;|jd}|j|jd|jddddS(Ns"foofooR)R$R9(RRR'(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt=test_find_by_name_and_containing_string_when_string_is_buriedscCsc|jd}|j}|j|g|jdddd|jg|jdddddS(Ns"foofooRiR$R9iR-(RR)RR'(RRR)((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt,test_find_by_attribute_and_containing_strings %(RRR`RgRkRmRqRvRxRzR|R}RRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR^s          t TestIndexcBseZdZdZRS(sTest Tag.indexcCsk|jd}|j}x6t|jD]%\}}|j||j|q(W|jt|jddS(Nsh
Identical Not identical Identical Identical with child Also not identical Identical with child
i(RRXt enumeratetcontentsRtindext assertRaisest ValueError(RRKRXtitelement((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_indexs   (RRR+R(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRstTestParentOperationscBs_eZdZdZdZdZdZdZdZdZ dZ d Z RS( s;Test navigation and searching through an element's parents.cCs8tt|j|jd|_|jj|_dS(Ns1
          Start here
      (RIRRJRRKRtstart(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJs cCs[|j|jjdd|j|jjjdd|j|jjjjdddS(NRtbottomtmiddlettop(RRtparent(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_parentscCs*|jjd}|j|j|jdS(Ni(RKRRR(Rttop_tag((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_parent_of_top_tag_is_soup_objectscCs|jd|jjdS(N(RR{RKR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_soup_object_has_no_parentscCsN|j|jjddddg|j|jjddddgdS(NtulRRRR(RRt find_parents(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_parentsscCsJ|j|jjddd|j|jjddddddS(NRRRR(RRt find_parent(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_parents cCs/|jjdd}|j|jjddS(NR$s Start hereR(RKR RRRF(RR$((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_parent_of_text_elementscCs6|jjdd}|j|jddddS(NR$s Start hereRRR(RKR RR(RR$((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_text_element_find_parentscCs[g|jjD]+}|dk r d|jkr |d^q }|j|dddgdS(NRRRR(RtparentsR{RDR(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_parent_generators+( RRR+RJRRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs       t ProximityTestcBseZdZRS(cCs)tt|j|jd|_dS(NsgOneTwoThree(RIRRJRRK(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJs(RRRJ(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRstTestNextOperationscBsPeZdZdZdZdZdZdZdZdZ RS(cCs&tt|j|jj|_dS(N(RIRRJRKRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJscCs7|j|jjd|j|jjjdddS(NtOneRR(RRt next_element(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_nextscCs,|jjdd}|j|jddS(NR$tThree(RKR RRR{(Rtlast((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_next_of_last_item_is_nonescCs|j|jjddS(N(RRKRR{(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_next_of_root_is_nonescCs[|j|jjdddg|jjdd|j|jjdddgdS(NRtTwoRRi(RRt find_all_next(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_nexts"cCsC|j|jjddd|j|jjddddS(NRRRR$R(RRt find_next(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_next s cCsT|jjdd}|j|jdjd|j|jdddgdS(NR$RRRR(RKR RRRRR(RR$((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_next_for_text_elementscCse|jjdd}g|jD] }|^q}|\}}|j|dd|j|ddS(NR$RRR5R(RKR t next_elementsR(RRtnodet successorsRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_next_generators  ( RRRJRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs       tTestPreviousOperationscBsPeZdZdZdZdZdZdZdZdZ RS(cCs/tt|j|jjdd|_dS(NR$R(RIRRJRKR tend(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJscCs7|j|jjdd|j|jjjddS(NRR5R(RRtprevious_element(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_previous!scCs)|jjd}|j|jddS(Nthtml(RKR RRR{(RR_((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt#test_previous_of_first_item_is_none%scCsdS(N((R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_previous_of_root_is_none)scCsK|j|jjddddg|j|jjdddgdS(NRRRRRi(RRtfind_all_previous(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_previous/scCsC|j|jjddd|j|jjddddS(NRRR5R$R(RRt find_previous(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_previous7s cCsW|jjdd}|j|jdjd|j|jddddgdS(NR$RRRR(RKR RRRRR(RR$((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt#test_find_previous_for_text_element;scCs|jjdd}g|jD] }|^q}|\}}}}|j|dd|j|jd|j|jd|j|jddS(NR$RRR4tbodytheadR(RKR tprevious_elementsRRF(RRRt predecessorsRRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_previous_generatorAs( RRRJRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs       t SiblingTestcBseZdZRS(cCsJtt|jd}tjdjd|}|j||_dS(Ns s\n\s*t(RIRRJR/R0tsubRRK(Rtmarkup((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJPs (RRRJ(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRNstTestNextSiblingcBsGeZdZdZdZdZdZdZdZRS(cCs/tt|j|jjdd|_dS(NRR4(RIRRJRKR R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJfscCs|j|jjddS(N(RRKt next_siblingR{(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_next_sibling_of_root_is_nonejscCsU|j|jjdd|j|jjjdd|j|jjdddS(NRRR5s1.1(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_next_siblingmscCsm|j|jjjd|jjdd}|j|jd|jjdd}|j|jddS(NRs1.1R6(RRKRRR{R (Rt nested_spant last_span((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_next_sibling_may_not_existts cCs$|j|jjddddS(NtspanRR(RRtfind_next_sibling(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_next_sibling}scCsK|j|jjddddg|j|jjdddgdS(NRRR5R6R(RRtfind_next_siblings(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_next_siblingsscCs|jd}|jdd}|j|jjd|j|jjd|j|jddg|j|jddd|j|jddddS(NsFoobarbazR$R.RtbazR-tnonesuch( RR RRRFRRRR{(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_next_sibling_for_text_elements( RRRJRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRds     tTestPreviousSiblingcBsGeZdZdZdZdZdZdZdZRS(cCs/tt|j|jjdd|_dS(NRR6(RIRRJRKR R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJscCs|j|jjddS(N(RRKtprevious_siblingR{(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_previous_sibling_of_root_is_nonescCsU|j|jjdd|j|jjjdd|j|jjdddS(NRR5Rs3.1(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_previous_siblingscCsm|j|jjjd|jjdd}|j|jd|jjdd}|j|jddS(NRs1.1R4(RRKRRR{R (RRt first_span((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt#test_previous_sibling_may_not_exists cCs$|j|jjddddS(NRRR5(RRtfind_previous_sibling(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_previous_siblingscCsK|j|jjddddg|j|jjdddgdS(NRR5RR4R(RRtfind_previous_siblings(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_previous_siblingsscCs|jd}|jdd}|j|jjd|j|jjd|j|jddg|j|jddd|j|jddddS(NsFoobarbazR$RRR.R-R( RR RRRFRRRR{(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt&test_previous_sibling_for_text_elements( RRRJRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs     tTestTagCreationcBs2eZdZdZdZdZdZRS(s$Test the ability to create new tags.cCs|jd}|jddddidd6}|jt|t|jd|j|jtdddd|j|jd|j dS(NRR9R-RRDsa nameRF( Rtnew_tagR?t isinstanceR RRFtdictRDR{R(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_new_tags ""cCstrbtdd}|jd}|jd}|jd|j|jd|jntdd}|jd}|jd}|jd|j|jd|jdS( NRslxml-xmltbrtps
      s

      s html.parsers

      (tXML_BUILDER_PRESENTRRRRc(Rtxml_souptxml_brtxml_pt html_soupthtml_brthtml_p((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_tag_inherits_self_closing_rules_from_builderscCsH|jd}|jd}|jd||jt|tdS(NRR9(Rt new_stringRR?RR (RRts((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt'test_new_string_creates_navigablestringscCsK|jd}|jdt}|jd||jt|tdS(NRR9(RRRRR?R(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt3test_new_string_can_create_navigablestring_subclasss(RRR+RRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs    tTestTreeModificationcBs^eZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!d Z"d!Z#d"Z$d#Z%d$Z&d%Z'RS(&cCs|jd}d|jd<|j|j|jd|jd=|j|j|jdd|jd<|j|j|jddS( NsiRssR9tid2s(RR)RRdt document_for(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_modifications   cCstjd}|jdd|}t||d}t||d}d|d<|jjd||jjd ||j|jjd dS( NRs tbuilderR)tolshttp://foo.com/threfiis4
        (RtlookupRR RtinsertRRc(RRRR)R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_new_tag_creations  cCsd}|j|}|jdd}|j}|jddj|j|j|j||j|j|jddS(NsT

        Don't leave me here.

        Don't leave!

        RRsD

        Don't leave me .

        Don't leave!here

        (RR RR;RRRdR(RtdocRt second_paratbold((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_append_to_contents_moves_tags cCsDd}|j|}|j}|j|j}|j||dS(Ns(RR)t replace_withRNR(RR$RR)tnew_a((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_replace_with_returns_thing_that_was_replaceds  cCs>d}|j|}|j}|j}|j||dS(Ns(RR)tunwrapR(RR$RR)R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt+test_unwrap_returns_thing_that_was_replaceds   cCse|jd}|j}|j|jd|j|jt|j|jt|j |j dS(NsFooBar( RR)textractRR{RRRRRRN(RRR)((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytItest_replace_with_and_unwrap_give_useful_exception_when_tag_has_no_parents   cCsQd}|j|}|j}|jj||j|j|j|dS(Ns-Foo(RRNRRRdR(RR$RRN((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_replace_tag_with_itself's  cCs5d}|j|}|jt|jj|jdS(Ns(RRRRRR)(RR$R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_replace_tag_with_its_parent_raises_exception.scCs8d}|j|}|jt|jjd|jdS(Nsi(RRRR)R(RR$R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt,test_insert_tag_into_itself_raises_exception3sc Cs|jd}d}|j|}|jd|x|jD]}q>Wt|j\}}}}|jd|j|jd|j|jd|j|jd|jdS( sInserting one BeautifulSoup object into another actually inserts all of its children -- you'll never combine BeautifulSoup objects. s-

        And now, a word:

        And we're back.

        s

        p2

        p3

        isAnd now, a word:tp2tp3sAnd we're back.N(RRt descendantstlisttchildrent assertEqualsR( RRR$t to_insertRtp1RRtp4((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_insert_beautifulsoup_object_inserts_children8scCsx|jd}|j}|jd}|jdd|j\}}|jd|jd|jd|jjdS(Ns

        onethree

        iittwoRtthree(RR)RRt replaceWithRRR(RRR)Rtlefttright((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt3test_replace_with_maintains_next_element_throughoutLs    cCs|jd}|jddjd|jdd}|j}|j|j||j|j||j|jj||j|jddS(Ns Argh!R$sArgh!sHooray!( RR RRRRRRR{(RRtnew_textR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_replace_final_node[s cCs|jd}|jjdd|j|j|jd|jdd}|j|jd|j|jj||j|j d|j|j j ||j|j d|j|j|j dS(NsArgh!isHooray!s!Argh!Hooray!R$sArgh!( RRRRRdRR RRRRR{RN(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_consecutive_text_nodeses cCsr|jd}|jjdd|jjdd|jddg|jj|j|jjdjddS(NsiR-R9(RR)RRRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_insert_stringzs cCsW|j}|jdd|}t||d}|jdd|jjd||j|j|jd|j}|j|j ||j|j ||j dd }|j|j ||j|j ||j}|j|j ||j|j ||j dd}|j|j||j|j ||j|j |dS( Ns%Findlady!Rtmagictagittheis=Findthelady!R$tFind(tdefault_builderRR RR)RRdRRRRR RRRNR(RRRt magic_tagtb_tagR tc_tagR#((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_insert_tags,    cCsBd}|j|}|jj|j|j||jdS(Ns(RR)R;RRRd(RRfR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt*test_append_child_thats_already_at_the_endscCsEd}|j|}|jjd|j|jd|jdS(Nsis(RR)RtdRRd(RRfR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt$test_move_tag_to_beginning_of_parentscCs?|jd}|jjdd|jt|jddS(Ns
        itContentss
        Contents
        (RRRRR#(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt&test_insert_works_on_empty_element_tagscCs|jd}|jjd|jjd|j|j|jd|jj|j|j|j|jddS(NsfoobartBAZtQUUXsQUUXfooBAZbarsQUUXbarfooBAZ(RRt insert_beforeR)RRdR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_insert_beforescCs|jd}|jjd|jjd|j|j|jd|jj|j|j|j|jddS(NsfoobarR/R0sfooQUUXbarBAZsQUUXbarfooBAZ(RRt insert_afterR)RRdR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_insert_afterscCss|jd}|jd}|jd}|jt|j||jt|j||jt|j|dS(NRR)(RRRRRR3tNotImplementedError(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt:test_insert_after_raises_exception_if_after_has_no_meanings cCss|jd}|jd}|jd}|jt|j||jt|j||jt|j|dS(NRR)(RRRRRR1R5(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytFtest_insert_before_raises_notimplementederror_if_before_has_no_meanings cCs|jd}|jd\}}|j||j|j|jd|j|jd|j|j|j|j|j d|j|j ddS(Ns;

        There's no business like show business

        Rs0

        There's business like no business

        tnos business( RR'RRRdRRR{RRR(RRR8tshow((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_replace_withs    cCsBd}|j|}|jj|j|jd|jdS(Nss(RRRRNRRd(RRfR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_replace_first_childscCsBd}|j|}|jj|j|jd|jdS(Nss(RRNRRRRd(RRfR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_replace_last_childscCsx|jd}|j}|j}|j||j|j|jd|j|jd|j|j ddj d|j|j d|j|j d|j|j d|j|j|j|j|j d|j|j j |j|j|j d|j dd}|j}|j|j ||j|j ||j|j ||j|j |dS(NsQWereservetherighttorefuseservices-WerefusetoserviceR$RtWetto(RRRpRRRdRRR{R RRRRR)tetg(RRt remove_tagtmove_tagtto_texttg_tag((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_nested_tag_replace_withs.      cCsI|jd}|jj|j|jd|j|jjddS(NsI

        Unneeded formatting is unneeded

        sUnneeded formatting is unneeded(RtemRRR{RR$(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_unwraps   cCsc|jd}|jj|jd}|j|jd|j|j|jddS(NsI wish I was bold.RsI wish I was bold.(RRtwrapRRRdR(RRRs((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_wrap"s cCsH|jd}|jjj|j|j|j|jddS(NsI wish I was bold.sI wish I was bold.(RRRRHRRdR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_wrap_extracts_tag_from_elsewhere)scCsd|jd}|jjj|j|jdt|jj|j|j|jddS(Ns+I like being bold.I wish I was bold.is+I like being bold.I wish I was bold.( RRRRHRR&RRdR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt&test_wrap_puts_new_contents_at_the_end/s cCs;|jd}|jt|jjd|jddj}|j|jd|j|jd|jt|jjd|j|jd|j|j d|j|j j d|jdd }|jdd }|j|j ||j|j ||j|j ||j|j |dS( NsRSome content. More content.iRtnavs6Some content. More content.siR$sSome content. s More content.(RRR&RRR R RdRR{RRRR(RRt extractedt content_1t content_2((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_extract7s" cCs|jd}|jj}|jj}|jd}|jd}|jj||jj||j|j|j||jj|j||jjdS(NsfoobarR9R-(RR)RRRR;R R(RRtfoo_1tbar_1tfoo_2tbar_2((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt4test_extract_distinguishes_between_identical_stringsPs    cCsU|jd}g|jdD]}|jj^q|jdt|jdS(Nsv tscripts (RR'RVR RtunicodeR(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_extract_multiples_of_same_tagas )cCs?|jd}|jdj|jd|jddS(Ns hi R(RR R RR{(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytBtest_extract_works_when_element_is_surrounded_by_identical_stringsqs cCs|jd}|j}|jj|jt|jjd|jt|d|j }|jdt |jdt|jdS(s Tag.clear()s4

        String Italicized and another

        iRt decomposeN( RR)RtclearRR&RR?R@RFR1(RRR)RF((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_clearzs   cCs]|jd}d|j_|j|jjdgd|j_|j|jjdgdS(sTag.string = 'string's R9R-N(RR)RRRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_string_sets   cCs>|jd}|jj|j_|j|jjddS(Nsfoobarsbarbar(RRNRRRR)Rc(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt/test_string_set_does_not_affect_original_stringscCsG|jd}td}||j_|jt|jjtdS(NsR9(RRR)RR?R(RRtcdata((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt)test_set_string_preserves_class_of_strings  ((RRRRRRRR R R R RRRR R!R)R*R,R.R2R4R6R7R:R;R<RERGRIRJRKRPRURXRYR\R]R^R`(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRsL                   $          tTestElementObjectscBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZRS(s)Test various features of element objects.cCsw|jd}|jt|jd|jt|d|jt|jd|jt|jjddS(s3The length of an element is its number of children.s123iiN(RRR&RR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_lens cCsj|jd}|j|j|jd|j|jj|jdjd|j|jddS(s2Accessing a Python member .foo invokes find('foo')sRRN(RRRR RR)R{(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_member_access_invokes_finds(cCsg|jd}tjdt}|j}WdQX|j|j||jdt|djdS(Nstrecordsp.bTag is deprecated, use .find("b") instead. If you really were looking for a tag called bTag, use .find("bTag")i( Rtwarningstcatch_warningsR1tbTagRRR#tmessage(RRtwR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_deprecated_member_accessscCsE|jd}|j|jjd|j|jjddS(shas_attr() checks for the presence of an attribute. Please note note: has_attr() is different from __in__. has_attr() checks the tag's attributes and __in__ checks the tag's chidlren. stattrtattr2N(RR?R9thas_attrt assertFalse(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_has_attrscCsd}|j|ddS(Ns%s%(tassertSoupEquals(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt.test_attributes_come_out_in_alphabetical_orderscCs)|jd}|j|jjddS(Ns fooR9(RRRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_stringscCs)|jd}|j|jjddS(Ns(RRRRR{(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_empty_tag_has_no_stringscCs|jd}|j|jjd|jd}|j|jjd|jd}|jjdd|j|jjddS(Nsfoo
        sfoobar
        s foo
        iR-(RRRRR{R)R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt-test_tag_with_multiple_children_has_no_stringscCs<|jd}|j|jjd|j|jddS(NsfooR9(RRR)R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt)test_tag_with_recursive_string_has_stringscCsH|jd}|j|jj|jd}|j|jjdS(s7Only a tag containing a single text node has a .string.sfeosN(RRnRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_lack_of_stringscCs|jd}|j|jjd|j|jjdtd|j|jjdd|j|jjddtddS( sBTag.text and Tag.get_text(sep=u"") -> all child text, concatenatedsar t sar t tstriptartt,s a,r, , t sa,r,tN(RRR)R$tget_textR1(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_all_texts cCsg|jd}|j|jd|j|jdttfd|j|jddddS(Nsfoobartfoobarttypest fooIGNOREbar(RRRzR RR{(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_get_text_ignores_commentss cCs2|jd}|jddgt|jdS(NsfoobarR9R-(RRRtstrings(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_all_strings_ignores_commentss(RRR+RbRcRjRoRqRrRsRtRuRvR{RR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRas          tTestCDAtaListAttributescBsVeZdZdZdZdZdZdZdZdZ dZ RS( s0Testing cdata-list attributes like 'class'. cCs-|jd}|jdg|jddS(NsR9Rj(RRR)(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_single_value_becomes_list scCs0|jd}|jddg|jddS(NsR9R-Rj(RRR)(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_multiple_values_becomes_listscCs3|jd}|jdddg|jddS(NsR9R-RRj(RRR)(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt2test_multiple_values_separated_by_weird_whitespacescCs,|jd}|jd|jjdS(Nss(RRR)Rc(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt,test_attributes_joined_into_string_on_outputscCs2|jd}|jdg|jjddS(Nssabc defR(RRR)tget_attribute_list(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_get_attribute_listscCs0|jd}|jddg|jddS(Ns(
        s ISO-8859-1sUTF-8saccept-charset(RRtform(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_accept_charset!scCs0d}|j|}|jd|jddS(Ns)sISO-8859-1 UTF-8saccept-charset(RRR)(RRfR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt-test_cdata_attribute_applying_only_to_one_tag%scsH|jdj|jdjfd}|jt|dS(NRcs d_dS(NR9(RF((R(s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytt0s(RRRR{RFRtAttributeError(RR((Rs7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt'test_string_has_immutable_name_property-s( RRR+RRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR s       tTestPersistencecBs_eZdZdZdZdZdZdZdZdZ dZ d Z RS( s*Testing features like pickle and deepcopy.cCs5tt|jd|_|j|j|_dS(Nsy Beautiful Soup: We called him Tortoise because he taught us. foo bar (RIRRJtpageRRK(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJ7s cCsZtj|jd}tj|}|j|jt|j|j|jjdS(Ni(tpickletdumpsRKtloadsRt __class__RRd(Rtdumpedtloaded((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_pickle_and_unpickle_identityKscCs5tj|j}|j|j|jjdS(N(tcopytdeepcopyRKRRd(Rtcopied((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_deepcopy_identitySscCsQtdd}|j}|j}|jdt||j||jdS(Ns

         

        s html.parseru

         

        (Rtoriginal_encodingt__copy__RRW(RRtencodingR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_copy_preserves_encodingXs   cCsYd}|j|}tj|tj}tj|}|j|j|jdS(Nu (RRRtHIGHEST_PROTOCOLRRRd(RRRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_unicode_pickle_s cCsd}|j|}|jdd}tj|}|j|||jd|j|jd|j|jd|j|jd|j|jd|j dS(NuFooBarRR.( RR RRR{RRtassertNotEqualRR(RRRts1ts2((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_copy_navigablestring_is_not_attached_to_treegscCsWd}|j|}|j}tj|}|j|||jt|tdS(Nu(RRRRR?RR(RRRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt0test_copy_navigablestring_subclass_has_same_typess  cCs8d}|j|}tj|}|j||dS(Nu)
        FooBar
        end(RRR(RRRt soup_copy((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_copy_entire_soup{scCsd}|j|}|j}tj|}|jt|t||j|||j||k|jd|j|jd|j|jd|j ddj |j d|j ddj dS(Nu)
        FooBar
        endRtBar( RRXRRRWRnR{RRR RR(RRRRXtdiv_copy((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_copy_tag_copies_contentss ( RRR+RJRRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR4s       tTestSubstitutionscBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZRS(cCsDd}|j|}|jdd}|j||jddS(Nu#<<Sacré bleu!>>t formattertminimal(RRdRR(RRRtdecoded((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_default_formatter_is_minimalscCsDd}|j|}|jdd}|j||jddS(Nu'
        <<Sacré bleu!>>RRs.
        <<Sacré bleu!>>(RRdRR(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_formatter_htmls cCsDd}|j|}|jdd}|j||jddS(Nu'
        <<Sacré bleu!>>Rthtml5s-
        <<Sacré bleu!>>(RRdRR(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_formatter_html5s cCsDd}|j|}|jdd}|j||jddS(Nu#<<Sacré bleu!>>RR(RRdRR(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_formatter_minimalscCsDd}|j|}|jdd}|j||jddS(Nu#<<Sacré bleu!>>Ru<>(RRdR{RR(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_formatter_nulls  cCsGd}|j|}|jdd}|j||jddS(Nu!<foo>bar
        RcSs |jS(N(tupper(tx((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytsuBAR
        (RRdRR(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_formatter_customs cCsd}|j|}|j}d}|j||j|j||jddd}|j||jdd|j||jddd}|j||jdddS( Nu%eu)eRRu/eRu%EcSs |jS(N(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs(RR)RRdR{(RRRR)texpect_minimalt expect_htmlt expect_upper((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt)test_formatter_is_run_on_attribute_valuess cCs2d}t|dj}|jd|kdS(NsO s html.parsers < < hey > >(RRcR?(RRtencoded((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt2test_formatter_skips_script_tag_for_html_documentsscCs2d}t|dj}|jd|kdS(NsF s html.parsers < < hey > >(RRcR?(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_formatter_skips_style_tag_for_html_documentsscCs,|jd}|jd|jjdS(Ns*
        foo
          	bar
          
          
        baz u/
        foo
          	bar
          
          
        baz
        (RRRXtprettify(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt,test_prettify_leaves_preformatted_text_alonescCs;tdd}|jdd}|jd|kdS(Nsfoos html.parserRcSs |jS(N(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRstFOO(RRR?(RRtpretty((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt(test_prettify_accepts_formatter_functionscCs/|jd}|jtt|jdS(Ns(RRRWttypeR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt(test_prettify_outputs_unicode_by_defaultscCs2|jd}|jtt|jddS(Nssutf-8(RRtbytesRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_prettify_can_encode_datascCsDd}|j|}|jjd}|j||jddS(NuSacré bleu!sutf-8(RRRcR(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt,test_html_entity_substitution_off_by_defaultscCsd}|j|}|j|jdd|jd}|jd|k|jd}|jd|k|jd}|jd |k|jd jd }|jd |kdS( NsEtcontentstext/html; charset=x-sjissutf-8s charset=utf-8teuc_jpscharset=euc_jps shift-jisscharset=shift-jissutf-16scharset=utf-16(RRtmetaRcR?Rd(Rtmeta_tagRtutf_8Rt shift_jistutf_16_u((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_encoding_substitution scCsEd}td}|j|d|}|j|jdjddS(Ns`
        foo
        tpret parse_onlyi(R RRRRF(RRRyR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt;test_encoding_substitution_doesnt_happen_if_tag_is_strained$s (RRRRRRRRRRRRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs          t TestEncodingcBsVeZdZdZdZdZdZdZdZdZ dZ RS( s0Test the ability to encode objects into strings.cCsAd}|j|}|j|jjjddjddS(Nu sutf-8u☃(RRRRRc(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_unicode_string_can_be_encoded2scCs>d}|j|}|j|jjd|jddS(Nu sutf-8(RRRRc(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_tag_containing_unicode_string_can_be_encoded8scCs5d}|j|}|j|jjdddS(Nu tasciis(RRRRc(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt<test_encoding_substitutes_unrecognized_characters_by_default>scCs5d}|j|}|jt|jddddS(Nu Rterrorststrict(RRtUnicodeEncodeErrorRc(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_encoding_can_be_made_strictCscCs2d}|j|}|jd|jjdS(Nu u☃(RRRtdecode_contents(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_decode_contentsIscCsAd}|j|}|jdjd|jjdddS(Nu u☃RaR(RRRcRtencode_contents(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_encode_contentsNs cCs;d}|j|}|jdjd|jjdS(Nu u☃Ra(RRRcRtrenderContents(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_deprecated_renderContentsUscCsNd}|j|}tr4|j|t|n|jdt|dS(Nu s \u2603(RRRtrepr(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_repr[s ( RRR+RRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR/s       tTestNavigableStringSubclassescBs,eZdZdZdZdZRS(cCsx|jd}td}|jd||jt|d|j|jddd|j|jdddS(NRR9isR$i(RRRRR#R R(RRR_((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_cdataes  csvd_fd}jd}td}|jd|jd|jd|jdjdS( skText inside a CData object is passed into the formatter. But the return value is ignored. icsjd7_dS(NisBITTER FAILURE(tcount(targs(R(s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt incrementvsRs<><><>is<><>]]>RN(RRRRRRc(RRRR_((Rs7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_cdata_is_never_formattedos  cCsEtd}|jd}|jd||j|jddS(NR9Ris (RRRRRc(RtdoctypeR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_doctype_ends_in_newlines cCs&td}|jd|jdS(NR9s(RRt output_ready(RR+((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_declarations (RRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRcs  tTestSoupSelectorcBseZdZdZdZeZdZdZdZdZ dZ dZ d Z d Z d Zd Zd ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!dZ"d Z#d!Z$d"Z%d#Z&d$Z'd%Z(d&Z)d'Z*d(Z+d)Z,d*Z-d+Z.d,Z/d-Z0d.Z1d/Z2d0Z3d1Z4d2Z5d3Z6d4Z7d5Z8d6Z9d7Z:d8Z;d9Z<RS(:s The title Hello there.

        An H1

        Some text

        Some more text

        An H2

        Another

        Bob

        Another H2

        me span1a1 span1a2 test span2a1

        English

        English UK

        English US

        French

        cCst|jd|_dS(Ns html.parser(RtHTMLR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJscKsvg|jj||D]}|d^q}|j|j|j||d|dj|dj|fdS(NRs$Selector %s, expected [%s], got [%s]s, (RtselecttsortRtjoin(Rtselectort expected_idstkwargsteltel_ids((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs ,   cGs+x$|D]\}}|j||qWdS(N(t assertSelect(RttestsRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytassertSelectMultiplescCs]|jjd}|jt|d|j|djd|j|djdgdS(NRbiiu The title(RRRR&RFR(Rtels((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_one_tag_onescCsv|jjd}|jt|dx!|D]}|j|jdq/W|jjd}|jd|ddS(NRXitmainR(RRRR&RFt select_one(RRRXR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_one_tag_manys  cCs&|jjd}|jd|dS(Ntnonexistenttag(RRRR{(Rtmatch((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt(test_select_one_returns_none_if_no_matchscCs,|jjd}|jdddgdS(Nsdiv divtinnertdata1(RRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_tag_in_tag_onescCs1x*dD]"}|j|ddddgqWdS( Nshtml divs html body divsbody divRRRtfooter(shtml divs html body divsbody div(R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_tag_in_tag_manys cCs[|jddgdd|jdddgdd|jdd ddd gdd dS( Nshtml divRR3is html body divRisbody divRR i (R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_limitscCs&|jt|jjdddS(Ntdeli(RR&RR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_tag_no_matchscCs|jt|jjddS(Nstag%t(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_invalid_tagscCs|jdddgdS(Nscustom-dashed-tagtdash1tdash2(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_select_dashed_tag_idsscCsE|jjd}|j|djd|j|ddddS(Nscustom-dashed-tag[id="dash2"]iscustom-dashed-tagRR(RRRRF(Rtdashed((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_select_dashed_by_idscCs'|j|jjddjddS(Nsbody > custom-dashed-tagiu Hello there.(RRRR$(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_dashed_tag_textscCs,|j|jjd|jjddS(Nscustom-dashed-tag(RRRR'(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt#test_select_dashed_matches_find_allscCs)|jddgfdddgfdS(Nth1theader1th2theader2theader3(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_header_tags s cCsoxhd D]`}|jj|}|jt|d|j|djd|j|dddgqWdS( Ns.onepsp.oneps html p.onepiiRRjtonep(s.onepsp.oneps html p.onep(RRRR&RF(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_class_ones  cCs,|jjd}|jt|ddS(Nsdiv.onepi(RRRR&(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_class_mismatched_tagscCs(x!dD]}|j|dgqWdS(Ns div#inners#inners div div#innerR(s div#inners#inners div div#inner(R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_one_ids cCs,|jjd}|jt|ddS(Ns #doesnotexisti(RRRR&(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_bad_idscCs|jjd}|jt|dx!|D]}|j|jdq/W|j|dddg|j|djddS(Ns div#inner piRiRjRi(RRRR&RFRnRm(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_items_in_id#s  cCs7x0dD](}|jt|jj|dqWdS(Ns div#main delsdiv#main div.oopss div div#maini(s div#main delsdiv#main div.oopss div div#main(RR&RR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_a_bunch_of_emptys+s cCs(x!d D]}|j|d gqWdS( Ns.class1sp.class1s.class2sp.class2s.class3sp.class3s html p.class2sdiv#inner .class2tpmulti(s.class1sp.class1s.class2sp.class2s.class3sp.class3s html p.class2sdiv#inner .class2(R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multi_class_support/s cCs(x!dD]}|j|dgqWdS(Ns.class1.class3s.class3.class2s.class1.class2.class3R#(s.class1.class3s.class3.class2s.class1.class2.class3(R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multi_class_selection4s cCs-|jdddg|jddgdS(Ns.s1 > ats1a1ts1a2s .s1 > a spants1a2s1(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_child_selector9scCs|jddgdS(Ns.s1 > a#s1a2 spanR((R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_child_selector_id=scCs|jddgfddgfddgfddgfddgfddgfd dgfd gfd dgfd dgfd dgfdgfdgfdgfdS(Nsp[class="onep"]Rs p[id="p1"]s[class="onep"]s [id="p1"]slink[rel="stylesheet"]tl1slink[type="text/css"]slink[href="blah.css"]slink[href="no-blah.css"]s[rel="stylesheet"]s[type="text/css"]s[href="blah.css"]s[href="no-blah.css"]sp[href="no-blah.css"](R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_equals@s             c Cs|jddgfddgfddgfddgfddgfddgfdd gfd d gfd d gfd d gf dS( Nsp[class~="class1"]R#sp[class~="class2"]sp[class~="class3"]s[class~="class1"]s[class~="class2"]s[class~="class3"]sa[rel~="friend"]tbobs a[rel~="met"]s[rel~="friend"]s [rel~="met"](R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_tildeRs         cCs|jddgfddgfdgfdgfdgfddgfdd d gfd d d gfd d dgfdd dgfddgfdd gfddgf dS(Ns[rel^="style"]R+slink[rel^="style"]snotlink[rel^="notstyle"]s[rel^="notstyle"]slink[rel^="notstyle"]slink[href^="bla"]sa[href^="http://"]R-tmes[href^="http://"]s [id^="p"]R#Rs [id^="m"]Rs div[id^="m"]s a[id^="m"]sdiv[data-tag^="dashed"]R(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_startswith`s        c Csh|jddgfddgfddgfdddddd d d d gfd dgfdgfdS(Ns[href$=".css"]R+slink[href$=".css"]s link[id$="1"]s [id$="1"]RRRR&ts2a1R(Rs div[id$="1"]s[id$="noending"](R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_endswithqs   ! cCs4|jddgfddgfdgfdgfdgfddgfdd d gfd d d gfddgfdd gfddgfddgfddgfdddd ddddddg fddgfdgfdd d dgfdd d gfd dgfd!dd"gfd#d"gfd$dgfdS(%Ns[rel*="style"]R+slink[rel*="style"]snotlink[rel*="notstyle"]s[rel*="notstyle"]slink[rel*="notstyle"]slink[href*="bla"]s[href*="http://"]R-R/s [id*="p"]R#Rs div[id*="m"]Rs a[id*="m"]s[href*=".css"]slink[href*=".css"]s link[id*="1"]s [id*="1"]RRR&R'R1R(Rs div[id*="1"]s[id*="noending"]s [href*="."]s a[href*="."]slink[href*="."]s div[id*="n"]Rs div[id*="nn"]sdiv[data-tag*="edval"](R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_contains{s.           $    cCsG|jddddgfddddgfddgfdgfdS( Ns p[lang|="en"]slang-ens lang-en-gbs lang-en-uss [lang|="en"]s p[lang|="fr"]slang-frs p[lang|="gb"](R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_exact_or_hypens  c Cs}|jddddgfddgfdddgfddd d d gfd d dgfdgfdgfddgfdS(Ns[rel]R+R-R/s link[rel]sa[rel]s[lang]slang-ens lang-en-gbs lang-en-usslang-frsp[class]RR#s[blah]sp[blah]s div[data-tag]R(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_existss   cCs>d}t|d}|jd\}|jd|jdS(Ns]
        nope
        yes
        s html.parsersdiv[style="display: right"]tyes(RRRR(RRRtchosen((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_quoted_space_in_selector_namescCs6|jt|jjd|jt|jjddS(Nsa:no-such-pseudoclasssa:nth-of-type(a)(RR5RR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_unsupported_pseudoclassscCs|jjd}|jt|d|j|djd|jjd}|jt|d|j|djd|jjd}|jt|d|jt|jjddS( Nsdiv#inner p:nth-of-type(1)iiu Some textsdiv#inner p:nth-of-type(3)uAnothersdiv#inner p:nth-of-type(4)sdiv p:nth-of-type(0)(RRRR&RRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_nth_of_typescCsC|jjd}|jt|d|j|djddS(Nsdiv#inner > p:nth-of-type(1)iiu Some text(RRRR&R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_nth_of_type_direct_descendantscCs|jddgdS(Ns#inner > p:nth-of-type(2)R(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_id_child_selector_nth_of_typescCsA|jjddd}|jd}|j|ddgdS(NRXRRRR(RR RR(RRtselected((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_select_on_elementscCs'|jddg|jdgdS(Ns .fancy #innerRs.normal #inner(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_overspecified_child_idscCsY|jddg|jddg|jddg|jg|jjddS(Ns#p1 + h2Rs #p1 + h2 + pR#s#p1 + #header2 + .class1s#p1 + p(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_adjacent_sibling_selectorscCso|jdddg|jddg|jddg|jddg|jg|jjddS( Ns#p1 ~ h2RRs#p1 ~ #header2s #p1 ~ h2 + aR/s#p1 ~ h2 + [rel="me"]s #inner ~ h2(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_general_sibling_selectors cCs|jt|jjddS(Nsh1 >(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_dangling_combinatorscCs|jddddgdS(Ns p[lang] ~ ps lang-en-gbs lang-en-usslang-fr(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt2test_sibling_combinator_wont_select_same_tag_twicescCs|jdddgdS(Nsx, ytxidtyid(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multiple_selectscCs|jdddgdS(Nsx,yRDRE(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_multiple_select_with_no_spacescCs|jdddgdS(Nsx, yRDRE(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt$test_multiple_select_with_more_spacescCs|jddgdS(Nsx, xRD(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multiple_select_duplicatedscCs|jdddgdS(Nsx, y ~ p[lang=fr]RDslang-fr(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multiple_select_siblingscCs|jdddgdS(Nsx, y > zRDtzidb(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt.test_multiple_select_tag_and_direct_descendantscCs&|jdddddddgdS(Ns div > x, y, zRDREtzidaRKtzidabtzidac(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt/test_multiple_select_direct_descendant_and_tags scCs&|jdddddddgdS(Ns div x,y, zRDRERMRKRNRO(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt(test_multiple_select_indirect_descendant scCs6|jt|jjd|jt|jjddS(Ns,x, ysx,,y(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_invalid_multiple_selectscCs|jdddgdS(Nsp[lang=en], p[lang=en-gb]slang-ens lang-en-gb(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multiple_select_attrsscCs|jddddgdS(Ns*x, y > z[id=zida], z[id=zidab], z[id=zidb]RDRKRN(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multiple_select_idsscCs|jdddgdS(Nsbody > div > x, y > zRDRK(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multiple_select_nestedscCsad}t|d}|jd}|jdt|x |jdddgD]}qSWdS(Ns3
        s html.parsers.c1, .c2iRltc1tc2(RRRR&R'(RRRR=R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_select_duplicate_elementss (=RRRRJRRRRRRRR R R RRRRRRRRRR R!R"R$R%R)R*R,R.R0R2R3R4R5R8R9R:R;R<R>R?R@RARBRCRFRGRHRIRJRLRPRQRRRSRTRURX(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRsv1                                                    (3R+tpdbRRRR/Retbs4Rt bs4.builderRRt bs4.elementRRRRRR R R t bs4.testingR R RR{Rt LXML_PRESENTRRR,RCRHR^RRRRRRRRRRRaRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt sF    : ;O3(3--*n+a4*PK@N#]{aa%site-packages/bs4/tests/test_tree.pycnu[ _[c@sdZddlmZddlZddlZddlZddlZddlmZddl m Z m Z ddl m Z mZmZmZmZmZmZmZddlmZmZe jdek Ze jd ek Zd efd YZd efd YZdefdYZdefdYZdefdYZ defdYZ!defdYZ"defdYZ#defdYZ$de$fdYZ%de$fdYZ&d efd!YZ'd"e'fd#YZ(d$e'fd%YZ)d&efd'YZ*d(efd)YZ+d*efd+YZ,d,efd-YZ-d.efd/YZ.d0efd1YZ/d2efd3YZ0d4efd5YZ1d6efd7YZ2dS(8s8Tests for Beautiful Soup's tree traversal methods. The tree traversal methods are the main advantage of using Beautiful Soup over just using a parser. Different parsers will build different Beautiful Soup trees given the same markup, but all Beautiful Soup trees can be traversed with the methods tested here. i(t set_traceN(t BeautifulSoup(tbuilder_registrytHTMLParserTreeBuilder(tPY3KtCDatatCommentt DeclarationtDoctypetNavigableStringt SoupStrainertTag(tSoupTesttskipIftxmltlxmltTreeTestcBseZdZdZRS(cCs*|jg|D]}|j^q |dS(sMake sure that the given tags have the correct text. This is used in tests that define a bunch of tags, each containing a single string, and then select certain strings by some mechanism. N(t assertEqualtstring(tselfttagst should_matchttag((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt assertSelects+scCs+|jg|D]}|d^q |dS(sMake sure that the given tags have the correct IDs. This is used in tests that define a bunch of tags, each containing a single string, and then select certain strings by some mechanism. tidN(R(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytassertSelectsIDs4s(t__name__t __module__RR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR)s tTestFindcBs;eZdZdZdZdZdZdZRS(sBasic tests of the find() method. find() just calls find_all() with limit=1, so it's not tested all that thouroughly here. cCs/|jd}|j|jdjddS(Ns 1234tbt2(tsoupRtfindR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_find_tagEscCs/|jd}|j|jddddS(Nu

        Räksmörgås

        Ru Räksmörgås(RRR (RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_unicode_text_findIscCs<|jd}t||jd|jddjdS(Nu&

        here it is

        s here it isRu Räksmörgås(RtstrRR ttext(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_unicode_attribute_findMs cCs/|jd}|jdt|jdS(s)Test an optimization that finds all tags.sfoobariN(RRtlentfind_all(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_everythingSscCs2|jd}|jdt|jddS(s;Test an optimization that finds all tags with a given name.sfoobarbazitaN(RRR&R'(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_everything_with_nameXs(RRt__doc__R!R"R%R(R*(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR>s     t TestFindAllcBs;eZdZdZdZdZdZdZRS(s%Basic tests of the find_all() method.cCs|jd}|j|jdddg|j|jdddg|j|jdddgddg|j|jdtjdddd g|j|jdtddd gd S( s'You can search the tree for text nodes.sFoobarRtbarubarR$tFoouFoos.*u»N(RRR'tretcompiletTrue(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_text_nodes`s"cCs|jd}|j|jddddddg|j|jddddg|j|jddd dddd d g|j|jddd dddd d gd S(s7You can limit the number of items returned by find_all.s(12345R)tlimitit1Rt3ii t4t5iN(RRR'(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_limitps("(cCsQ|jd}|j|ddddg|j|jdddgdS( Ns!123R)R3iR4RtfooR5(RRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_calling_a_tag_is_calling_findall|scCs?|jd}g}|j||jg|j|dS(Ns(RtappendRR'(RRtl((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytTtest_find_all_with_self_referential_data_structure_does_not_cause_infinite_recursions cCs|jd}|jd}|jt|d|jt}|jt|d|jdd}|jt|ddS(s%All find_all calls return a ResultSetsR)tsourceR$R9N(RR't assertTruethasattrR1(RRtresult((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_resultsets(RRR+R2R8R:R=RB(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR,]s    tTestFindAllBasicNamespacescBseZdZRS(cCsU|jd}|jd|jdj|jd|jdidd6jdS(Ns04R6s mathml:msqrtR)tattrstredssvg:fill(RRR Rtname(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_by_namespaced_names(RRRG(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRCstTestFindAllByNamecBsqeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z RS( s&Test ways of finding tags by tag name.cCs)tt|j|jd|_dS(NsFirst tag. Second tag. Third Nested tag. tag.(tsuperRtsetUpRttree(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJscCs&|j|jjdddgdS(NR)s First tag.s Nested tag.(RRKR'(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_tag_namescCs|j|jjddddg|j|jjddtddg|j|jjddtjdddgdS(NR)R$s First tag.s Nested tag.R(RRKR'R1R/R0(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_name_and_texts"cCs&|j|jjjddgdS(NR)s Nested tag.(RRKtcR'(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_find_all_on_non_root_elementscCs#|j|jdddgdS(NR)s First tag.s Nested tag.(RRK(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_calling_element_invokes_find_allscCs,|j|jjtdddgdS(NR)s First tag.s Nested tag.(RRKR'R (R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_tag_strainerscCs/|j|jjddgdddgdS(NR)Rs First tag.s Second tag.s Nested tag.(RRKR'(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_tag_namesscCs7|j|jjitd6td6dddgdS(NR)Rs First tag.s Second tag.s Nested tag.(RRKR'R1(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_tag_dictscCs2|j|jjtjddddgdS(Ns^[ab]$s First tag.s Second tag.s Nested tag.(RRKR'R/R0(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_tag_rescCs;d}|jd}|j|j|ddgdS(NcSs|j|jdkS(NR(RFtget(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytid_matches_namessMatch 1. Does not match. Match 2.sMatch 1.sMatch 2.(RRR'(RRVRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt'test_find_all_with_tags_matching_methods   cCs|jd}|jdd}|jdtjd}|jdddg\}}|jd|j|jd|j|jd|j|jd|jdS(NsH
        1
        2
        3
        tdivsa dsa bR5R4(RR R/R0R'RR(RRtr1tr2tr3tr4((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_find_with_multi_valued_attributes (RRR+RJRLRMRORPRQRRRSRTRWR](((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRHs         tTestFindAllByAttributecBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZRS(cCs5|jd}|j|jddddgdS(Ns Matching a. Non-matching Matching b.a. Rtfirsts Matching a.s Matching b.(RRR'(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_attribute_names cCsdjd}djd}|j|}|j|jg|jd||j|jg|jd|jd|j|jg|jd|dgdS(Nuםולשtutf8uttitlessomething else(tencodeRRR)R'tdecode(RtpeacetdataR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_find_all_by_utf8_attribute_values "+cCs~|jd}|j|jdddg|j|jdidd6dg|j|jdidd6d gdS( Ns0 Name match. Class match. Non-match. A tag called 'name1'. RFtname1sA tag called 'name1'.RDs Name match.tclass2tclasss Class match.(RRR'(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_attribute_dicts   cCs|jd}|j|jddddg|j|jddddg|j|jddd dg|j|jdddg|j|jd dddg|j|jdddg|j|jdd dgdS( Ns Class 1. Class 2. Class 1. Class 3 and 4. R)tclass_R4sClass 1.RNR5sClass 3 and 4.R6RD(RRR'(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_by_classs """"cCs|jd}|jddtjd}|j|dg|jddtjd}|j|dg|jddtjd}|j|dgdS(Ns#Found ittgarRltosFound itR)so b(RR'R/R0R(RRKtf((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt0test_find_by_class_when_multiple_classes_present-scCs|jd}|j|jdtjddgd}|j|jd|gd}|j|jd|dgdS(NsFound itR)tbasFound itcSst|dkS(Ni(R&(tvalue((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytbig_attribute_value@scSst|dkS(Ni(R&(Rs((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytsmall_attribute_valueEs(RRR'R/R0(RRRtRu((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt:test_find_all_with_non_dictionary_for_attrs_finds_by_class;s(  cCs|jd}|jd\}}|j||g|jdd|j|g|jdd|j|g|jddd|j|g|jdd|jg|jdddS(Ns*R)R9R-Rlsfoo barsbar foo(RR'R(RRR)ta2((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt:test_find_all_with_string_for_attrs_finds_multiple_classesKs""cCsE|jd}tdidd6}|j|j|dgdS(Nsi Match. Non-match.RDR_RsMatch.(RR RR'(RRKtstrainer((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt'test_find_all_by_attribute_soupstrainerWs cCs5|jd}|j|jddddgdS(NsID present. No ID present. ID is empty.R)RsNo ID present.(RRR'tNone(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt$test_find_all_with_missing_attribute_s cCs5|jd}|j|jdtddgdS(NsID present. No ID present. ID is empty.Rs ID present.s ID is empty.(RRR'R1(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt$test_find_all_with_defined_attributegs cCsW|jd}ddg}|j|jdd||j|jdd|dS(Ns[Unquoted attribute. Quoted attribute.sUnquoted attribute.sQuoted attribute.RiR4(RRR'(RRKtexpected((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt$test_find_all_with_numeric_attributeps   cCs>|jd}|j|jddddgddgdS(Ns1 2 3 No ID.RR4R5R6(RRR'(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt(test_find_all_with_list_attribute_valuesys cCs>|jd}|j|jdtjdddgdS(NsOne a. Two as. Mixed as and bs. One b. No ID.Rs^a+$sOne a.sTwo as.(RRR'R/R0(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt5test_find_all_with_regular_expression_attribute_values cCs||jd}|j}|j|g|jddd|jg|jddd|jg|jddddS(NsfoobarfooR)R$R9R-(RR)RR'(RRR)((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt'test_find_by_name_and_containing_strings  "cCs;|jd}|j|jd|jddddS(Ns"foofooR)R$R9(RRR'(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt=test_find_by_name_and_containing_string_when_string_is_buriedscCsc|jd}|j}|j|g|jdddd|jg|jdddddS(Ns"foofooRiR$R9iR-(RR)RR'(RRR)((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt,test_find_by_attribute_and_containing_strings %(RRR`RgRkRmRqRvRxRzR|R}RRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR^s          t TestIndexcBseZdZdZRS(sTest Tag.indexcCsk|jd}|j}x6t|jD]%\}}|j||j|q(W|jt|jddS(Nsh
        Identical Not identical Identical Identical with child Also not identical Identical with child
        i(RRXt enumeratetcontentsRtindext assertRaisest ValueError(RRKRXtitelement((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_indexs   (RRR+R(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRstTestParentOperationscBs_eZdZdZdZdZdZdZdZdZ dZ d Z RS( s;Test navigation and searching through an element's parents.cCs8tt|j|jd|_|jj|_dS(Ns1
                Start here
            (RIRRJRRKRtstart(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJs cCs[|j|jjdd|j|jjjdd|j|jjjjdddS(NRtbottomtmiddlettop(RRtparent(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_parentscCs*|jjd}|j|j|jdS(Ni(RKRRR(Rttop_tag((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_parent_of_top_tag_is_soup_objectscCs|jd|jjdS(N(RR{RKR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_soup_object_has_no_parentscCsN|j|jjddddg|j|jjddddgdS(NtulRRRR(RRt find_parents(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_parentsscCsJ|j|jjddd|j|jjddddddS(NRRRR(RRt find_parent(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_parents cCs/|jjdd}|j|jjddS(NR$s Start hereR(RKR RRRF(RR$((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_parent_of_text_elementscCs6|jjdd}|j|jddddS(NR$s Start hereRRR(RKR RR(RR$((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_text_element_find_parentscCs[g|jjD]+}|dk r d|jkr |d^q }|j|dddgdS(NRRRR(RtparentsR{RDR(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_parent_generators+( RRR+RJRRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs       t ProximityTestcBseZdZRS(cCs)tt|j|jd|_dS(NsgOneTwoThree(RIRRJRRK(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJs(RRRJ(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRstTestNextOperationscBsPeZdZdZdZdZdZdZdZdZ RS(cCs&tt|j|jj|_dS(N(RIRRJRKRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJscCs7|j|jjd|j|jjjdddS(NtOneRR(RRt next_element(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_nextscCs,|jjdd}|j|jddS(NR$tThree(RKR RRR{(Rtlast((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_next_of_last_item_is_nonescCs|j|jjddS(N(RRKRR{(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_next_of_root_is_nonescCs[|j|jjdddg|jjdd|j|jjdddgdS(NRtTwoRRi(RRt find_all_next(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_nexts"cCsC|j|jjddd|j|jjddddS(NRRRR$R(RRt find_next(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_next s cCsT|jjdd}|j|jdjd|j|jdddgdS(NR$RRRR(RKR RRRRR(RR$((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_next_for_text_elementscCse|jjdd}g|jD] }|^q}|\}}|j|dd|j|ddS(NR$RRR5R(RKR t next_elementsR(RRtnodet successorsRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_next_generators  ( RRRJRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs       tTestPreviousOperationscBsPeZdZdZdZdZdZdZdZdZ RS(cCs/tt|j|jjdd|_dS(NR$R(RIRRJRKR tend(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJscCs7|j|jjdd|j|jjjddS(NRR5R(RRtprevious_element(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_previous!scCs)|jjd}|j|jddS(Nthtml(RKR RRR{(RR_((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt#test_previous_of_first_item_is_none%scCsdS(N((R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_previous_of_root_is_none)scCsK|j|jjddddg|j|jjdddgdS(NRRRRRi(RRtfind_all_previous(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_all_previous/scCsC|j|jjddd|j|jjddddS(NRRR5R$R(RRt find_previous(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_previous7s cCsW|jjdd}|j|jdjd|j|jddddgdS(NR$RRRR(RKR RRRRR(RR$((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt#test_find_previous_for_text_element;scCs|jjdd}g|jD] }|^q}|\}}}}|j|dd|j|jd|j|jd|j|jddS(NR$RRR4tbodytheadR(RKR tprevious_elementsRRF(RRRt predecessorsRRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_previous_generatorAs( RRRJRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs       t SiblingTestcBseZdZRS(cCsJtt|jd}tjdjd|}|j||_dS(Ns s\n\s*t(RIRRJR/R0tsubRRK(Rtmarkup((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJPs (RRRJ(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRNstTestNextSiblingcBsGeZdZdZdZdZdZdZdZRS(cCs/tt|j|jjdd|_dS(NRR4(RIRRJRKR R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJfscCs|j|jjddS(N(RRKt next_siblingR{(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_next_sibling_of_root_is_nonejscCsU|j|jjdd|j|jjjdd|j|jjdddS(NRRR5s1.1(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_next_siblingmscCsm|j|jjjd|jjdd}|j|jd|jjdd}|j|jddS(NRs1.1R6(RRKRRR{R (Rt nested_spant last_span((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_next_sibling_may_not_existts cCs$|j|jjddddS(NtspanRR(RRtfind_next_sibling(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_next_sibling}scCsK|j|jjddddg|j|jjdddgdS(NRRR5R6R(RRtfind_next_siblings(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_next_siblingsscCs|jd}|jdd}|j|jjd|j|jjd|j|jddg|j|jddd|j|jddddS(NsFoobarbazR$R.RtbazR-tnonesuch( RR RRRFRRRR{(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_next_sibling_for_text_elements( RRRJRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRds     tTestPreviousSiblingcBsGeZdZdZdZdZdZdZdZRS(cCs/tt|j|jjdd|_dS(NRR6(RIRRJRKR R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJscCs|j|jjddS(N(RRKtprevious_siblingR{(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_previous_sibling_of_root_is_nonescCsU|j|jjdd|j|jjjdd|j|jjdddS(NRR5Rs3.1(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_previous_siblingscCsm|j|jjjd|jjdd}|j|jd|jjdd}|j|jddS(NRs1.1R4(RRKRRR{R (RRt first_span((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt#test_previous_sibling_may_not_exists cCs$|j|jjddddS(NRRR5(RRtfind_previous_sibling(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_find_previous_siblingscCsK|j|jjddddg|j|jjdddgdS(NRR5RR4R(RRtfind_previous_siblings(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_previous_siblingsscCs|jd}|jdd}|j|jjd|j|jjd|j|jddg|j|jddd|j|jddddS(NsFoobarbazR$RRR.R-R( RR RRRFRRRR{(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt&test_previous_sibling_for_text_elements( RRRJRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs     tTestTagCreationcBs2eZdZdZdZdZdZRS(s$Test the ability to create new tags.cCs|jd}|jddddidd6}|jt|t|jd|j|jtdddd|j|jd|j dS(NRR9R-RRDsa nameRF( Rtnew_tagR?t isinstanceR RRFtdictRDR{R(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_new_tags ""cCstrbtdd}|jd}|jd}|jd|j|jd|jntdd}|jd}|jd}|jd|j|jd|jdS( NRslxml-xmltbrtps
            s

            s html.parsers

            (tXML_BUILDER_PRESENTRRRRc(Rtxml_souptxml_brtxml_pt html_soupthtml_brthtml_p((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_tag_inherits_self_closing_rules_from_builderscCsH|jd}|jd}|jd||jt|tdS(NRR9(Rt new_stringRR?RR (RRts((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt'test_new_string_creates_navigablestringscCsK|jd}|jdt}|jd||jt|tdS(NRR9(RRRRR?R(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt3test_new_string_can_create_navigablestring_subclasss(RRR+RRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs    tTestTreeModificationcBs^eZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!d Z"d!Z#d"Z$d#Z%d$Z&d%Z'RS(&cCs|jd}d|jd<|j|j|jd|jd=|j|j|jdd|jd<|j|j|jddS( NsiRssR9tid2s(RR)RRdt document_for(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_modifications   cCstjd}|jdd|}t||d}t||d}d|d<|jjd||jjd ||j|jjd dS( NRs tbuilderR)tolshttp://foo.com/threfiis4
              (RtlookupRR RtinsertRRc(RRRR)R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_new_tag_creations  cCsd}|j|}|jdd}|j}|jddj|j|j|j||j|j|jddS(NsT

              Don't leave me here.

              Don't leave!

              RRsD

              Don't leave me .

              Don't leave!here

              (RR RR;RRRdR(RtdocRt second_paratbold((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_append_to_contents_moves_tags cCsDd}|j|}|j}|j|j}|j||dS(Ns(RR)t replace_withRNR(RR$RR)tnew_a((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_replace_with_returns_thing_that_was_replaceds  cCs>d}|j|}|j}|j}|j||dS(Ns(RR)tunwrapR(RR$RR)R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt+test_unwrap_returns_thing_that_was_replaceds   cCse|jd}|j}|j|jd|j|jt|j|jt|j |j dS(NsFooBar( RR)textractRR{RRRRRRN(RRR)((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytItest_replace_with_and_unwrap_give_useful_exception_when_tag_has_no_parents   cCsQd}|j|}|j}|jj||j|j|j|dS(Ns-Foo(RRNRRRdR(RR$RRN((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_replace_tag_with_itself's  cCs5d}|j|}|jt|jj|jdS(Ns(RRRRRR)(RR$R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_replace_tag_with_its_parent_raises_exception.scCs8d}|j|}|jt|jjd|jdS(Nsi(RRRR)R(RR$R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt,test_insert_tag_into_itself_raises_exception3sc Cs|jd}d}|j|}|jd|x'|jD]}t|t s>tq>Wt|j\}}}}|jd|j |jd|j |jd|j |jd|j dS( sInserting one BeautifulSoup object into another actually inserts all of its children -- you'll never combine BeautifulSoup objects. s-

              And now, a word:

              And we're back.

              s

              p2

              p3

              isAnd now, a word:tp2tp3sAnd we're back.N( RRt descendantsRRtAssertionErrortlisttchildrent assertEqualsR( RRR$t to_insertRtp1RRtp4((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_insert_beautifulsoup_object_inserts_children8scCsx|jd}|j}|jd}|jdd|j\}}|jd|jd|jd|jjdS(Ns

              onethree

              iittwoRtthree(RR)RRt replaceWithRRR(RRR)Rtlefttright((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt3test_replace_with_maintains_next_element_throughoutLs    cCs|jd}|jddjd|jdd}|j}|j|j||j|j||j|jj||j|jddS(Ns Argh!R$sArgh!sHooray!( RR RRRRRRR{(RRtnew_textR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_replace_final_node[s cCs|jd}|jjdd|j|j|jd|jdd}|j|jd|j|jj||j|j d|j|j j ||j|j d|j|j|j dS(NsArgh!isHooray!s!Argh!Hooray!R$sArgh!( RRRRRdRR RRRRR{RN(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_consecutive_text_nodeses cCsr|jd}|jjdd|jjdd|jddg|jj|j|jjdjddS(NsiR-R9(RR)RRRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_insert_stringzs cCsW|j}|jdd|}t||d}|jdd|jjd||j|j|jd|j}|j|j ||j|j ||j dd }|j|j ||j|j ||j}|j|j ||j|j ||j dd}|j|j||j|j ||j|j |dS( Ns%Findlady!Rtmagictagittheis=Findthelady!R$tFind(tdefault_builderRR RR)RRdRRRRR RRRNR(RRRt magic_tagtb_tagR tc_tagR$((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_insert_tags,    cCsBd}|j|}|jj|j|j||jdS(Ns(RR)R;RRRd(RRfR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt*test_append_child_thats_already_at_the_endscCsEd}|j|}|jjd|j|jd|jdS(Nsis(RR)RtdRRd(RRfR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt$test_move_tag_to_beginning_of_parentscCs?|jd}|jjdd|jt|jddS(Ns
              itContentss
              Contents
              (RRRRR#(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt&test_insert_works_on_empty_element_tagscCs|jd}|jjd|jjd|j|j|jd|jj|j|j|j|jddS(NsfoobartBAZtQUUXsQUUXfooBAZbarsQUUXbarfooBAZ(RRt insert_beforeR)RRdR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_insert_beforescCs|jd}|jjd|jjd|j|j|jd|jj|j|j|j|jddS(NsfoobarR0R1sfooQUUXbarBAZsQUUXbarfooBAZ(RRt insert_afterR)RRdR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_insert_afterscCss|jd}|jd}|jd}|jt|j||jt|j||jt|j|dS(NRR)(RRRRRR4tNotImplementedError(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt:test_insert_after_raises_exception_if_after_has_no_meanings cCss|jd}|jd}|jd}|jt|j||jt|j||jt|j|dS(NRR)(RRRRRR2R6(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytFtest_insert_before_raises_notimplementederror_if_before_has_no_meanings cCs|jd}|jd\}}|j||j|j|jd|j|jd|j|j|j|j|j d|j|j ddS(Ns;

              There's no business like show business

              Rs0

              There's business like no business

              tnos business( RR'RRRdRRR{RRR(RRR9tshow((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_replace_withs    cCsBd}|j|}|jj|j|jd|jdS(Nss(RRRRNRRd(RRfR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_replace_first_childscCsBd}|j|}|jj|j|jd|jdS(Nss(RRNRRRRd(RRfR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_replace_last_childscCsx|jd}|j}|j}|j||j|j|jd|j|jd|j|j ddj d|j|j d|j|j d|j|j d|j|j|j|j|j d|j|j j |j|j|j d|j dd}|j}|j|j ||j|j ||j|j ||j|j |dS(NsQWereservetherighttorefuseservices-WerefusetoserviceR$RtWetto(RRRpRRRdRRR{R RRRRR)tetg(RRt remove_tagtmove_tagtto_texttg_tag((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_nested_tag_replace_withs.      cCsI|jd}|jj|j|jd|j|jjddS(NsI

              Unneeded formatting is unneeded

              sUnneeded formatting is unneeded(RtemRRR{RR$(RRK((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_unwraps   cCsc|jd}|jj|jd}|j|jd|j|j|jddS(NsI wish I was bold.RsI wish I was bold.(RRtwrapRRRdR(RRRs((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_wrap"s cCsH|jd}|jjj|j|j|j|jddS(NsI wish I was bold.sI wish I was bold.(RRRRIRRdR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt%test_wrap_extracts_tag_from_elsewhere)scCsd|jd}|jjj|j|jdt|jj|j|j|jddS(Ns+I like being bold.I wish I was bold.is+I like being bold.I wish I was bold.( RRRRIRR&RRdR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt&test_wrap_puts_new_contents_at_the_end/s cCs;|jd}|jt|jjd|jddj}|j|jd|j|jd|jt|jjd|j|jd|j|j d|j|j j d|jdd }|jdd }|j|j ||j|j ||j|j ||j|j |dS( NsRSome content. More content.iRtnavs6Some content. More content.siR$sSome content. s More content.(RRR&RRR R RdRR{RRRR(RRt extractedt content_1t content_2((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_extract7s" cCs|jd}|jj}|jj}|jd}|jd}|jj||jj||j|j|j||jj|j||jjdS(NsfoobarR9R-(RR)RRRR;R R(RRtfoo_1tbar_1tfoo_2tbar_2((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt4test_extract_distinguishes_between_identical_stringsPs    cCsU|jd}g|jdD]}|jj^q|jdt|jdS(Nsv tscripts (RR'RWR RtunicodeR(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_extract_multiples_of_same_tagas )cCs?|jd}|jdj|jd|jddS(Ns hi R(RR R RR{(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytBtest_extract_works_when_element_is_surrounded_by_identical_stringsqs cCs|jd}|j}|jj|jt|jjd|jt|d|j }|jdt |jdt|jdS(s Tag.clear()s4

              String Italicized and another

              iRt decomposeN( RR)RtclearRR&RR?R@RGR1(RRR)RG((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_clearzs   cCs]|jd}d|j_|j|jjdgd|j_|j|jjdgdS(sTag.string = 'string's R9R-N(RR)RRRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_string_sets   cCs>|jd}|jj|j_|j|jjddS(Nsfoobarsbarbar(RRNRRRR)Rc(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt/test_string_set_does_not_affect_original_stringscCsG|jd}td}||j_|jt|jjtdS(NsR9(RRR)RR?R(RRtcdata((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt)test_set_string_preserves_class_of_strings  ((RRRRRRRR R R R RRR R!R"R*R+R-R/R3R5R7R8R;R<R=RFRHRJRKRLRQRVRYRZR]R^R_Ra(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRsL                   $          tTestElementObjectscBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZRS(s)Test various features of element objects.cCsw|jd}|jt|jd|jt|d|jt|jd|jt|jjddS(s3The length of an element is its number of children.s123iiN(RRR&RR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_lens cCsj|jd}|j|j|jd|j|jj|jdjd|j|jddS(s2Accessing a Python member .foo invokes find('foo')sRRN(RRRR RR)R{(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_member_access_invokes_finds(cCsg|jd}tjdt}|j}WdQX|j|j||jdt|djdS(Nstrecordsp.bTag is deprecated, use .find("b") instead. If you really were looking for a tag called bTag, use .find("bTag")i( Rtwarningstcatch_warningsR1tbTagRRR#tmessage(RRtwR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_deprecated_member_accessscCsE|jd}|j|jjd|j|jjddS(shas_attr() checks for the presence of an attribute. Please note note: has_attr() is different from __in__. has_attr() checks the tag's attributes and __in__ checks the tag's chidlren. stattrtattr2N(RR?R9thas_attrt assertFalse(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_has_attrscCsd}|j|ddS(Ns%s%(tassertSoupEquals(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt.test_attributes_come_out_in_alphabetical_orderscCs)|jd}|j|jjddS(Ns fooR9(RRRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_stringscCs)|jd}|j|jjddS(Ns(RRRRR{(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_empty_tag_has_no_stringscCs|jd}|j|jjd|jd}|j|jjd|jd}|jjdd|j|jjddS(Nsfoo
              sfoobars fooiR-(RRRRR{R)R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt-test_tag_with_multiple_children_has_no_stringscCs<|jd}|j|jjd|j|jddS(NsfooR9(RRR)R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt)test_tag_with_recursive_string_has_stringscCsH|jd}|j|jj|jd}|j|jjdS(s7Only a tag containing a single text node has a .string.sfeosN(RRoRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_lack_of_stringscCs|jd}|j|jjd|j|jjdtd|j|jjdd|j|jjddtddS( sBTag.text and Tag.get_text(sep=u"") -> all child text, concatenatedsar t sar t tstriptartt,s a,r, , t sa,r,tN(RRR)R$tget_textR1(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_all_texts cCsg|jd}|j|jd|j|jdttfd|j|jddddS(Nsfoobartfoobarttypest fooIGNOREbar(RRR{R RR{(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_get_text_ignores_commentss cCs2|jd}|jddgt|jdS(NsfoobarR9R-(RRRtstrings(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_all_strings_ignores_commentss(RRR+RcRdRkRpRrRsRtRuRvRwR|RR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRbs          tTestCDAtaListAttributescBsVeZdZdZdZdZdZdZdZdZ dZ RS( s0Testing cdata-list attributes like 'class'. cCs-|jd}|jdg|jddS(NsR9Rj(RRR)(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_single_value_becomes_list scCs0|jd}|jddg|jddS(NsR9R-Rj(RRR)(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_multiple_values_becomes_listscCs3|jd}|jdddg|jddS(NsR9R-RRj(RRR)(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt2test_multiple_values_separated_by_weird_whitespacescCs,|jd}|jd|jjdS(Nss(RRR)Rc(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt,test_attributes_joined_into_string_on_outputscCs2|jd}|jdg|jjddS(Nssabc defR(RRR)tget_attribute_list(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_get_attribute_listscCs0|jd}|jddg|jddS(Ns(s ISO-8859-1sUTF-8saccept-charset(RRtform(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_accept_charset!scCs0d}|j|}|jd|jddS(Ns)sISO-8859-1 UTF-8saccept-charset(RRR)(RRfR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt-test_cdata_attribute_applying_only_to_one_tag%scsH|jdj|jdjfd}|jt|dS(NRcs d_dS(NR9(RF((R(s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytt0s(RRRR{RFRtAttributeError(RR((Rs7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt'test_string_has_immutable_name_property-s( RRR+RRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR s       tTestPersistencecBs_eZdZdZdZdZdZdZdZdZ dZ d Z RS( s*Testing features like pickle and deepcopy.cCs5tt|jd|_|j|j|_dS(Nsy Beautiful Soup: We called him Tortoise because he taught us. foo bar (RIRRJtpageRRK(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJ7s cCsZtj|jd}tj|}|j|jt|j|j|jjdS(Ni(tpickletdumpsRKtloadsRt __class__RRd(Rtdumpedtloaded((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_pickle_and_unpickle_identityKscCs5tj|j}|j|j|jjdS(N(tcopytdeepcopyRKRRd(Rtcopied((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_deepcopy_identitySscCsQtdd}|j}|j}|jdt||j||jdS(Ns

               

              s html.parseru

               

              (Rtoriginal_encodingt__copy__RRX(RRtencodingR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_copy_preserves_encodingXs   cCsYd}|j|}tj|tj}tj|}|j|j|jdS(Nu (RRRtHIGHEST_PROTOCOLRRRd(RRRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_unicode_pickle_s cCsd}|j|}|jdd}tj|}|j|||jd|j|jd|j|jd|j|jd|j|jd|j dS(NuFooBarRR.( RR RRR{RRtassertNotEqualRR(RRRts1ts2((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_copy_navigablestring_is_not_attached_to_treegscCsWd}|j|}|j}tj|}|j|||jt|tdS(Nu(RRRRR?RR(RRRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt0test_copy_navigablestring_subclass_has_same_typess  cCs8d}|j|}tj|}|j||dS(Nu)
              FooBar
              end(RRR(RRRt soup_copy((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_copy_entire_soup{scCsd}|j|}|j}tj|}|jt|t||j|||j||k|jd|j|jd|j|jd|j ddj |j d|j ddj dS(Nu)
              FooBar
              endRtBar( RRXRRRXRoR{RRR RR(RRRRXtdiv_copy((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_copy_tag_copies_contentss ( RRR+RJRRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR4s       tTestSubstitutionscBseZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZRS(cCsDd}|j|}|jdd}|j||jddS(Nu#<<Sacré bleu!>>t formattertminimal(RRdRR(RRRtdecoded((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt!test_default_formatter_is_minimalscCsDd}|j|}|jdd}|j||jddS(Nu'
              <<Sacré bleu!>>RRs.
              <<Sacré bleu!>>(RRdRR(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_formatter_htmls cCsDd}|j|}|jdd}|j||jddS(Nu'
              <<Sacré bleu!>>Rthtml5s-
              <<Sacré bleu!>>(RRdRR(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_formatter_html5s cCsDd}|j|}|jdd}|j||jddS(Nu#<<Sacré bleu!>>RR(RRdRR(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_formatter_minimalscCsDd}|j|}|jdd}|j||jddS(Nu#<<Sacré bleu!>>Ru<>(RRdR{RR(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_formatter_nulls  cCsGd}|j|}|jdd}|j||jddS(Nu!<foo>bar
              RcSs |jS(N(tupper(tx((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytsuBAR
              (RRdRR(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_formatter_customs cCsd}|j|}|j}d}|j||j|j||jddd}|j||jdd|j||jddd}|j||jdddS( Nu%eu)eRRu/eRu%EcSs |jS(N(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs(RR)RRdR{(RRRR)texpect_minimalt expect_htmlt expect_upper((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt)test_formatter_is_run_on_attribute_valuess cCs2d}t|dj}|jd|kdS(NsO s html.parsers < < hey > >(RRcR?(RRtencoded((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt2test_formatter_skips_script_tag_for_html_documentsscCs2d}t|dj}|jd|kdS(NsF s html.parsers < < hey > >(RRcR?(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_formatter_skips_style_tag_for_html_documentsscCs,|jd}|jd|jjdS(Ns*
              foo
                	bar
                
                
              baz u/
              foo
                	bar
                
                
              baz
              (RRRXtprettify(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt,test_prettify_leaves_preformatted_text_alonescCs;tdd}|jdd}|jd|kdS(Nsfoos html.parserRcSs |jS(N(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRstFOO(RRR?(RRtpretty((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt(test_prettify_accepts_formatter_functionscCs/|jd}|jtt|jdS(Ns(RRRXttypeR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt(test_prettify_outputs_unicode_by_defaultscCs2|jd}|jtt|jddS(Nssutf-8(RRtbytesRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_prettify_can_encode_datascCsDd}|j|}|jjd}|j||jddS(NuSacré bleu!sutf-8(RRRcR(RRRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt,test_html_entity_substitution_off_by_defaultscCsd}|j|}|j|jdd|jd}|jd|k|jd}|jd|k|jd}|jd |k|jd jd }|jd |kdS( NsEtcontentstext/html; charset=x-sjissutf-8s charset=utf-8teuc_jpscharset=euc_jps shift-jisscharset=shift-jissutf-16scharset=utf-16(RRtmetaRcR?Rd(Rtmeta_tagRtutf_8Rt shift_jistutf_16_u((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_encoding_substitution scCsEd}td}|j|d|}|j|jdjddS(Ns`
              foo
              tpret parse_onlyi(R RRRRF(RRRyR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt;test_encoding_substitution_doesnt_happen_if_tag_is_strained$s (RRRRRRRRRRRRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs          t TestEncodingcBsVeZdZdZdZdZdZdZdZdZ dZ RS( s0Test the ability to encode objects into strings.cCsAd}|j|}|j|jjjddjddS(Nu sutf-8u☃(RRRRRc(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_unicode_string_can_be_encoded2scCs>d}|j|}|j|jjd|jddS(Nu sutf-8(RRRRc(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt1test_tag_containing_unicode_string_can_be_encoded8scCs5d}|j|}|j|jjdddS(Nu tasciis(RRRRc(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt<test_encoding_substitutes_unrecognized_characters_by_default>scCs5d}|j|}|jt|jddddS(Nu Rterrorststrict(RRtUnicodeEncodeErrorRc(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_encoding_can_be_made_strictCscCs2d}|j|}|jd|jjdS(Nu u☃(RRRtdecode_contents(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_decode_contentsIscCsAd}|j|}|jdjd|jjdddS(Nu u☃RaR(RRRcRtencode_contents(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_encode_contentsNs cCs;d}|j|}|jdjd|jjdS(Nu u☃Ra(RRRcRtrenderContents(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_deprecated_renderContentsUscCsNd}|j|}tr4|j|t|n|jdt|dS(Nu s \u2603(RRRtrepr(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_repr[s ( RRR+RRRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyR/s       tTestNavigableStringSubclassescBs,eZdZdZdZdZRS(cCsx|jd}td}|jd||jt|d|j|jddd|j|jdddS(NRR9isR$i(RRRRR#R R(RRR`((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_cdataes  csvd_fd}jd}td}|jd|jd|jd|jdjdS( skText inside a CData object is passed into the formatter. But the return value is ignored. icsjd7_dS(NisBITTER FAILURE(tcount(targs(R(s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt incrementvsRs<><><>is<><>]]>RN(RRRRRRc(RRRR`((Rs7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_cdata_is_never_formattedos  cCsEtd}|jd}|jd||j|jddS(NR9Ris (RRRRRc(RtdoctypeR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_doctype_ends_in_newlines cCs&td}|jd|jdS(NR9s(RRt output_ready(RR,((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_declarations (RRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRcs  tTestSoupSelectorcBseZdZdZdZeZdZdZdZdZ dZ dZ d Z d Z d Zd Zd ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!dZ"d Z#d!Z$d"Z%d#Z&d$Z'd%Z(d&Z)d'Z*d(Z+d)Z,d*Z-d+Z.d,Z/d-Z0d.Z1d/Z2d0Z3d1Z4d2Z5d3Z6d4Z7d5Z8d6Z9d7Z:d8Z;d9Z<RS(:s The title Hello there.

              An H1

              Some text

              Some more text

              An H2

              Another

              Bob

              Another H2

              me span1a1 span1a2 test span2a1

              English

              English UK

              English US

              French

              cCst|jd|_dS(Ns html.parser(RtHTMLR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRJscKsvg|jj||D]}|d^q}|j|j|j||d|dj|dj|fdS(NRs$Selector %s, expected [%s], got [%s]s, (RtselecttsortRtjoin(Rtselectort expected_idstkwargsteltel_ids((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRs ,   cGs+x$|D]\}}|j||qWdS(N(t assertSelect(RttestsRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pytassertSelectMultiplescCs]|jjd}|jt|d|j|djd|j|djdgdS(NRbiiu The title(RRRR&RFR(Rtels((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_one_tag_onescCsv|jjd}|jt|dx!|D]}|j|jdq/W|jjd}|jd|ddS(NRXitmainR(RRRR&RFt select_one(RRRXR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_one_tag_manys  cCs&|jjd}|jd|dS(Ntnonexistenttag(RRRR{(Rtmatch((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt(test_select_one_returns_none_if_no_matchscCs,|jjd}|jdddgdS(Nsdiv divtinnertdata1(RRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_tag_in_tag_onescCs1x*dD]"}|j|ddddgqWdS( Nshtml divs html body divsbody divRRRtfooter(shtml divs html body divsbody div(R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_tag_in_tag_manys cCs[|jddgdd|jdddgdd|jdd ddd gdd dS( Nshtml divRR3is html body divRisbody divRR i (R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_limitscCs&|jt|jjdddS(Ntdeli(RR&RR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_tag_no_matchscCs|jt|jjddS(Nstag%t(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_invalid_tagscCs|jdddgdS(Nscustom-dashed-tagtdash1tdash2(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_select_dashed_tag_idsscCsE|jjd}|j|djd|j|ddddS(Nscustom-dashed-tag[id="dash2"]iscustom-dashed-tagRR(RRRRF(Rtdashed((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_select_dashed_by_idscCs'|j|jjddjddS(Nsbody > custom-dashed-tagiu Hello there.(RRRR$(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_dashed_tag_textscCs,|j|jjd|jjddS(Nscustom-dashed-tag(RRRR'(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt#test_select_dashed_matches_find_allscCs)|jddgfdddgfdS(Nth1theader1th2theader2theader3(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_header_tags s cCsoxhd D]`}|jj|}|jt|d|j|djd|j|dddgqWdS( Ns.onepsp.oneps html p.onepiiRRjtonep(s.onepsp.oneps html p.onep(RRRR&RF(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_class_ones  cCs,|jjd}|jt|ddS(Nsdiv.onepi(RRRR&(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_class_mismatched_tagscCs(x!dD]}|j|dgqWdS(Ns div#inners#inners div div#innerR(s div#inners#inners div div#inner(R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_one_ids cCs,|jjd}|jt|ddS(Ns #doesnotexisti(RRRR&(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt test_bad_idscCs|jjd}|jt|dx!|D]}|j|jdq/W|j|dddg|j|djddS(Ns div#inner piRiRjRi(RRRR&RFRoRn(RRR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_items_in_id#s  cCs7x0dD](}|jt|jj|dqWdS(Ns div#main delsdiv#main div.oopss div div#maini(s div#main delsdiv#main div.oopss div div#main(RR&RR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_a_bunch_of_emptys+s cCs(x!d D]}|j|d gqWdS( Ns.class1sp.class1s.class2sp.class2s.class3sp.class3s html p.class2sdiv#inner .class2tpmulti(s.class1sp.class1s.class2sp.class2s.class3sp.class3s html p.class2sdiv#inner .class2(R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multi_class_support/s cCs(x!dD]}|j|dgqWdS(Ns.class1.class3s.class3.class2s.class1.class2.class3R$(s.class1.class3s.class3.class2s.class1.class2.class3(R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multi_class_selection4s cCs-|jdddg|jddgdS(Ns.s1 > ats1a1ts1a2s .s1 > a spants1a2s1(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_child_selector9scCs|jddgdS(Ns.s1 > a#s1a2 spanR)(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_child_selector_id=scCs|jddgfddgfddgfddgfddgfddgfd dgfd gfd dgfd dgfd dgfdgfdgfdgfdS(Nsp[class="onep"]Rs p[id="p1"]s[class="onep"]s [id="p1"]slink[rel="stylesheet"]tl1slink[type="text/css"]slink[href="blah.css"]slink[href="no-blah.css"]s[rel="stylesheet"]s[type="text/css"]s[href="blah.css"]s[href="no-blah.css"]sp[href="no-blah.css"](R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_equals@s             c Cs|jddgfddgfddgfddgfddgfddgfdd gfd d gfd d gfd d gf dS( Nsp[class~="class1"]R$sp[class~="class2"]sp[class~="class3"]s[class~="class1"]s[class~="class2"]s[class~="class3"]sa[rel~="friend"]tbobs a[rel~="met"]s[rel~="friend"]s [rel~="met"](R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_tildeRs         cCs|jddgfddgfdgfdgfdgfddgfdd d gfd d d gfd d dgfdd dgfddgfdd gfddgf dS(Ns[rel^="style"]R,slink[rel^="style"]snotlink[rel^="notstyle"]s[rel^="notstyle"]slink[rel^="notstyle"]slink[href^="bla"]sa[href^="http://"]R.tmes[href^="http://"]s [id^="p"]R$Rs [id^="m"]Rs div[id^="m"]s a[id^="m"]sdiv[data-tag^="dashed"]R(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_startswith`s        c Csh|jddgfddgfddgfdddddd d d d gfd dgfdgfdS(Ns[href$=".css"]R,slink[href$=".css"]s link[id$="1"]s [id$="1"]RRRR'ts2a1R)Rs div[id$="1"]s[id$="noending"](R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_endswithqs   ! cCs4|jddgfddgfdgfdgfdgfddgfdd d gfd d d gfddgfdd gfddgfddgfddgfdddd ddddddg fddgfdgfdd d dgfdd d gfd dgfd!dd"gfd#d"gfd$dgfdS(%Ns[rel*="style"]R,slink[rel*="style"]snotlink[rel*="notstyle"]s[rel*="notstyle"]slink[rel*="notstyle"]slink[href*="bla"]s[href*="http://"]R.R0s [id*="p"]R$Rs div[id*="m"]Rs a[id*="m"]s[href*=".css"]slink[href*=".css"]s link[id*="1"]s [id*="1"]RRR'R(R2R)Rs div[id*="1"]s[id*="noending"]s [href*="."]s a[href*="."]slink[href*="."]s div[id*="n"]Rs div[id*="nn"]sdiv[data-tag*="edval"](R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_contains{s.           $    cCsG|jddddgfddddgfddgfdgfdS( Ns p[lang|="en"]slang-ens lang-en-gbs lang-en-uss [lang|="en"]s p[lang|="fr"]slang-frs p[lang|="gb"](R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_exact_or_hypens  c Cs}|jddddgfddgfdddgfddd d d gfd d dgfdgfdgfddgfdS(Ns[rel]R,R.R0s link[rel]sa[rel]s[lang]slang-ens lang-en-gbs lang-en-usslang-frsp[class]RR$s[blah]sp[blah]s div[data-tag]R(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_attribute_existss   cCs>d}t|d}|jd\}|jd|jdS(Ns]
              nope
              yes
              s html.parsersdiv[style="display: right"]tyes(RRRR(RRRtchosen((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_quoted_space_in_selector_namescCs6|jt|jjd|jt|jjddS(Nsa:no-such-pseudoclasssa:nth-of-type(a)(RR6RR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_unsupported_pseudoclassscCs|jjd}|jt|d|j|djd|jjd}|jt|d|j|djd|jjd}|jt|d|jt|jjddS( Nsdiv#inner p:nth-of-type(1)iiu Some textsdiv#inner p:nth-of-type(3)uAnothersdiv#inner p:nth-of-type(4)sdiv p:nth-of-type(0)(RRRR&RRR(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_nth_of_typescCsC|jjd}|jt|d|j|djddS(Nsdiv#inner > p:nth-of-type(1)iiu Some text(RRRR&R(RR((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_nth_of_type_direct_descendantscCs|jddgdS(Ns#inner > p:nth-of-type(2)R(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_id_child_selector_nth_of_typescCsA|jjddd}|jd}|j|ddgdS(NRXRRRR(RR RR(RRtselected((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_select_on_elementscCs'|jddg|jdgdS(Ns .fancy #innerRs.normal #inner(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_overspecified_child_idscCsY|jddg|jddg|jddg|jg|jjddS(Ns#p1 + h2Rs #p1 + h2 + pR$s#p1 + #header2 + .class1s#p1 + p(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_adjacent_sibling_selectorscCso|jdddg|jddg|jddg|jddg|jg|jjddS( Ns#p1 ~ h2RRs#p1 ~ #header2s #p1 ~ h2 + aR0s#p1 ~ h2 + [rel="me"]s #inner ~ h2(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_general_sibling_selectors cCs|jt|jjddS(Nsh1 >(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_dangling_combinatorscCs|jddddgdS(Ns p[lang] ~ ps lang-en-gbs lang-en-usslang-fr(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt2test_sibling_combinator_wont_select_same_tag_twicescCs|jdddgdS(Nsx, ytxidtyid(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multiple_selectscCs|jdddgdS(Nsx,yRERF(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt"test_multiple_select_with_no_spacescCs|jdddgdS(Nsx, yRERF(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt$test_multiple_select_with_more_spacescCs|jddgdS(Nsx, xRE(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multiple_select_duplicatedscCs|jdddgdS(Nsx, y ~ p[lang=fr]REslang-fr(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multiple_select_siblingscCs|jdddgdS(Nsx, y > zREtzidb(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt.test_multiple_select_tag_and_direct_descendantscCs&|jdddddddgdS(Ns div > x, y, zRERFtzidaRLtzidabtzidac(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt/test_multiple_select_direct_descendant_and_tags scCs&|jdddddddgdS(Ns div x,y, zRERFRNRLRORP(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt(test_multiple_select_indirect_descendant scCs6|jt|jjd|jt|jjddS(Ns,x, ysx,,y(RRRR(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_invalid_multiple_selectscCs|jdddgdS(Nsp[lang=en], p[lang=en-gb]slang-ens lang-en-gb(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multiple_select_attrsscCs|jddddgdS(Ns*x, y > z[id=zida], z[id=zidab], z[id=zidb]RERLRO(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multiple_select_idsscCs|jdddgdS(Nsbody > div > x, y > zRERL(R(R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_multiple_select_nestedscCssd}t|d}|jd}|jdt|x2|jdddgD]}||ksStqSWdS(Ns3
              s html.parsers.c1, .c2iRltc1tc2(RRRR&R'R(RRRR>R((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyttest_select_duplicate_elementss (=RRRRJRRRRRRR R R RRRRRRRRRR R!R"R#R%R&R*R+R-R/R1R3R4R5R6R9R:R;R<R=R?R@RARBRCRDRGRHRIRJRKRMRQRRRSRTRURVRY(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyRsv1                                                    (3R+tpdbRRRR/Rftbs4Rt bs4.builderRRt bs4.elementRRRRRR R R t bs4.testingR R RR{Rt LXML_PRESENTRRR,RCRHR^RRRRRRRRRRRbRRRRRR(((s7/usr/lib/python2.7/site-packages/bs4/tests/test_tree.pyt sF    : ;O3(3--*n+a4*PK@N#]zLX X $site-packages/bs4/tests/test_lxml.pynu["""Tests to ensure that the lxml tree builder generates good trees.""" import re import warnings try: import lxml.etree LXML_PRESENT = True LXML_VERSION = lxml.etree.LXML_VERSION except ImportError, e: LXML_PRESENT = False LXML_VERSION = (0,) if LXML_PRESENT: from bs4.builder import LXMLTreeBuilder, LXMLTreeBuilderForXML from bs4 import ( BeautifulSoup, BeautifulStoneSoup, ) from bs4.element import Comment, Doctype, SoupStrainer from bs4.testing import skipIf from bs4.tests import test_htmlparser from bs4.testing import ( HTMLTreeBuilderSmokeTest, XMLTreeBuilderSmokeTest, SoupTest, skipIf, ) @skipIf( not LXML_PRESENT, "lxml seems not to be present, not testing its tree builder.") class LXMLTreeBuilderSmokeTest(SoupTest, HTMLTreeBuilderSmokeTest): """See ``HTMLTreeBuilderSmokeTest``.""" @property def default_builder(self): return LXMLTreeBuilder() def test_out_of_range_entity(self): self.assertSoupEquals( "

              foo�bar

              ", "

              foobar

              ") self.assertSoupEquals( "

              foo�bar

              ", "

              foobar

              ") self.assertSoupEquals( "

              foo�bar

              ", "

              foobar

              ") def test_entities_in_foreign_document_encoding(self): # We can't implement this case correctly because by the time we # hear about markup like "“", it's been (incorrectly) converted into # a string like u'\x93' pass # In lxml < 2.3.5, an empty doctype causes a segfault. Skip this # test if an old version of lxml is installed. @skipIf( not LXML_PRESENT or LXML_VERSION < (2,3,5,0), "Skipping doctype test for old version of lxml to avoid segfault.") def test_empty_doctype(self): soup = self.soup("") doctype = soup.contents[0] self.assertEqual("", doctype.strip()) def test_beautifulstonesoup_is_xml_parser(self): # Make sure that the deprecated BSS class uses an xml builder # if one is installed. with warnings.catch_warnings(record=True) as w: soup = BeautifulStoneSoup("") self.assertEqual(u"", unicode(soup.b)) self.assertTrue("BeautifulStoneSoup class is deprecated" in str(w[0].message)) @skipIf( not LXML_PRESENT, "lxml seems not to be present, not testing its XML tree builder.") class LXMLXMLTreeBuilderSmokeTest(SoupTest, XMLTreeBuilderSmokeTest): """See ``HTMLTreeBuilderSmokeTest``.""" @property def default_builder(self): return LXMLTreeBuilderForXML() PK@N#]t +site-packages/bs4/tests/test_htmlparser.pyonu[ Y=K[c@sdZddlmZddlZddlmZmZddlmZddl m Z deefdYZ d efd YZ dS( sGTests to ensure that the html.parser tree builder generates good trees.i(t set_traceN(tSoupTesttHTMLTreeBuilderSmokeTest(tHTMLParserTreeBuilder(tBeautifulSoupHTMLParsertHTMLParserTreeBuilderSmokeTestcBsDeZedZdZdZdZdZdZRS(cCstS(N(R(tself((s=/usr/lib/python2.7/site-packages/bs4/tests/test_htmlparser.pytdefault_builder scCsdS(N((R((s=/usr/lib/python2.7/site-packages/bs4/tests/test_htmlparser.pyttest_namespaced_system_doctypescCsdS(N((R((s=/usr/lib/python2.7/site-packages/bs4/tests/test_htmlparser.pyttest_namespaced_public_doctypescCsV|jd}tj|d}tj|}|jt|jt|jdS(sfUnlike most tree builders, HTMLParserTreeBuilder and will be restored after pickling. s fooiN(tsouptpickletdumpstloadst assertTruet isinstancetbuilderttype(Rttreetdumpedtloaded((s=/usr/lib/python2.7/site-packages/bs4/tests/test_htmlparser.pyttest_builder_is_pickledscCs$|jdd|jdddS(Ns





              s


              s


              t(tassertSoupEquals(R((s=/usr/lib/python2.7/site-packages/bs4/tests/test_htmlparser.pyt)test_redundant_empty_element_closing_tags!scCs|jdddS(Ns foo &# barsfoo &# bar(R(R((s=/usr/lib/python2.7/site-packages/bs4/tests/test_htmlparser.pyttest_empty_element%s( t__name__t __module__tpropertyRRR RRR(((s=/usr/lib/python2.7/site-packages/bs4/tests/test_htmlparser.pyR s    tTestHTMLParserSubclasscBseZdZRS(cCst}|jddS(slVerify that our HTMLParser subclass implements error() in a way that doesn't cause a crash. s don't crashN(Rterror(Rtparser((s=/usr/lib/python2.7/site-packages/bs4/tests/test_htmlparser.pyt test_error,s (RRR (((s=/usr/lib/python2.7/site-packages/bs4/tests/test_htmlparser.pyR+s( t__doc__tpdbRR t bs4.testingRRt bs4.builderRtbs4.builder._htmlparserRRR(((s=/usr/lib/python2.7/site-packages/bs4/tests/test_htmlparser.pyts !PK@N#]"K99$site-packages/bs4/tests/test_tree.pynu[ # -*- coding: utf-8 -*- """Tests for Beautiful Soup's tree traversal methods. The tree traversal methods are the main advantage of using Beautiful Soup over just using a parser. Different parsers will build different Beautiful Soup trees given the same markup, but all Beautiful Soup trees can be traversed with the methods tested here. """ from pdb import set_trace import copy import pickle import re import warnings from bs4 import BeautifulSoup from bs4.builder import ( builder_registry, HTMLParserTreeBuilder, ) from bs4.element import ( PY3K, CData, Comment, Declaration, Doctype, NavigableString, SoupStrainer, Tag, ) from bs4.testing import ( SoupTest, skipIf, ) XML_BUILDER_PRESENT = (builder_registry.lookup("xml") is not None) LXML_PRESENT = (builder_registry.lookup("lxml") is not None) class TreeTest(SoupTest): def assertSelects(self, tags, should_match): """Make sure that the given tags have the correct text. This is used in tests that define a bunch of tags, each containing a single string, and then select certain strings by some mechanism. """ self.assertEqual([tag.string for tag in tags], should_match) def assertSelectsIDs(self, tags, should_match): """Make sure that the given tags have the correct IDs. This is used in tests that define a bunch of tags, each containing a single string, and then select certain strings by some mechanism. """ self.assertEqual([tag['id'] for tag in tags], should_match) class TestFind(TreeTest): """Basic tests of the find() method. find() just calls find_all() with limit=1, so it's not tested all that thouroughly here. """ def test_find_tag(self): soup = self.soup("1234") self.assertEqual(soup.find("b").string, "2") def test_unicode_text_find(self): soup = self.soup(u'

              Räksmörgås

              ') self.assertEqual(soup.find(string=u'Räksmörgås'), u'Räksmörgås') def test_unicode_attribute_find(self): soup = self.soup(u'

              here it is

              ') str(soup) self.assertEqual("here it is", soup.find(id=u'Räksmörgås').text) def test_find_everything(self): """Test an optimization that finds all tags.""" soup = self.soup("foobar") self.assertEqual(2, len(soup.find_all())) def test_find_everything_with_name(self): """Test an optimization that finds all tags with a given name.""" soup = self.soup("foobarbaz") self.assertEqual(2, len(soup.find_all('a'))) class TestFindAll(TreeTest): """Basic tests of the find_all() method.""" def test_find_all_text_nodes(self): """You can search the tree for text nodes.""" soup = self.soup("Foobar\xbb") # Exact match. self.assertEqual(soup.find_all(string="bar"), [u"bar"]) self.assertEqual(soup.find_all(text="bar"), [u"bar"]) # Match any of a number of strings. self.assertEqual( soup.find_all(text=["Foo", "bar"]), [u"Foo", u"bar"]) # Match a regular expression. self.assertEqual(soup.find_all(text=re.compile('.*')), [u"Foo", u"bar", u'\xbb']) # Match anything. self.assertEqual(soup.find_all(text=True), [u"Foo", u"bar", u'\xbb']) def test_find_all_limit(self): """You can limit the number of items returned by find_all.""" soup = self.soup("12345") self.assertSelects(soup.find_all('a', limit=3), ["1", "2", "3"]) self.assertSelects(soup.find_all('a', limit=1), ["1"]) self.assertSelects( soup.find_all('a', limit=10), ["1", "2", "3", "4", "5"]) # A limit of 0 means no limit. self.assertSelects( soup.find_all('a', limit=0), ["1", "2", "3", "4", "5"]) def test_calling_a_tag_is_calling_findall(self): soup = self.soup("123") self.assertSelects(soup('a', limit=1), ["1"]) self.assertSelects(soup.b(id="foo"), ["3"]) def test_find_all_with_self_referential_data_structure_does_not_cause_infinite_recursion(self): soup = self.soup("") # Create a self-referential list. l = [] l.append(l) # Without special code in _normalize_search_value, this would cause infinite # recursion. self.assertEqual([], soup.find_all(l)) def test_find_all_resultset(self): """All find_all calls return a ResultSet""" soup = self.soup("") result = soup.find_all("a") self.assertTrue(hasattr(result, "source")) result = soup.find_all(True) self.assertTrue(hasattr(result, "source")) result = soup.find_all(text="foo") self.assertTrue(hasattr(result, "source")) class TestFindAllBasicNamespaces(TreeTest): def test_find_by_namespaced_name(self): soup = self.soup('4') self.assertEqual("4", soup.find("mathml:msqrt").string) self.assertEqual("a", soup.find(attrs= { "svg:fill" : "red" }).name) class TestFindAllByName(TreeTest): """Test ways of finding tags by tag name.""" def setUp(self): super(TreeTest, self).setUp() self.tree = self.soup("""First tag. Second tag. Third Nested tag. tag.""") def test_find_all_by_tag_name(self): # Find all the tags. self.assertSelects( self.tree.find_all('a'), ['First tag.', 'Nested tag.']) def test_find_all_by_name_and_text(self): self.assertSelects( self.tree.find_all('a', text='First tag.'), ['First tag.']) self.assertSelects( self.tree.find_all('a', text=True), ['First tag.', 'Nested tag.']) self.assertSelects( self.tree.find_all('a', text=re.compile("tag")), ['First tag.', 'Nested tag.']) def test_find_all_on_non_root_element(self): # You can call find_all on any node, not just the root. self.assertSelects(self.tree.c.find_all('a'), ['Nested tag.']) def test_calling_element_invokes_find_all(self): self.assertSelects(self.tree('a'), ['First tag.', 'Nested tag.']) def test_find_all_by_tag_strainer(self): self.assertSelects( self.tree.find_all(SoupStrainer('a')), ['First tag.', 'Nested tag.']) def test_find_all_by_tag_names(self): self.assertSelects( self.tree.find_all(['a', 'b']), ['First tag.', 'Second tag.', 'Nested tag.']) def test_find_all_by_tag_dict(self): self.assertSelects( self.tree.find_all({'a' : True, 'b' : True}), ['First tag.', 'Second tag.', 'Nested tag.']) def test_find_all_by_tag_re(self): self.assertSelects( self.tree.find_all(re.compile('^[ab]$')), ['First tag.', 'Second tag.', 'Nested tag.']) def test_find_all_with_tags_matching_method(self): # You can define an oracle method that determines whether # a tag matches the search. def id_matches_name(tag): return tag.name == tag.get('id') tree = self.soup("""Match 1. Does not match. Match 2.""") self.assertSelects( tree.find_all(id_matches_name), ["Match 1.", "Match 2."]) def test_find_with_multi_valued_attribute(self): soup = self.soup( "
              1
              2
              3
              " ) r1 = soup.find('div', 'a d'); r2 = soup.find('div', re.compile(r'a d')); r3, r4 = soup.find_all('div', ['a b', 'a d']); self.assertEqual('3', r1.string) self.assertEqual('3', r2.string) self.assertEqual('1', r3.string) self.assertEqual('3', r4.string) class TestFindAllByAttribute(TreeTest): def test_find_all_by_attribute_name(self): # You can pass in keyword arguments to find_all to search by # attribute. tree = self.soup(""" Matching a. Non-matching Matching b.a. """) self.assertSelects(tree.find_all(id='first'), ["Matching a.", "Matching b."]) def test_find_all_by_utf8_attribute_value(self): peace = u"םולש".encode("utf8") data = u''.encode("utf8") soup = self.soup(data) self.assertEqual([soup.a], soup.find_all(title=peace)) self.assertEqual([soup.a], soup.find_all(title=peace.decode("utf8"))) self.assertEqual([soup.a], soup.find_all(title=[peace, "something else"])) def test_find_all_by_attribute_dict(self): # You can pass in a dictionary as the argument 'attrs'. This # lets you search for attributes like 'name' (a fixed argument # to find_all) and 'class' (a reserved word in Python.) tree = self.soup(""" Name match. Class match. Non-match. A tag called 'name1'. """) # This doesn't do what you want. self.assertSelects(tree.find_all(name='name1'), ["A tag called 'name1'."]) # This does what you want. self.assertSelects(tree.find_all(attrs={'name' : 'name1'}), ["Name match."]) self.assertSelects(tree.find_all(attrs={'class' : 'class2'}), ["Class match."]) def test_find_all_by_class(self): tree = self.soup(""" Class 1. Class 2. Class 1. Class 3 and 4. """) # Passing in the class_ keyword argument will search against # the 'class' attribute. self.assertSelects(tree.find_all('a', class_='1'), ['Class 1.']) self.assertSelects(tree.find_all('c', class_='3'), ['Class 3 and 4.']) self.assertSelects(tree.find_all('c', class_='4'), ['Class 3 and 4.']) # Passing in a string to 'attrs' will also search the CSS class. self.assertSelects(tree.find_all('a', '1'), ['Class 1.']) self.assertSelects(tree.find_all(attrs='1'), ['Class 1.', 'Class 1.']) self.assertSelects(tree.find_all('c', '3'), ['Class 3 and 4.']) self.assertSelects(tree.find_all('c', '4'), ['Class 3 and 4.']) def test_find_by_class_when_multiple_classes_present(self): tree = self.soup("Found it") f = tree.find_all("gar", class_=re.compile("o")) self.assertSelects(f, ["Found it"]) f = tree.find_all("gar", class_=re.compile("a")) self.assertSelects(f, ["Found it"]) # If the search fails to match the individual strings "foo" and "bar", # it will be tried against the combined string "foo bar". f = tree.find_all("gar", class_=re.compile("o b")) self.assertSelects(f, ["Found it"]) def test_find_all_with_non_dictionary_for_attrs_finds_by_class(self): soup = self.soup("Found it") self.assertSelects(soup.find_all("a", re.compile("ba")), ["Found it"]) def big_attribute_value(value): return len(value) > 3 self.assertSelects(soup.find_all("a", big_attribute_value), []) def small_attribute_value(value): return len(value) <= 3 self.assertSelects( soup.find_all("a", small_attribute_value), ["Found it"]) def test_find_all_with_string_for_attrs_finds_multiple_classes(self): soup = self.soup('') a, a2 = soup.find_all("a") self.assertEqual([a, a2], soup.find_all("a", "foo")) self.assertEqual([a], soup.find_all("a", "bar")) # If you specify the class as a string that contains a # space, only that specific value will be found. self.assertEqual([a], soup.find_all("a", class_="foo bar")) self.assertEqual([a], soup.find_all("a", "foo bar")) self.assertEqual([], soup.find_all("a", "bar foo")) def test_find_all_by_attribute_soupstrainer(self): tree = self.soup(""" Match. Non-match.""") strainer = SoupStrainer(attrs={'id' : 'first'}) self.assertSelects(tree.find_all(strainer), ['Match.']) def test_find_all_with_missing_attribute(self): # You can pass in None as the value of an attribute to find_all. # This will match tags that do not have that attribute set. tree = self.soup("""ID present. No ID present. ID is empty.""") self.assertSelects(tree.find_all('a', id=None), ["No ID present."]) def test_find_all_with_defined_attribute(self): # You can pass in None as the value of an attribute to find_all. # This will match tags that have that attribute set to any value. tree = self.soup("""ID present. No ID present. ID is empty.""") self.assertSelects( tree.find_all(id=True), ["ID present.", "ID is empty."]) def test_find_all_with_numeric_attribute(self): # If you search for a number, it's treated as a string. tree = self.soup("""Unquoted attribute. Quoted attribute.""") expected = ["Unquoted attribute.", "Quoted attribute."] self.assertSelects(tree.find_all(id=1), expected) self.assertSelects(tree.find_all(id="1"), expected) def test_find_all_with_list_attribute_values(self): # You can pass a list of attribute values instead of just one, # and you'll get tags that match any of the values. tree = self.soup("""1 2 3 No ID.""") self.assertSelects(tree.find_all(id=["1", "3", "4"]), ["1", "3"]) def test_find_all_with_regular_expression_attribute_value(self): # You can pass a regular expression as an attribute value, and # you'll get tags whose values for that attribute match the # regular expression. tree = self.soup("""One a. Two as. Mixed as and bs. One b. No ID.""") self.assertSelects(tree.find_all(id=re.compile("^a+$")), ["One a.", "Two as."]) def test_find_by_name_and_containing_string(self): soup = self.soup("foobarfoo") a = soup.a self.assertEqual([a], soup.find_all("a", text="foo")) self.assertEqual([], soup.find_all("a", text="bar")) self.assertEqual([], soup.find_all("a", text="bar")) def test_find_by_name_and_containing_string_when_string_is_buried(self): soup = self.soup("foofoo") self.assertEqual(soup.find_all("a"), soup.find_all("a", text="foo")) def test_find_by_attribute_and_containing_string(self): soup = self.soup('foofoo') a = soup.a self.assertEqual([a], soup.find_all(id=2, text="foo")) self.assertEqual([], soup.find_all(id=1, text="bar")) class TestIndex(TreeTest): """Test Tag.index""" def test_index(self): tree = self.soup("""
              Identical Not identical Identical Identical with child Also not identical Identical with child
              """) div = tree.div for i, element in enumerate(div.contents): self.assertEqual(i, div.index(element)) self.assertRaises(ValueError, tree.index, 1) class TestParentOperations(TreeTest): """Test navigation and searching through an element's parents.""" def setUp(self): super(TestParentOperations, self).setUp() self.tree = self.soup('''
                      Start here
                  ''') self.start = self.tree.b def test_parent(self): self.assertEqual(self.start.parent['id'], 'bottom') self.assertEqual(self.start.parent.parent['id'], 'middle') self.assertEqual(self.start.parent.parent.parent['id'], 'top') def test_parent_of_top_tag_is_soup_object(self): top_tag = self.tree.contents[0] self.assertEqual(top_tag.parent, self.tree) def test_soup_object_has_no_parent(self): self.assertEqual(None, self.tree.parent) def test_find_parents(self): self.assertSelectsIDs( self.start.find_parents('ul'), ['bottom', 'middle', 'top']) self.assertSelectsIDs( self.start.find_parents('ul', id="middle"), ['middle']) def test_find_parent(self): self.assertEqual(self.start.find_parent('ul')['id'], 'bottom') self.assertEqual(self.start.find_parent('ul', id='top')['id'], 'top') def test_parent_of_text_element(self): text = self.tree.find(text="Start here") self.assertEqual(text.parent.name, 'b') def test_text_element_find_parent(self): text = self.tree.find(text="Start here") self.assertEqual(text.find_parent('ul')['id'], 'bottom') def test_parent_generator(self): parents = [parent['id'] for parent in self.start.parents if parent is not None and 'id' in parent.attrs] self.assertEqual(parents, ['bottom', 'middle', 'top']) class ProximityTest(TreeTest): def setUp(self): super(TreeTest, self).setUp() self.tree = self.soup( 'OneTwoThree') class TestNextOperations(ProximityTest): def setUp(self): super(TestNextOperations, self).setUp() self.start = self.tree.b def test_next(self): self.assertEqual(self.start.next_element, "One") self.assertEqual(self.start.next_element.next_element['id'], "2") def test_next_of_last_item_is_none(self): last = self.tree.find(text="Three") self.assertEqual(last.next_element, None) def test_next_of_root_is_none(self): # The document root is outside the next/previous chain. self.assertEqual(self.tree.next_element, None) def test_find_all_next(self): self.assertSelects(self.start.find_all_next('b'), ["Two", "Three"]) self.start.find_all_next(id=3) self.assertSelects(self.start.find_all_next(id=3), ["Three"]) def test_find_next(self): self.assertEqual(self.start.find_next('b')['id'], '2') self.assertEqual(self.start.find_next(text="Three"), "Three") def test_find_next_for_text_element(self): text = self.tree.find(text="One") self.assertEqual(text.find_next("b").string, "Two") self.assertSelects(text.find_all_next("b"), ["Two", "Three"]) def test_next_generator(self): start = self.tree.find(text="Two") successors = [node for node in start.next_elements] # There are two successors: the final tag and its text contents. tag, contents = successors self.assertEqual(tag['id'], '3') self.assertEqual(contents, "Three") class TestPreviousOperations(ProximityTest): def setUp(self): super(TestPreviousOperations, self).setUp() self.end = self.tree.find(text="Three") def test_previous(self): self.assertEqual(self.end.previous_element['id'], "3") self.assertEqual(self.end.previous_element.previous_element, "Two") def test_previous_of_first_item_is_none(self): first = self.tree.find('html') self.assertEqual(first.previous_element, None) def test_previous_of_root_is_none(self): # The document root is outside the next/previous chain. # XXX This is broken! #self.assertEqual(self.tree.previous_element, None) pass def test_find_all_previous(self): # The tag containing the "Three" node is the predecessor # of the "Three" node itself, which is why "Three" shows up # here. self.assertSelects( self.end.find_all_previous('b'), ["Three", "Two", "One"]) self.assertSelects(self.end.find_all_previous(id=1), ["One"]) def test_find_previous(self): self.assertEqual(self.end.find_previous('b')['id'], '3') self.assertEqual(self.end.find_previous(text="One"), "One") def test_find_previous_for_text_element(self): text = self.tree.find(text="Three") self.assertEqual(text.find_previous("b").string, "Three") self.assertSelects( text.find_all_previous("b"), ["Three", "Two", "One"]) def test_previous_generator(self): start = self.tree.find(text="One") predecessors = [node for node in start.previous_elements] # There are four predecessors: the tag containing "One" # the tag, the tag, and the tag. b, body, head, html = predecessors self.assertEqual(b['id'], '1') self.assertEqual(body.name, "body") self.assertEqual(head.name, "head") self.assertEqual(html.name, "html") class SiblingTest(TreeTest): def setUp(self): super(SiblingTest, self).setUp() markup = ''' ''' # All that whitespace looks good but makes the tests more # difficult. Get rid of it. markup = re.compile(r"\n\s*").sub("", markup) self.tree = self.soup(markup) class TestNextSibling(SiblingTest): def setUp(self): super(TestNextSibling, self).setUp() self.start = self.tree.find(id="1") def test_next_sibling_of_root_is_none(self): self.assertEqual(self.tree.next_sibling, None) def test_next_sibling(self): self.assertEqual(self.start.next_sibling['id'], '2') self.assertEqual(self.start.next_sibling.next_sibling['id'], '3') # Note the difference between next_sibling and next_element. self.assertEqual(self.start.next_element['id'], '1.1') def test_next_sibling_may_not_exist(self): self.assertEqual(self.tree.html.next_sibling, None) nested_span = self.tree.find(id="1.1") self.assertEqual(nested_span.next_sibling, None) last_span = self.tree.find(id="4") self.assertEqual(last_span.next_sibling, None) def test_find_next_sibling(self): self.assertEqual(self.start.find_next_sibling('span')['id'], '2') def test_next_siblings(self): self.assertSelectsIDs(self.start.find_next_siblings("span"), ['2', '3', '4']) self.assertSelectsIDs(self.start.find_next_siblings(id='3'), ['3']) def test_next_sibling_for_text_element(self): soup = self.soup("Foobarbaz") start = soup.find(text="Foo") self.assertEqual(start.next_sibling.name, 'b') self.assertEqual(start.next_sibling.next_sibling, 'baz') self.assertSelects(start.find_next_siblings('b'), ['bar']) self.assertEqual(start.find_next_sibling(text="baz"), "baz") self.assertEqual(start.find_next_sibling(text="nonesuch"), None) class TestPreviousSibling(SiblingTest): def setUp(self): super(TestPreviousSibling, self).setUp() self.end = self.tree.find(id="4") def test_previous_sibling_of_root_is_none(self): self.assertEqual(self.tree.previous_sibling, None) def test_previous_sibling(self): self.assertEqual(self.end.previous_sibling['id'], '3') self.assertEqual(self.end.previous_sibling.previous_sibling['id'], '2') # Note the difference between previous_sibling and previous_element. self.assertEqual(self.end.previous_element['id'], '3.1') def test_previous_sibling_may_not_exist(self): self.assertEqual(self.tree.html.previous_sibling, None) nested_span = self.tree.find(id="1.1") self.assertEqual(nested_span.previous_sibling, None) first_span = self.tree.find(id="1") self.assertEqual(first_span.previous_sibling, None) def test_find_previous_sibling(self): self.assertEqual(self.end.find_previous_sibling('span')['id'], '3') def test_previous_siblings(self): self.assertSelectsIDs(self.end.find_previous_siblings("span"), ['3', '2', '1']) self.assertSelectsIDs(self.end.find_previous_siblings(id='1'), ['1']) def test_previous_sibling_for_text_element(self): soup = self.soup("Foobarbaz") start = soup.find(text="baz") self.assertEqual(start.previous_sibling.name, 'b') self.assertEqual(start.previous_sibling.previous_sibling, 'Foo') self.assertSelects(start.find_previous_siblings('b'), ['bar']) self.assertEqual(start.find_previous_sibling(text="Foo"), "Foo") self.assertEqual(start.find_previous_sibling(text="nonesuch"), None) class TestTagCreation(SoupTest): """Test the ability to create new tags.""" def test_new_tag(self): soup = self.soup("") new_tag = soup.new_tag("foo", bar="baz", attrs={"name": "a name"}) self.assertTrue(isinstance(new_tag, Tag)) self.assertEqual("foo", new_tag.name) self.assertEqual(dict(bar="baz", name="a name"), new_tag.attrs) self.assertEqual(None, new_tag.parent) def test_tag_inherits_self_closing_rules_from_builder(self): if XML_BUILDER_PRESENT: xml_soup = BeautifulSoup("", "lxml-xml") xml_br = xml_soup.new_tag("br") xml_p = xml_soup.new_tag("p") # Both the
                  and

                  tag are empty-element, just because # they have no contents. self.assertEqual(b"
                  ", xml_br.encode()) self.assertEqual(b"

                  ", xml_p.encode()) html_soup = BeautifulSoup("", "html.parser") html_br = html_soup.new_tag("br") html_p = html_soup.new_tag("p") # The HTML builder users HTML's rules about which tags are # empty-element tags, and the new tags reflect these rules. self.assertEqual(b"
                  ", html_br.encode()) self.assertEqual(b"

                  ", html_p.encode()) def test_new_string_creates_navigablestring(self): soup = self.soup("") s = soup.new_string("foo") self.assertEqual("foo", s) self.assertTrue(isinstance(s, NavigableString)) def test_new_string_can_create_navigablestring_subclass(self): soup = self.soup("") s = soup.new_string("foo", Comment) self.assertEqual("foo", s) self.assertTrue(isinstance(s, Comment)) class TestTreeModification(SoupTest): def test_attribute_modification(self): soup = self.soup('') soup.a['id'] = 2 self.assertEqual(soup.decode(), self.document_for('')) del(soup.a['id']) self.assertEqual(soup.decode(), self.document_for('')) soup.a['id2'] = 'foo' self.assertEqual(soup.decode(), self.document_for('')) def test_new_tag_creation(self): builder = builder_registry.lookup('html')() soup = self.soup("", builder=builder) a = Tag(soup, builder, 'a') ol = Tag(soup, builder, 'ol') a['href'] = 'http://foo.com/' soup.body.insert(0, a) soup.body.insert(1, ol) self.assertEqual( soup.body.encode(), b'
                    ') def test_append_to_contents_moves_tag(self): doc = """

                    Don't leave me here.

                    Don\'t leave!

                    """ soup = self.soup(doc) second_para = soup.find(id='2') bold = soup.b # Move the tag to the end of the second paragraph. soup.find(id='2').append(soup.b) # The tag is now a child of the second paragraph. self.assertEqual(bold.parent, second_para) self.assertEqual( soup.decode(), self.document_for( '

                    Don\'t leave me .

                    \n' '

                    Don\'t leave!here

                    ')) def test_replace_with_returns_thing_that_was_replaced(self): text = "" soup = self.soup(text) a = soup.a new_a = a.replace_with(soup.c) self.assertEqual(a, new_a) def test_unwrap_returns_thing_that_was_replaced(self): text = "" soup = self.soup(text) a = soup.a new_a = a.unwrap() self.assertEqual(a, new_a) def test_replace_with_and_unwrap_give_useful_exception_when_tag_has_no_parent(self): soup = self.soup("FooBar") a = soup.a a.extract() self.assertEqual(None, a.parent) self.assertRaises(ValueError, a.unwrap) self.assertRaises(ValueError, a.replace_with, soup.c) def test_replace_tag_with_itself(self): text = "Foo" soup = self.soup(text) c = soup.c soup.c.replace_with(c) self.assertEqual(soup.decode(), self.document_for(text)) def test_replace_tag_with_its_parent_raises_exception(self): text = "" soup = self.soup(text) self.assertRaises(ValueError, soup.b.replace_with, soup.a) def test_insert_tag_into_itself_raises_exception(self): text = "" soup = self.soup(text) self.assertRaises(ValueError, soup.a.insert, 0, soup.a) def test_insert_beautifulsoup_object_inserts_children(self): """Inserting one BeautifulSoup object into another actually inserts all of its children -- you'll never combine BeautifulSoup objects. """ soup = self.soup("

                    And now, a word:

                    And we're back.

                    ") text = "

                    p2

                    p3

                    " to_insert = self.soup(text) soup.insert(1, to_insert) for i in soup.descendants: assert not isinstance(i, BeautifulSoup) p1, p2, p3, p4 = list(soup.children) self.assertEquals("And now, a word:", p1.string) self.assertEquals("p2", p2.string) self.assertEquals("p3", p3.string) self.assertEquals("And we're back.", p4.string) def test_replace_with_maintains_next_element_throughout(self): soup = self.soup('

                    onethree

                    ') a = soup.a b = a.contents[0] # Make it so the tag has two text children. a.insert(1, "two") # Now replace each one with the empty string. left, right = a.contents left.replaceWith('') right.replaceWith('') # The tag is still connected to the tree. self.assertEqual("three", soup.b.string) def test_replace_final_node(self): soup = self.soup("Argh!") soup.find(text="Argh!").replace_with("Hooray!") new_text = soup.find(text="Hooray!") b = soup.b self.assertEqual(new_text.previous_element, b) self.assertEqual(new_text.parent, b) self.assertEqual(new_text.previous_element.next_element, new_text) self.assertEqual(new_text.next_element, None) def test_consecutive_text_nodes(self): # A builder should never create two consecutive text nodes, # but if you insert one next to another, Beautiful Soup will # handle it correctly. soup = self.soup("Argh!") soup.b.insert(1, "Hooray!") self.assertEqual( soup.decode(), self.document_for( "Argh!Hooray!")) new_text = soup.find(text="Hooray!") self.assertEqual(new_text.previous_element, "Argh!") self.assertEqual(new_text.previous_element.next_element, new_text) self.assertEqual(new_text.previous_sibling, "Argh!") self.assertEqual(new_text.previous_sibling.next_sibling, new_text) self.assertEqual(new_text.next_sibling, None) self.assertEqual(new_text.next_element, soup.c) def test_insert_string(self): soup = self.soup("") soup.a.insert(0, "bar") soup.a.insert(0, "foo") # The string were added to the tag. self.assertEqual(["foo", "bar"], soup.a.contents) # And they were converted to NavigableStrings. self.assertEqual(soup.a.contents[0].next_element, "bar") def test_insert_tag(self): builder = self.default_builder soup = self.soup( "Findlady!", builder=builder) magic_tag = Tag(soup, builder, 'magictag') magic_tag.insert(0, "the") soup.a.insert(1, magic_tag) self.assertEqual( soup.decode(), self.document_for( "Findthelady!")) # Make sure all the relationships are hooked up correctly. b_tag = soup.b self.assertEqual(b_tag.next_sibling, magic_tag) self.assertEqual(magic_tag.previous_sibling, b_tag) find = b_tag.find(text="Find") self.assertEqual(find.next_element, magic_tag) self.assertEqual(magic_tag.previous_element, find) c_tag = soup.c self.assertEqual(magic_tag.next_sibling, c_tag) self.assertEqual(c_tag.previous_sibling, magic_tag) the = magic_tag.find(text="the") self.assertEqual(the.parent, magic_tag) self.assertEqual(the.next_element, c_tag) self.assertEqual(c_tag.previous_element, the) def test_append_child_thats_already_at_the_end(self): data = "" soup = self.soup(data) soup.a.append(soup.b) self.assertEqual(data, soup.decode()) def test_move_tag_to_beginning_of_parent(self): data = "" soup = self.soup(data) soup.a.insert(0, soup.d) self.assertEqual("", soup.decode()) def test_insert_works_on_empty_element_tag(self): # This is a little strange, since most HTML parsers don't allow # markup like this to come through. But in general, we don't # know what the parser would or wouldn't have allowed, so # I'm letting this succeed for now. soup = self.soup("
                    ") soup.br.insert(1, "Contents") self.assertEqual(str(soup.br), "
                    Contents
                    ") def test_insert_before(self): soup = self.soup("foobar") soup.b.insert_before("BAZ") soup.a.insert_before("QUUX") self.assertEqual( soup.decode(), self.document_for("QUUXfooBAZbar")) soup.a.insert_before(soup.b) self.assertEqual( soup.decode(), self.document_for("QUUXbarfooBAZ")) def test_insert_after(self): soup = self.soup("foobar") soup.b.insert_after("BAZ") soup.a.insert_after("QUUX") self.assertEqual( soup.decode(), self.document_for("fooQUUXbarBAZ")) soup.b.insert_after(soup.a) self.assertEqual( soup.decode(), self.document_for("QUUXbarfooBAZ")) def test_insert_after_raises_exception_if_after_has_no_meaning(self): soup = self.soup("") tag = soup.new_tag("a") string = soup.new_string("") self.assertRaises(ValueError, string.insert_after, tag) self.assertRaises(NotImplementedError, soup.insert_after, tag) self.assertRaises(ValueError, tag.insert_after, tag) def test_insert_before_raises_notimplementederror_if_before_has_no_meaning(self): soup = self.soup("") tag = soup.new_tag("a") string = soup.new_string("") self.assertRaises(ValueError, string.insert_before, tag) self.assertRaises(NotImplementedError, soup.insert_before, tag) self.assertRaises(ValueError, tag.insert_before, tag) def test_replace_with(self): soup = self.soup( "

                    There's no business like show business

                    ") no, show = soup.find_all('b') show.replace_with(no) self.assertEqual( soup.decode(), self.document_for( "

                    There's business like no business

                    ")) self.assertEqual(show.parent, None) self.assertEqual(no.parent, soup.p) self.assertEqual(no.next_element, "no") self.assertEqual(no.next_sibling, " business") def test_replace_first_child(self): data = "" soup = self.soup(data) soup.b.replace_with(soup.c) self.assertEqual("", soup.decode()) def test_replace_last_child(self): data = "" soup = self.soup(data) soup.c.replace_with(soup.b) self.assertEqual("", soup.decode()) def test_nested_tag_replace_with(self): soup = self.soup( """Wereservetherighttorefuseservice""") # Replace the entire tag and its contents ("reserve the # right") with the tag ("refuse"). remove_tag = soup.b move_tag = soup.f remove_tag.replace_with(move_tag) self.assertEqual( soup.decode(), self.document_for( "Werefusetoservice")) # The tag is now an orphan. self.assertEqual(remove_tag.parent, None) self.assertEqual(remove_tag.find(text="right").next_element, None) self.assertEqual(remove_tag.previous_element, None) self.assertEqual(remove_tag.next_sibling, None) self.assertEqual(remove_tag.previous_sibling, None) # The tag is now connected to the tag. self.assertEqual(move_tag.parent, soup.a) self.assertEqual(move_tag.previous_element, "We") self.assertEqual(move_tag.next_element.next_element, soup.e) self.assertEqual(move_tag.next_sibling, None) # The gap where the tag used to be has been mended, and # the word "to" is now connected to the tag. to_text = soup.find(text="to") g_tag = soup.g self.assertEqual(to_text.next_element, g_tag) self.assertEqual(to_text.next_sibling, g_tag) self.assertEqual(g_tag.previous_element, to_text) self.assertEqual(g_tag.previous_sibling, to_text) def test_unwrap(self): tree = self.soup("""

                    Unneeded formatting is unneeded

                    """) tree.em.unwrap() self.assertEqual(tree.em, None) self.assertEqual(tree.p.text, "Unneeded formatting is unneeded") def test_wrap(self): soup = self.soup("I wish I was bold.") value = soup.string.wrap(soup.new_tag("b")) self.assertEqual(value.decode(), "I wish I was bold.") self.assertEqual( soup.decode(), self.document_for("I wish I was bold.")) def test_wrap_extracts_tag_from_elsewhere(self): soup = self.soup("I wish I was bold.") soup.b.next_sibling.wrap(soup.b) self.assertEqual( soup.decode(), self.document_for("I wish I was bold.")) def test_wrap_puts_new_contents_at_the_end(self): soup = self.soup("I like being bold.I wish I was bold.") soup.b.next_sibling.wrap(soup.b) self.assertEqual(2, len(soup.b.contents)) self.assertEqual( soup.decode(), self.document_for( "I like being bold.I wish I was bold.")) def test_extract(self): soup = self.soup( 'Some content. More content.') self.assertEqual(len(soup.body.contents), 3) extracted = soup.find(id="nav").extract() self.assertEqual( soup.decode(), "Some content. More content.") self.assertEqual(extracted.decode(), '') # The extracted tag is now an orphan. self.assertEqual(len(soup.body.contents), 2) self.assertEqual(extracted.parent, None) self.assertEqual(extracted.previous_element, None) self.assertEqual(extracted.next_element.next_element, None) # The gap where the extracted tag used to be has been mended. content_1 = soup.find(text="Some content. ") content_2 = soup.find(text=" More content.") self.assertEqual(content_1.next_element, content_2) self.assertEqual(content_1.next_sibling, content_2) self.assertEqual(content_2.previous_element, content_1) self.assertEqual(content_2.previous_sibling, content_1) def test_extract_distinguishes_between_identical_strings(self): soup = self.soup("
                    foobar") foo_1 = soup.a.string bar_1 = soup.b.string foo_2 = soup.new_string("foo") bar_2 = soup.new_string("bar") soup.a.append(foo_2) soup.b.append(bar_2) # Now there are two identical strings in the tag, and two # in the tag. Let's remove the first "foo" and the second # "bar". foo_1.extract() bar_2.extract() self.assertEqual(foo_2, soup.a.string) self.assertEqual(bar_2, soup.b.string) def test_extract_multiples_of_same_tag(self): soup = self.soup(""" """) [soup.script.extract() for i in soup.find_all("script")] self.assertEqual("\n\n\n", unicode(soup.body)) def test_extract_works_when_element_is_surrounded_by_identical_strings(self): soup = self.soup( '\n' 'hi\n' '') soup.find('body').extract() self.assertEqual(None, soup.find('body')) def test_clear(self): """Tag.clear()""" soup = self.soup("

                    String Italicized and another

                    ") # clear using extract() a = soup.a soup.p.clear() self.assertEqual(len(soup.p.contents), 0) self.assertTrue(hasattr(a, "contents")) # clear using decompose() em = a.em a.clear(decompose=True) self.assertEqual(0, len(em.contents)) def test_string_set(self): """Tag.string = 'string'""" soup = self.soup(" ") soup.a.string = "foo" self.assertEqual(soup.a.contents, ["foo"]) soup.b.string = "bar" self.assertEqual(soup.b.contents, ["bar"]) def test_string_set_does_not_affect_original_string(self): soup = self.soup("foobar") soup.b.string = soup.c.string self.assertEqual(soup.a.encode(), b"barbar") def test_set_string_preserves_class_of_string(self): soup = self.soup("") cdata = CData("foo") soup.a.string = cdata self.assertTrue(isinstance(soup.a.string, CData)) class TestElementObjects(SoupTest): """Test various features of element objects.""" def test_len(self): """The length of an element is its number of children.""" soup = self.soup("123") # The BeautifulSoup object itself contains one element: the # tag. self.assertEqual(len(soup.contents), 1) self.assertEqual(len(soup), 1) # The tag contains three elements: the text node "1", the # tag, and the text node "3". self.assertEqual(len(soup.top), 3) self.assertEqual(len(soup.top.contents), 3) def test_member_access_invokes_find(self): """Accessing a Python member .foo invokes find('foo')""" soup = self.soup('') self.assertEqual(soup.b, soup.find('b')) self.assertEqual(soup.b.i, soup.find('b').find('i')) self.assertEqual(soup.a, None) def test_deprecated_member_access(self): soup = self.soup('') with warnings.catch_warnings(record=True) as w: tag = soup.bTag self.assertEqual(soup.b, tag) self.assertEqual( '.bTag is deprecated, use .find("b") instead. If you really were looking for a tag called bTag, use .find("bTag")', str(w[0].message)) def test_has_attr(self): """has_attr() checks for the presence of an attribute. Please note note: has_attr() is different from __in__. has_attr() checks the tag's attributes and __in__ checks the tag's chidlren. """ soup = self.soup("") self.assertTrue(soup.foo.has_attr('attr')) self.assertFalse(soup.foo.has_attr('attr2')) def test_attributes_come_out_in_alphabetical_order(self): markup = '' self.assertSoupEquals(markup, '') def test_string(self): # A tag that contains only a text node makes that node # available as .string. soup = self.soup("foo") self.assertEqual(soup.b.string, 'foo') def test_empty_tag_has_no_string(self): # A tag with no children has no .stirng. soup = self.soup("") self.assertEqual(soup.b.string, None) def test_tag_with_multiple_children_has_no_string(self): # A tag with no children has no .string. soup = self.soup("foo") self.assertEqual(soup.b.string, None) soup = self.soup("foobar
                    ") self.assertEqual(soup.b.string, None) # Even if all the children are strings, due to trickery, # it won't work--but this would be a good optimization. soup = self.soup("foo
                    ") soup.a.insert(1, "bar") self.assertEqual(soup.a.string, None) def test_tag_with_recursive_string_has_string(self): # A tag with a single child which has a .string inherits that # .string. soup = self.soup("foo") self.assertEqual(soup.a.string, "foo") self.assertEqual(soup.string, "foo") def test_lack_of_string(self): """Only a tag containing a single text node has a .string.""" soup = self.soup("feo") self.assertFalse(soup.b.string) soup = self.soup("") self.assertFalse(soup.b.string) def test_all_text(self): """Tag.text and Tag.get_text(sep=u"") -> all child text, concatenated""" soup = self.soup("ar t ") self.assertEqual(soup.a.text, "ar t ") self.assertEqual(soup.a.get_text(strip=True), "art") self.assertEqual(soup.a.get_text(","), "a,r, , t ") self.assertEqual(soup.a.get_text(",", strip=True), "a,r,t") def test_get_text_ignores_comments(self): soup = self.soup("foobar") self.assertEqual(soup.get_text(), "foobar") self.assertEqual( soup.get_text(types=(NavigableString, Comment)), "fooIGNOREbar") self.assertEqual( soup.get_text(types=None), "fooIGNOREbar") def test_all_strings_ignores_comments(self): soup = self.soup("foobar") self.assertEqual(['foo', 'bar'], list(soup.strings)) class TestCDAtaListAttributes(SoupTest): """Testing cdata-list attributes like 'class'. """ def test_single_value_becomes_list(self): soup = self.soup("") self.assertEqual(["foo"],soup.a['class']) def test_multiple_values_becomes_list(self): soup = self.soup("") self.assertEqual(["foo", "bar"], soup.a['class']) def test_multiple_values_separated_by_weird_whitespace(self): soup = self.soup("") self.assertEqual(["foo", "bar", "baz"],soup.a['class']) def test_attributes_joined_into_string_on_output(self): soup = self.soup("") self.assertEqual(b'', soup.a.encode()) def test_get_attribute_list(self): soup = self.soup("") self.assertEqual(['abc def'], soup.a.get_attribute_list('id')) def test_accept_charset(self): soup = self.soup('') self.assertEqual(['ISO-8859-1', 'UTF-8'], soup.form['accept-charset']) def test_cdata_attribute_applying_only_to_one_tag(self): data = '' soup = self.soup(data) # We saw in another test that accept-charset is a cdata-list # attribute for the tag. But it's not a cdata-list # attribute for any other tag. self.assertEqual('ISO-8859-1 UTF-8', soup.a['accept-charset']) def test_string_has_immutable_name_property(self): string = self.soup("s").string self.assertEqual(None, string.name) def t(): string.name = 'foo' self.assertRaises(AttributeError, t) class TestPersistence(SoupTest): "Testing features like pickle and deepcopy." def setUp(self): super(TestPersistence, self).setUp() self.page = """ Beautiful Soup: We called him Tortoise because he taught us. foo bar """ self.tree = self.soup(self.page) def test_pickle_and_unpickle_identity(self): # Pickling a tree, then unpickling it, yields a tree identical # to the original. dumped = pickle.dumps(self.tree, 2) loaded = pickle.loads(dumped) self.assertEqual(loaded.__class__, BeautifulSoup) self.assertEqual(loaded.decode(), self.tree.decode()) def test_deepcopy_identity(self): # Making a deepcopy of a tree yields an identical tree. copied = copy.deepcopy(self.tree) self.assertEqual(copied.decode(), self.tree.decode()) def test_copy_preserves_encoding(self): soup = BeautifulSoup(b'

                     

                    ', 'html.parser') encoding = soup.original_encoding copy = soup.__copy__() self.assertEqual(u"

                     

                    ", unicode(copy)) self.assertEqual(encoding, copy.original_encoding) def test_unicode_pickle(self): # A tree containing Unicode characters can be pickled. html = u"\N{SNOWMAN}" soup = self.soup(html) dumped = pickle.dumps(soup, pickle.HIGHEST_PROTOCOL) loaded = pickle.loads(dumped) self.assertEqual(loaded.decode(), soup.decode()) def test_copy_navigablestring_is_not_attached_to_tree(self): html = u"FooBar" soup = self.soup(html) s1 = soup.find(string="Foo") s2 = copy.copy(s1) self.assertEqual(s1, s2) self.assertEqual(None, s2.parent) self.assertEqual(None, s2.next_element) self.assertNotEqual(None, s1.next_sibling) self.assertEqual(None, s2.next_sibling) self.assertEqual(None, s2.previous_element) def test_copy_navigablestring_subclass_has_same_type(self): html = u"" soup = self.soup(html) s1 = soup.string s2 = copy.copy(s1) self.assertEqual(s1, s2) self.assertTrue(isinstance(s2, Comment)) def test_copy_entire_soup(self): html = u"
                    FooBar
                    end" soup = self.soup(html) soup_copy = copy.copy(soup) self.assertEqual(soup, soup_copy) def test_copy_tag_copies_contents(self): html = u"
                    FooBar
                    end" soup = self.soup(html) div = soup.div div_copy = copy.copy(div) # The two tags look the same, and evaluate to equal. self.assertEqual(unicode(div), unicode(div_copy)) self.assertEqual(div, div_copy) # But they're not the same object. self.assertFalse(div is div_copy) # And they don't have the same relation to the parse tree. The # copy is not associated with a parse tree at all. self.assertEqual(None, div_copy.parent) self.assertEqual(None, div_copy.previous_element) self.assertEqual(None, div_copy.find(string='Bar').next_element) self.assertNotEqual(None, div.find(string='Bar').next_element) class TestSubstitutions(SoupTest): def test_default_formatter_is_minimal(self): markup = u"<<Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!>>" soup = self.soup(markup) decoded = soup.decode(formatter="minimal") # The < is converted back into < but the e-with-acute is left alone. self.assertEqual( decoded, self.document_for( u"<<Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!>>")) def test_formatter_html(self): markup = u"
                    <<Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!>>" soup = self.soup(markup) decoded = soup.decode(formatter="html") self.assertEqual( decoded, self.document_for("
                    <<Sacré bleu!>>")) def test_formatter_html5(self): markup = u"
                    <<Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!>>" soup = self.soup(markup) decoded = soup.decode(formatter="html5") self.assertEqual( decoded, self.document_for("
                    <<Sacré bleu!>>")) def test_formatter_minimal(self): markup = u"<<Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!>>" soup = self.soup(markup) decoded = soup.decode(formatter="minimal") # The < is converted back into < but the e-with-acute is left alone. self.assertEqual( decoded, self.document_for( u"<<Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!>>")) def test_formatter_null(self): markup = u"<<Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!>>" soup = self.soup(markup) decoded = soup.decode(formatter=None) # Neither the angle brackets nor the e-with-acute are converted. # This is not valid HTML, but it's what the user wanted. self.assertEqual(decoded, self.document_for(u"<>")) def test_formatter_custom(self): markup = u"<foo>bar
                    " soup = self.soup(markup) decoded = soup.decode(formatter = lambda x: x.upper()) # Instead of normal entity conversion code, the custom # callable is called on every string. self.assertEqual( decoded, self.document_for(u"BAR
                    ")) def test_formatter_is_run_on_attribute_values(self): markup = u'e' soup = self.soup(markup) a = soup.a expect_minimal = u'e' self.assertEqual(expect_minimal, a.decode()) self.assertEqual(expect_minimal, a.decode(formatter="minimal")) expect_html = u'e' self.assertEqual(expect_html, a.decode(formatter="html")) self.assertEqual(markup, a.decode(formatter=None)) expect_upper = u'E' self.assertEqual(expect_upper, a.decode(formatter=lambda x: x.upper())) def test_formatter_skips_script_tag_for_html_documents(self): doc = """ """ encoded = BeautifulSoup(doc, 'html.parser').encode() self.assertTrue(b"< < hey > >" in encoded) def test_formatter_skips_style_tag_for_html_documents(self): doc = """ """ encoded = BeautifulSoup(doc, 'html.parser').encode() self.assertTrue(b"< < hey > >" in encoded) def test_prettify_leaves_preformatted_text_alone(self): soup = self.soup("
                    foo
                      \tbar\n  \n  
                    baz ") # Everything outside the
                     tag is reformatted, but everything
                            # inside is left alone.
                            self.assertEqual(
                                u'
                    \n foo\n
                      \tbar\n  \n  
                    \n baz\n
                    ', soup.div.prettify()) def test_prettify_accepts_formatter_function(self): soup = BeautifulSoup("foo", 'html.parser') pretty = soup.prettify(formatter = lambda x: x.upper()) self.assertTrue("FOO" in pretty) def test_prettify_outputs_unicode_by_default(self): soup = self.soup("") self.assertEqual(unicode, type(soup.prettify())) def test_prettify_can_encode_data(self): soup = self.soup("") self.assertEqual(bytes, type(soup.prettify("utf-8"))) def test_html_entity_substitution_off_by_default(self): markup = u"Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!" soup = self.soup(markup) encoded = soup.b.encode("utf-8") self.assertEqual(encoded, markup.encode('utf-8')) def test_encoding_substitution(self): # Here's the tag saying that a document is # encoded in Shift-JIS. meta_tag = ('') soup = self.soup(meta_tag) # Parse the document, and the charset apprears unchanged. self.assertEqual(soup.meta['content'], 'text/html; charset=x-sjis') # Encode the document into some encoding, and the encoding is # substituted into the meta tag. utf_8 = soup.encode("utf-8") self.assertTrue(b"charset=utf-8" in utf_8) euc_jp = soup.encode("euc_jp") self.assertTrue(b"charset=euc_jp" in euc_jp) shift_jis = soup.encode("shift-jis") self.assertTrue(b"charset=shift-jis" in shift_jis) utf_16_u = soup.encode("utf-16").decode("utf-16") self.assertTrue("charset=utf-16" in utf_16_u) def test_encoding_substitution_doesnt_happen_if_tag_is_strained(self): markup = ('
                    foo
                    ') # Beautiful Soup used to try to rewrite the meta tag even if the # meta tag got filtered out by the strainer. This test makes # sure that doesn't happen. strainer = SoupStrainer('pre') soup = self.soup(markup, parse_only=strainer) self.assertEqual(soup.contents[0].name, 'pre') class TestEncoding(SoupTest): """Test the ability to encode objects into strings.""" def test_unicode_string_can_be_encoded(self): html = u"\N{SNOWMAN}" soup = self.soup(html) self.assertEqual(soup.b.string.encode("utf-8"), u"\N{SNOWMAN}".encode("utf-8")) def test_tag_containing_unicode_string_can_be_encoded(self): html = u"\N{SNOWMAN}" soup = self.soup(html) self.assertEqual( soup.b.encode("utf-8"), html.encode("utf-8")) def test_encoding_substitutes_unrecognized_characters_by_default(self): html = u"\N{SNOWMAN}" soup = self.soup(html) self.assertEqual(soup.b.encode("ascii"), b"") def test_encoding_can_be_made_strict(self): html = u"\N{SNOWMAN}" soup = self.soup(html) self.assertRaises( UnicodeEncodeError, soup.encode, "ascii", errors="strict") def test_decode_contents(self): html = u"\N{SNOWMAN}" soup = self.soup(html) self.assertEqual(u"\N{SNOWMAN}", soup.b.decode_contents()) def test_encode_contents(self): html = u"\N{SNOWMAN}" soup = self.soup(html) self.assertEqual( u"\N{SNOWMAN}".encode("utf8"), soup.b.encode_contents( encoding="utf8")) def test_deprecated_renderContents(self): html = u"\N{SNOWMAN}" soup = self.soup(html) self.assertEqual( u"\N{SNOWMAN}".encode("utf8"), soup.b.renderContents()) def test_repr(self): html = u"\N{SNOWMAN}" soup = self.soup(html) if PY3K: self.assertEqual(html, repr(soup)) else: self.assertEqual(b'\\u2603', repr(soup)) class TestNavigableStringSubclasses(SoupTest): def test_cdata(self): # None of the current builders turn CDATA sections into CData # objects, but you can create them manually. soup = self.soup("") cdata = CData("foo") soup.insert(1, cdata) self.assertEqual(str(soup), "") self.assertEqual(soup.find(text="foo"), "foo") self.assertEqual(soup.contents[0], "foo") def test_cdata_is_never_formatted(self): """Text inside a CData object is passed into the formatter. But the return value is ignored. """ self.count = 0 def increment(*args): self.count += 1 return "BITTER FAILURE" soup = self.soup("") cdata = CData("<><><>") soup.insert(1, cdata) self.assertEqual( b"<><>]]>", soup.encode(formatter=increment)) self.assertEqual(1, self.count) def test_doctype_ends_in_newline(self): # Unlike other NavigableString subclasses, a DOCTYPE always ends # in a newline. doctype = Doctype("foo") soup = self.soup("") soup.insert(1, doctype) self.assertEqual(soup.encode(), b"\n") def test_declaration(self): d = Declaration("foo") self.assertEqual("", d.output_ready()) class TestSoupSelector(TreeTest): HTML = """ The title Hello there.

                    An H1

                    Some text

                    Some more text

                    An H2

                    Another

                    Bob

                    Another H2

                    me span1a1 span1a2 test span2a1

                    English

                    English UK

                    English US

                    French

                    """ def setUp(self): self.soup = BeautifulSoup(self.HTML, 'html.parser') def assertSelects(self, selector, expected_ids, **kwargs): el_ids = [el['id'] for el in self.soup.select(selector, **kwargs)] el_ids.sort() expected_ids.sort() self.assertEqual(expected_ids, el_ids, "Selector %s, expected [%s], got [%s]" % ( selector, ', '.join(expected_ids), ', '.join(el_ids) ) ) assertSelect = assertSelects def assertSelectMultiple(self, *tests): for selector, expected_ids in tests: self.assertSelect(selector, expected_ids) def test_one_tag_one(self): els = self.soup.select('title') self.assertEqual(len(els), 1) self.assertEqual(els[0].name, 'title') self.assertEqual(els[0].contents, [u'The title']) def test_one_tag_many(self): els = self.soup.select('div') self.assertEqual(len(els), 4) for div in els: self.assertEqual(div.name, 'div') el = self.soup.select_one('div') self.assertEqual('main', el['id']) def test_select_one_returns_none_if_no_match(self): match = self.soup.select_one('nonexistenttag') self.assertEqual(None, match) def test_tag_in_tag_one(self): els = self.soup.select('div div') self.assertSelects('div div', ['inner', 'data1']) def test_tag_in_tag_many(self): for selector in ('html div', 'html body div', 'body div'): self.assertSelects(selector, ['data1', 'main', 'inner', 'footer']) def test_limit(self): self.assertSelects('html div', ['main'], limit=1) self.assertSelects('html body div', ['inner', 'main'], limit=2) self.assertSelects('body div', ['data1', 'main', 'inner', 'footer'], limit=10) def test_tag_no_match(self): self.assertEqual(len(self.soup.select('del')), 0) def test_invalid_tag(self): self.assertRaises(ValueError, self.soup.select, 'tag%t') def test_select_dashed_tag_ids(self): self.assertSelects('custom-dashed-tag', ['dash1', 'dash2']) def test_select_dashed_by_id(self): dashed = self.soup.select('custom-dashed-tag[id=\"dash2\"]') self.assertEqual(dashed[0].name, 'custom-dashed-tag') self.assertEqual(dashed[0]['id'], 'dash2') def test_dashed_tag_text(self): self.assertEqual(self.soup.select('body > custom-dashed-tag')[0].text, u'Hello there.') def test_select_dashed_matches_find_all(self): self.assertEqual(self.soup.select('custom-dashed-tag'), self.soup.find_all('custom-dashed-tag')) def test_header_tags(self): self.assertSelectMultiple( ('h1', ['header1']), ('h2', ['header2', 'header3']), ) def test_class_one(self): for selector in ('.onep', 'p.onep', 'html p.onep'): els = self.soup.select(selector) self.assertEqual(len(els), 1) self.assertEqual(els[0].name, 'p') self.assertEqual(els[0]['class'], ['onep']) def test_class_mismatched_tag(self): els = self.soup.select('div.onep') self.assertEqual(len(els), 0) def test_one_id(self): for selector in ('div#inner', '#inner', 'div div#inner'): self.assertSelects(selector, ['inner']) def test_bad_id(self): els = self.soup.select('#doesnotexist') self.assertEqual(len(els), 0) def test_items_in_id(self): els = self.soup.select('div#inner p') self.assertEqual(len(els), 3) for el in els: self.assertEqual(el.name, 'p') self.assertEqual(els[1]['class'], ['onep']) self.assertFalse(els[0].has_attr('class')) def test_a_bunch_of_emptys(self): for selector in ('div#main del', 'div#main div.oops', 'div div#main'): self.assertEqual(len(self.soup.select(selector)), 0) def test_multi_class_support(self): for selector in ('.class1', 'p.class1', '.class2', 'p.class2', '.class3', 'p.class3', 'html p.class2', 'div#inner .class2'): self.assertSelects(selector, ['pmulti']) def test_multi_class_selection(self): for selector in ('.class1.class3', '.class3.class2', '.class1.class2.class3'): self.assertSelects(selector, ['pmulti']) def test_child_selector(self): self.assertSelects('.s1 > a', ['s1a1', 's1a2']) self.assertSelects('.s1 > a span', ['s1a2s1']) def test_child_selector_id(self): self.assertSelects('.s1 > a#s1a2 span', ['s1a2s1']) def test_attribute_equals(self): self.assertSelectMultiple( ('p[class="onep"]', ['p1']), ('p[id="p1"]', ['p1']), ('[class="onep"]', ['p1']), ('[id="p1"]', ['p1']), ('link[rel="stylesheet"]', ['l1']), ('link[type="text/css"]', ['l1']), ('link[href="blah.css"]', ['l1']), ('link[href="no-blah.css"]', []), ('[rel="stylesheet"]', ['l1']), ('[type="text/css"]', ['l1']), ('[href="blah.css"]', ['l1']), ('[href="no-blah.css"]', []), ('p[href="no-blah.css"]', []), ('[href="no-blah.css"]', []), ) def test_attribute_tilde(self): self.assertSelectMultiple( ('p[class~="class1"]', ['pmulti']), ('p[class~="class2"]', ['pmulti']), ('p[class~="class3"]', ['pmulti']), ('[class~="class1"]', ['pmulti']), ('[class~="class2"]', ['pmulti']), ('[class~="class3"]', ['pmulti']), ('a[rel~="friend"]', ['bob']), ('a[rel~="met"]', ['bob']), ('[rel~="friend"]', ['bob']), ('[rel~="met"]', ['bob']), ) def test_attribute_startswith(self): self.assertSelectMultiple( ('[rel^="style"]', ['l1']), ('link[rel^="style"]', ['l1']), ('notlink[rel^="notstyle"]', []), ('[rel^="notstyle"]', []), ('link[rel^="notstyle"]', []), ('link[href^="bla"]', ['l1']), ('a[href^="http://"]', ['bob', 'me']), ('[href^="http://"]', ['bob', 'me']), ('[id^="p"]', ['pmulti', 'p1']), ('[id^="m"]', ['me', 'main']), ('div[id^="m"]', ['main']), ('a[id^="m"]', ['me']), ('div[data-tag^="dashed"]', ['data1']) ) def test_attribute_endswith(self): self.assertSelectMultiple( ('[href$=".css"]', ['l1']), ('link[href$=".css"]', ['l1']), ('link[id$="1"]', ['l1']), ('[id$="1"]', ['data1', 'l1', 'p1', 'header1', 's1a1', 's2a1', 's1a2s1', 'dash1']), ('div[id$="1"]', ['data1']), ('[id$="noending"]', []), ) def test_attribute_contains(self): self.assertSelectMultiple( # From test_attribute_startswith ('[rel*="style"]', ['l1']), ('link[rel*="style"]', ['l1']), ('notlink[rel*="notstyle"]', []), ('[rel*="notstyle"]', []), ('link[rel*="notstyle"]', []), ('link[href*="bla"]', ['l1']), ('[href*="http://"]', ['bob', 'me']), ('[id*="p"]', ['pmulti', 'p1']), ('div[id*="m"]', ['main']), ('a[id*="m"]', ['me']), # From test_attribute_endswith ('[href*=".css"]', ['l1']), ('link[href*=".css"]', ['l1']), ('link[id*="1"]', ['l1']), ('[id*="1"]', ['data1', 'l1', 'p1', 'header1', 's1a1', 's1a2', 's2a1', 's1a2s1', 'dash1']), ('div[id*="1"]', ['data1']), ('[id*="noending"]', []), # New for this test ('[href*="."]', ['bob', 'me', 'l1']), ('a[href*="."]', ['bob', 'me']), ('link[href*="."]', ['l1']), ('div[id*="n"]', ['main', 'inner']), ('div[id*="nn"]', ['inner']), ('div[data-tag*="edval"]', ['data1']) ) def test_attribute_exact_or_hypen(self): self.assertSelectMultiple( ('p[lang|="en"]', ['lang-en', 'lang-en-gb', 'lang-en-us']), ('[lang|="en"]', ['lang-en', 'lang-en-gb', 'lang-en-us']), ('p[lang|="fr"]', ['lang-fr']), ('p[lang|="gb"]', []), ) def test_attribute_exists(self): self.assertSelectMultiple( ('[rel]', ['l1', 'bob', 'me']), ('link[rel]', ['l1']), ('a[rel]', ['bob', 'me']), ('[lang]', ['lang-en', 'lang-en-gb', 'lang-en-us', 'lang-fr']), ('p[class]', ['p1', 'pmulti']), ('[blah]', []), ('p[blah]', []), ('div[data-tag]', ['data1']) ) def test_quoted_space_in_selector_name(self): html = """
                    nope
                    yes
                    """ soup = BeautifulSoup(html, 'html.parser') [chosen] = soup.select('div[style="display: right"]') self.assertEqual("yes", chosen.string) def test_unsupported_pseudoclass(self): self.assertRaises( NotImplementedError, self.soup.select, "a:no-such-pseudoclass") self.assertRaises( NotImplementedError, self.soup.select, "a:nth-of-type(a)") def test_nth_of_type(self): # Try to select first paragraph els = self.soup.select('div#inner p:nth-of-type(1)') self.assertEqual(len(els), 1) self.assertEqual(els[0].string, u'Some text') # Try to select third paragraph els = self.soup.select('div#inner p:nth-of-type(3)') self.assertEqual(len(els), 1) self.assertEqual(els[0].string, u'Another') # Try to select (non-existent!) fourth paragraph els = self.soup.select('div#inner p:nth-of-type(4)') self.assertEqual(len(els), 0) # Pass in an invalid value. self.assertRaises( ValueError, self.soup.select, 'div p:nth-of-type(0)') def test_nth_of_type_direct_descendant(self): els = self.soup.select('div#inner > p:nth-of-type(1)') self.assertEqual(len(els), 1) self.assertEqual(els[0].string, u'Some text') def test_id_child_selector_nth_of_type(self): self.assertSelects('#inner > p:nth-of-type(2)', ['p1']) def test_select_on_element(self): # Other tests operate on the tree; this operates on an element # within the tree. inner = self.soup.find("div", id="main") selected = inner.select("div") # The
                    tag was selected. The