o åvŽf•Nã@sædZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl m Z ddl mZejjdkr[ddlmZmZmZddlmZddlmZmZeeeeeefd Zndd lmZmZmZmZdd lmZddlmZd Zzdd lmZddl m!Z!e!Wn e"ydZ!Ynwddl#Z$ddl$Z$ej% &d¡Z'dd„Z(dd„Z)Gdd„de$j*j+ƒZ+da,Gdd„deƒZ-Gdd„deƒZ.d!dd„Z/e0dkrñddl1Z1ddl2Z2ddl3m4Z4da*da5da6da7Gdd „d e1j8ƒZ9e1 :¡dSdS)"z,Crash database implementation for Launchpad.éN)ÚFailedToDecompressContent)ÚBytesIOé)Ú HTTPSHandlerÚRequestÚ build_opener)ÚHTTPSConnection)Ú urlencodeÚurlopenT)rrrr )r F)Ú HTTPError)Ú Launchpadz%~/.cache/apport/launchpad.credentialsc cs`|D]*}z|j ¡}Wnttfyt d¡Yqw|j}| d¡s*| d¡r-|VqdS)Nz"Broken attachment on bug, ignoringú.txtú.gz)ÚdataÚopenr rÚapportÚerrorÚfilenameÚendswith)Ú attachmentsÚ attachmentÚfÚname©rú?/usr/lib/python3/dist-packages/apport/crashdb_impl/launchpad.pyÚfilter_filename,s€ þ€ørcCstdd„|DƒƒS)Ncss$|] }t|j d¡ ¡ƒVqdS)ú/N)ÚintÚ self_linkÚsplitÚpop)Ú.0ÚirrrÚ :s€"zid_set..)Úset)ÚtasksrrrÚid_set8sr&c@seZdZdZdd„Zedd„ƒZdd„Zedd „ƒZdAd d „Z d d„Z dd„Z dd„Z dd„Z  dBdd„ZdCdd„Zdd„Zdd„Zdd „Zd!d"„Zd#d$„Zd%d&„Zd'd(„Zd)d*„Zd+d,„Zd-d.„Zd/d0„Zd1d2„Zd3d4„ZdAd5d6„Zd7d8„Zd9d:„Zd;d<„Z d=d>„Z!e"d?d@„ƒZ#d S)DÚ CrashDatabasez5Launchpad implementation of crash database interface.cCst d¡r t d¡|d<|s$| d¡}|r"td| dd¡d}nt}tjj |||¡| d¡|_ |j r?d|vs>Jd ƒ‚nd|vsGJd ƒ‚d |vrSd |d |_ nd tj   ¡|_ ||_ ||_|jsfJ‚d |_d |_t d| d¡¡|_|jsŒtjdd|_tjtj|jddd Sd S)aInitialize Launchpad crash database. You need to specify a launchpadlib-style credentials file to access launchpad. If you supply None, it will use default_credentials_path (~/.cache/apport/launchpad.credentials). Recognized options are: - distro: Name of the distribution in Launchpad - project: Name of the project in Launchpad (Note that exactly one of "distro" or "project" must be given.) - launchpad_instance: If set, this uses the given launchpad instance instead of production (optional). This can be overriden or set by $APPORT_LAUNCHPAD_INSTANCE environment. - cache_dir: Path to a permanent cache directory; by default it uses a temporary one. (optional). This can be overridden or set by $APPORT_LAUNCHPAD_CACHE environment. - escalation_subscription: This subscribes the given person or team to a bug once it gets the 10th duplicate. - escalation_tag: This adds the given tag to a bug once it gets more than 10 duplicates. - initial_subscriber: The Launchpad user which gets subscribed to newly filed bugs (default: "apport"). It should be a bot user which the crash-digger instance runs as, as this will get to see all bug details immediately. - triaging_team: The Launchpad user/team which gets subscribed after updating a crash report bug by the retracer (default: "ubuntu-crashes-universe") - architecture: If set, this sets and watches out for needs-*-retrace tags of this architecture. This is useful when being used with apport-retrace and crash-digger to process crash reports of foreign architectures. Defaults to system architecture. ÚAPPORT_LAUNCHPAD_INSTANCEÚlaunchpad_instanceÚ.z://ééÿÿÿÿÚdistroÚprojectz/Must not set both "project" and "distro" optionz0Need to have either "project" or "distro" optionÚ architecturezneed-%s-retraceNÚAPPORT_LAUNCHPAD_CACHEÚ cache_dirzlaunchpadlib.cache.)ÚprefixT)Ú ignore_errors)ÚosÚgetenvÚgetÚdefault_credentials_pathrrÚcrashdbr'Ú__init__r-Úarch_tagÚ packagingÚget_system_architectureÚoptionsÚauthÚ_CrashDatabase__launchpadÚ_CrashDatabase__lp_distroÚ_CrashDatabase__lpcacheÚtempfileÚmkdtempÚatexitÚregisterÚshutilÚrmtree)Úselfr>r=Ú lp_instancerrrr9@s6 !ÿ   ýzCrashDatabase.__init__c Cs|jr|jStdurtrtj d¡ntj d¡t d¡|j d¡r+|j d¡}nd}t j   |j ¡}|rAt j   |¡sAt  |¡ztjd||jdg|j d d |_W|jSty‚}z"t|d ƒre|j}nt|ƒ}t d ||j ¡t d ¡WYd}~|jSd}~ww)zReturn Launchpad instance.Nz^ERROR: The python-launchpadlib package is not installed. This functionality is not available. z_ERROR: The python3-launchpadlib package is not installed. This functionality is not available. r+r)Ú productionzapport-collectÚ WRITE_PRIVATEz1.0)Úlaunchpadlib_dirÚallow_access_levelsÚcredentials_fileÚversionÚcontentzZconnecting to Launchpad failed: %s You can reset the credentials by removing the file "%s"éc)r?r Ú_python2ÚsysÚstderrÚwriteÚexitr=r6r4ÚpathÚdirnamer>ÚisdirÚmakedirsÚ login_withrAÚ ExceptionÚhasattrrPÚstrrr)rHr)Úauth_dirÚeÚmsgrrrÚ launchpad‚s>     ûø €øzCrashDatabase.launchpadccsH|jst‚|D]}|j ¡|jkst d|j|j ¡¡r!|VqdS)Nz ^.+\(%s.*\)$)r-Ú StopIterationÚbug_target_nameÚlowerÚreÚmatch)rHr%ÚtrrrÚ_get_distro_tasks«s€ÿ€ýzCrashDatabase._get_distro_taskscCsX|jdur)|jr|jj|j|_|jSd|jvr%|jj|jd|_|jStdƒ‚|jS)Nr.z:distro or project needs to be specified in crashdb options)r@r-rbÚ distributionsr=ÚprojectsÚ SystemError©rHrrrÚ lp_distro´s  ûþzCrashDatabase.lp_distroNcCs>| |¡sJ‚| |¡}t||| ¡d}| ¡|sJ‚|S)aŸUpload given problem report return a handle for it. This should happen noninteractively. If the implementation supports it, and a function progress_callback is passed, that is called repeatedly with two arguments: the number of bytes already sent, and the total number of bytes to send. This can be used to provide a proper upload progress indication on frontends. )Úhostname)ÚacceptsÚ_generate_upload_blobÚ upload_blobÚ get_hostnameÚclose)rHÚreportÚprogress_callbackÚ blob_fileÚticketrrrÚuploadÀs  zCrashDatabase.uploadcCs0|j d¡}|r|dkrd}|Sd}|Sd}|S)z/Return the hostname for the Launchpad instance.r)Ústagingzstaging.launchpad.netz launchpad.devú launchpad.net)r=r6)rHr)rorrrrsÒs ýÿzCrashDatabase.get_hostnamecCs¬i}| d| ¡¡}|rt|tƒs| d¡}||d<| ¡}d|vr'|d}n|j d¡}|sLd|vrAd||j|d|t|ƒfSd||j|t|ƒfSd|||t|ƒfS) a/Return an URL that should be opened after report has been uploaded and upload() returned handle. Should return None if no URL should be opened (anonymous filing without user comments); in that case this function should do whichever interactive steps it wants to perform.ÚTitleúUTF-8z field.titleÚ SnapSourcer.Ú SourcePackagez,https://bugs.%s/%s/+source/%s/+filebug/%s?%sz!https://bugs.%s/%s/+filebug/%s?%s) r6Ústandard_titleÚ isinstanceÚbytesÚencodersr=r-r )rHruÚhandleÚargsÚtitleror.rrrÚget_comment_urlßs*    ÿÿ ÿzCrashDatabase.get_comment_urlcCs dt|ƒS)zõReturn URL for a given report ID. The report is passed in case building the URL needs additional information from it, such as the SourcePackage name. Return None if URL is not available or cannot be determined. z https://bugs.launchpad.net/bugs/)r^)rHruÚidrrrÚ get_id_urls zCrashDatabase.get_id_urlc Cs¢t ¡}|jj|}t d|jtj¡}|s!t d|jtjtjB¡}|s'Jdƒ‚|  d¡  d¡  dd¡  dd ¡}d |vr`d |vrX|  d d¡\}}|  d d ¡d |  d d¡d }n|  d d¡d }|  t|ƒ¡d |vrƒz |j ¡|d <Wnty‚|j|d <Ynwd|vr¸d|jvr‘d|d<n'd|jvr›d|d<nd|jvr¥d|d<nd|jvr¯d|d<n tdt|jƒƒ‚d |j¡|d<d|vrÊ|d|d<|j|d<t|jƒD]z}tj |j¡\} } zd|| <Wn tyîYqÔw| dkr| ¡|| <z ||  d¡|| <WqÔt yYqÔw| dkrHz t!j"|d ¡|| <WqÔt#yG} zd t| ƒvr2‚| $d ¡| ¡|| <WYd!} ~ qÔd!} ~ wwtd"|jƒ‚|S)#z>Download the problem report from given ID and return a Report.z(ProblemType:.*)$z^--- \r?$[\r\n]*(.*)z8bug description must contain standard apport format datar+r}s ó s ó s sUname:rÚDateÚ ProblemTypez apport-bugÚBugú apport-crashÚCrashzapport-kernelcrashÚ KernelCrashzapport-packageÚPackagez(cannot determine ProblemType from tags: ú ÚTagsr|Ú OriginalTitleÚr r)Úfileobjz Not a gzipNzUnknown attachment type: )%rÚReportrbÚbugsrfÚsearchÚ descriptionÚSÚMÚgrouprƒÚreplacerÚloadrÚ date_createdÚctimeÚAttributeErrorÚtagsÚ ValueErrorr^Újoinr†rrr4rWÚsplitextrr\ÚreadÚdecodeÚUnicodeDecodeErrorÚgzipÚGzipFileÚIOErrorÚseek) rHrˆruÚbÚmr›Úpart1Úpart2rÚkeyÚextr`rrrÚdownload sz   ÿ þ            ÿ  ÿ  €úzCrashDatabase.downloadFc Cs¦|jj|}|rt| ¡ƒt|ƒ}nd}t ¡} |j| |d|  ¡|  d¡t r1t   | ¡} nt   | ¡} |   ¡} t r@|  ¡pC|  ¡} |  ¡sJJ‚t rP|  ¡pS|  ¡} |  ¡rZJ‚|  ¡dksbJ‚|sŒ|jdd…} |  d¡d|vr| | |d¡ ¡7} | |_| ¡|jj|}| jdd d d ¡}|r³|r§|jd ||_| ¡n |s¬|j}|j||d | D]} |j|p¼d |  ¡d| jdd|  ¡ddqµ|  ¡dS)ahUpdate the given report ID with all data from report. This creates a text comment with the "short" data (see ProblemReport.write_mime()), and creates attachments for all the bulk/binary data. If change_description is True, and the crash db implementation supports it, the short data will be put into the description instead (like in a new bug). comment will be added to the "short" data. If attachment_comment is given, it will be added to the attachment uploads. If key_filter is a list or set, then only those keys will be added. N)Ú skip_keysrú text/plainúapport-collectedr”T©r©r}rŸz --- ©rPÚsubjectr–F©Úcommentr›Ú content_typerrÚis_patch)rbr™r$ÚkeysrBÚ TemporaryFileÚ write_mimeÚflushr®rRÚemailÚmessage_from_fileÚmessage_from_binary_fileÚwalkÚnextÚ__next__Ú is_multipartÚget_content_typer¤ÚappendÚ_filter_tag_namesrÚlp_saveÚ get_payloadr©r›r†Ú newMessageÚ addAttachmentÚ get_filenamert)rHrˆrur½Úchange_descriptionÚattachment_commentÚ key_filterÚbugr¶ÚmimeraÚmsg_iterÚpartÚxÚtextrrrÚupdateasR           ü zCrashDatabase.updater–c Cs€tjj ||||¡|jj|}d|vr7|jD]}|jj  d¡r6|j j |dd|_|  ¡|jj|}nq|  ¡r¸|jD]}|jdkrUz| ¡Wq>tyTYq>wq>z| |j¡}trd| ¡}n| ¡}|jdkrtd|_|  ¡Wn ty~Ynw| ¡}|r¸t d|j¡}|r¸| d¡|kr¸| d ¡|| d ¡|_z|  ¡Wn ty±Ynw|jj|}| ||¡d S) zÆUpdate the given report ID for retracing results. This updates Stacktrace, ThreadStacktrace, StacktraceTop, and StacktraceSource. You can also supply an additional comment. rú #distribution©rú CoreDump.gzÚ UndecidedÚMediumz,^(.*crashed with SIG.* in )([^( ]+)(\(\).*$)rr+éN)rr8r'Ú update_tracesrbr™Ú bug_tasksÚtargetÚresource_type_linkrrnÚgetSourcePackagerÎÚhas_useful_stacktracerr†Ú removeFromBugr rirRrÈrÉÚ importancercÚstacktrace_top_functionrfrgržÚ_subscribe_triaging_team) rHrˆrur½rÖÚtaskÚaÚfnr°rrrrã´sV   ü    ÿý   € ÿ  ÿ zCrashDatabase.update_tracescCs0|jj|}t d|j¡}|r| d¡Stdƒ‚)zNGet 'DistroRelease: ' from the given report ID and return it.z"DistroRelease: ([-a-zA-Z0-9.+/ ]+)r+z)URL does not contain DistroRelease: field)rbr™rfršr›ržr¥)rHrˆrÖr°rrrÚget_distro_releaseès  z CrashDatabase.get_distro_releasecCs`t d|j¡}|jj|}g}|jD]}| |jj¡}|sq|j dvr%q|  |  d¡¡q|S)z5Return list of affected source packages for given ID.z5/%s/(?:(?P[^/]+)/)?\+source/(?P[^/]+)$)ÚInvalidú Won't Fixú Fix ReleasedÚsource) rfÚcompiler-rbr™räršrårÚstatusrÌrž)rHrˆÚ bug_target_rerÖÚresultrírgrrrÚget_affected_packagesñsÿ   z#CrashDatabase.get_affected_packagescCs|jj|}|jj|jjjkS)z3Check whether the user is the reporter of given ID.)rbr™ÚownerrÚme©rHrˆrÖrrrÚ is_reporters zCrashDatabase.is_reportercCsZ|jj|}|jr dS|jj|jjjkrdS|jjj}|jjD] }|d|kr*dSqdS)aACheck whether the user is eligible to update a report. A user should add additional information to an existing ID if (s)he is the reporter or subscribed, the bug is open, not a duplicate, etc. The exact policy and checks should be done according to the particular implementation. FTÚ person_link) rbr™Ú duplicate_ofrúrrûrÚ subscriptionsÚentries)rHrˆrÖrûÚsubrrrÚ can_update s    ÿzCrashDatabase.can_updatec Cs^z|jj|jdd}t|ƒWSty.}zt dt|ƒ¡t  d¡WYd}~dSd}~ww)z}Return an ID set of all crashes which have not been retraced yet and which happened on the current host architecture.ú 2011-08-01©r¤Ú created_sinceú"connecting to Launchpad failed: %srQN) rnÚ searchTasksr:r&r\rrr^rSrV©rHr™r`rrrÚget_unretraced s €þzCrashDatabase.get_unretracedc Cs\z |jjddd}t|ƒWSty-}zt dt|ƒ¡t d¡WYd}~dSd}~ww)a#Return an ID set of all crashes which have not been checked for being a duplicate. This is mainly useful for crashes of scripting languages such as Python, since they do not need to be retraced. It should not return bugs that are covered by get_unretraced().úneed-duplicate-checkrrrrQN) rnrr&r\rrr^rSrVr rrrÚget_dup_unchecked*s €þzCrashDatabase.get_dup_uncheckedcCs|jjdd}t|ƒS)aOReturn an ID set of all crashes which are not yet fixed. The list must not contain bugs which were rejected or duplicate. This function should make sure that the returned list is correct. If there are any errors with connecting to the crash database, it should raise an exception (preferably IOError).r)r¤)rnrr&)rHr™rrrÚ get_unfixed9s zCrashDatabase.get_unfixedcCs"|jjjd||jjd}|djS)z­Return the version of given source package in the latest release of given distribution. If 'distro' is None, we will look for a launchpad project . T)Ú exact_matchÚ source_nameÚ distro_seriesr)rnÚ main_archiveÚgetPublishedSourcesÚcurrent_seriesÚsource_package_version)rHÚpackageÚsourcesrrrÚ_get_source_versionEs ý z!CrashDatabase._get_source_versionc sNzˆjj|}Wn tyYdSw|jrdSt|jƒ}ˆjrdˆj ¡‰tt‡fdd„|ƒƒ}|sCtt‡fdd„|ƒƒ}|rCdSt |ƒdkrSt   dˆj|¡dS|ro|  ¡}z ˆ  |j ¡d ¡WStynYdSwtt‡fd d„|ƒƒ}|r‹tt‡fd d„|ƒƒ}|s‹dSdSttd d„|ƒƒ}|ršdSttd d„|ƒƒr¥dSdS)aReturn the package version that fixes a given crash. Return None if the crash is not yet fixed, or an empty string if the crash is fixed, but it cannot be determined by which version. Return 'invalid' if the crash report got invalidated, such as closed a duplicate or rejected. This function should make sure that the returned result is correct. If there are any errors with connecting to the crash database, it should raise an exception (preferably IOError). Úinvalidz(%s)cs|jdko ˆ|j ¡vS©Nró©röÚbug_target_display_namere©rí©Údistro_identifierrrÚoó z1CrashDatabase.get_fixed_version..cs|jdko|j ¡ˆj ¡kSr)rördrer-rrmrrrss r–r+zVThere is more than one task fixed in %s %s, using first one to determine fixed versionrcs|jdvo ˆ|j ¡vS©N)rñròÚExpiredrrrrrr†r cs|jdvo ˆ|j ¡vSr!rrrrrrŠr cSó |jdkSr©rörrrrró cSr#)Nrñr$rrrrr”r%N)rbr™ÚKeyErrorrÿÚlisträr-reÚfilterÚlenrÚwarningr rrrÚ IndexError) rHrˆr¯r%Ú fixed_tasksÚ fixed_distroríÚ invalid_tasksÚnon_invalid_tasksr)rrHrÚget_fixed_versionSs\ ÿ ÿÿ  þÿ þ øzCrashDatabase.get_fixed_versioncCs|jj|j}|r |jSdS)zcReturn master ID for a duplicate bug. If the bug is not a duplicate, return None. N)rbr™rÿrˆ)rHrˆr¯rrrrÿ™szCrashDatabase.duplicate_ofc CsÎ|jj|}|rT||ksJdt|ƒƒ‚|jj|}|jr2|j}|j}|j|kr2t d||¡dS|jD]}|jdvrLz|  ¡Wq5t yKYq5wq5|jj|}|j d|dd|jj|}|j rhd|_ |jsn||_|j }t|jƒd kr·d |jvrš|jd |vrš|j d d ¡|vrš||jd g|_ | ¡d |jvr·|j d d ¡|vr·|jj|jd }|j|d| ¡rd|vsÅd|vr|j||d|gd¢d|jj|}|j dd…} z|  d¡Wn tyïYnwz|  d¡Wn tyYnw| |_ z| ¡Wn t yYnwdg} |jjD]} | jdvr'q|  | j¡qt|j ƒ} |j }|  |¡} | D] }|| vrJ| |¡q>||_ | ¡n|jr[d|_|j re| ¡dSdS)zlMark a crash id as duplicate of given master ID. If master is None, id gets un-duplicated. z+cannot mark bug %s as a duplicate of itselfzNBug %i was manually marked as a dupe of newer bug %i, not closing as duplicateN)rßzStacktrace.txtzThreadStacktrace.txtz ProcMaps.txtzProcStatus.txtz Registers.txtzDisassembly.txtaðThank you for taking the time to report this crash and helping to make this software better. This particular crash has already been reported and is a duplicate of bug #%i, so is being marked as such. Please look at the other bug report to see if there is any missing information that you can provide, or to see if there is a workaround for the bug. Additionally, any further discussion regarding the bug should occur in the other report. Please continue to report any other bugs you may find.zThis bug is a duplicaterºFé Úescalation_tagÚ escalated_tagz invalid Úescalation_subscription©Úpersonzapport-request-retraceúapport-failed-retracez)Updated stack trace from duplicate bug %i)Ú StacktraceÚThreadStacktracer’Ú DependenciesÚProcMapsÚ ProcCmdline)rÕzbugpattern-needed)zActive DevelopmentzCurrent Stable ReleaseÚ SupportedzPre-release Freeze)!rbr™r^rÿrˆrr*rr†rér rÐÚprivater¤r)Ú duplicatesr=r6rÎÚpeopleÚ subscriberèrÜÚremover¥rnÚseriesrörÌrr$Ú differenceÚ_dirty_attributes)rHrurˆÚ master_idrÖÚmasterrîÚ master_tagsÚprÚÚ tags_to_copyrCÚ dupe_tagsÚ missing_tagsÚtagrrrÚclose_duplicate¤s¢   ÿ    ÿú úù *  ÿ  ÿÿ ÿ      €  ÿzCrashDatabase.close_duplicatecCsD|jj|}|jd|dd|jj|}|jdg|_| ¡dS)zpMark a crash id as reintroducing an earlier crash which is already marked as fixed (having ID 'master').zíThis crash has the same stack trace characteristics as bug #%i. However, the latter was already fixed in an earlier package version than the one in this report. This might be a regression or because the problem is in a dependent package.zPossible regression detectedrºúregression-retracerN)rbr™rÐr¤rÎ)rHrˆrGrÖrrrÚmark_regressions ýü  zCrashDatabase.mark_regressioncCs`|jj|}|j|jvr.|jdd…}| |j¡||_z| ¡WdSty-YdSwdS)zMark crash id as retraced.N)rbr™r:r¤rBrÎr )rHrˆrÖrÚrrrÚ mark_retraced#s    ÿúzCrashDatabase.mark_retracedc CsÒ|jj|}|rUz| |j¡}tr| ¡}n| ¡}Wnty)|jd}Ynwd|_|  ¡|j |dd|j D]}|j dkrRz|  ¡Wq;tyQYq;wq;dSd|jvrg|jdg|_|  ¡dSdS)z%Mark crash id as 'failed to retrace'.rrñz Crash report cannot be processedrºrßr7N)rbr™rirärRrÈrÉrcrörÎrÐrr†rér r¤)rHrˆÚ invalid_msgrÖrírîrrrÚmark_retrace_failed0s:   € þÿ    ÿýÿ  þz!CrashDatabase.mark_retrace_failedc Csê|jj|}d|vr9|jD]+}|jj d¡r8|jj|dd|_z | ¡|jj|}Wn t y5Ynwnq d|j vrm|j dd…}|  d¡||_ | ¡d|vrm|jD]}d|jjvrl|j dkrld|_ | ¡qX|  ||¡dS) z/Mark crash id as checked for being a duplicate.rrÝrÞr NÚ Tracebackràrá)rbr™rärårærrnrçrÎr r¤rBrêrì)rHrˆrurÖrírÚrrrÚ_mark_dup_checkedNs8  ÿ þ÷     €zCrashDatabase._mark_dup_checkedcCs tjj ||¡}|s |S||d<zt|dƒ}Wn ty#|YSw| ¡}| d¡s/dS|D]}| d¡rFd|vs@d|vrCdS|S| ¡sM|Sq1|S) a¦Check if the crash db already knows about the crash signature. Check if the report has a DuplicateSignature, crash_signature(), or StacktraceAddressSignature, and ask the database whether the problem is already known. If so, return an URL where the user can check the status or subscribe (if available), or just return True if the report is known but there is no public URL. In that case the report will not be uploaded (i. e. upload() will not be called). Return None if the report does not have any signature or the crash database does not support checking for duplicates on the client side. The default implementation uses a text file format generated by duplicate_db_publish() at an URL specified by the "dupdb_url" option. Subclasses are free to override this with a custom implementation, such as a real database lookup. Ú DuplicateOfz/+textsbug:Tstags:sapport-failed-retracesapport-request-retraceN) rr8r'Úknownr r­ÚreadlineÚ startswithÚstrip)rHruÚurlrÚlinerrrrWns. ý  ýýzCrashDatabase.knowncCsxd|vr|d ¡ddkrdSd|jj|j dd¡f}| t|jjƒd¡ d ¡d d „|jDƒvr:|j |d dSdS) z-Subscribe the right triaging team to the bug.Ú DistroReleaserÚUbuntuNz%s~%sÚ triaging_teamzubuntu-crashes-universer–ú~cSsg|] }t|ƒ d¡d‘qS)rr,)r^r)r!rrrrÚ ²sz:CrashDatabase._subscribe_triaging_team..r5) rrbÚ _root_urir=r6rŸr^rZrrA)rHrÖrur6rrrrì¥s ÿÿþz&CrashDatabase._subscribe_triaging_teamcCsni}d|d ¡|d<| d¡}|r|dkr| d¡}|r(|dd|7<d|vr;|dd| |d¡7<d|vr}|rid |vsMd |vsMd |vrid |d <| d|j dd¡¡|d<|dd|7<nd|vr}d |d <d|d<|dd7<d|vrd|dvr|dd7<d|vr™|d|d<gd¢}t ¡}|j||gd¢|d| ¡| d¡|S)zGenerate a multipart/MIME temporary file for uploading. You have to close the returned file object after you are done with it. z apport-%srr”ÚPackageArchitectureÚallÚ Architecturer“r]ÚVmCoreÚCoreDumpÚLaunchpadPrivateÚyesÚPrivateÚLaunchpadSubscribeÚinitial_subscriberrÚ Subscribersz need-%s-retracerTz need-duplicate-checkÚDuplicateSignaturer ÚCheckboxSubmissionzHWDB-Submission) rr]r’Ú RegressionÚ ReproducibleÚTestedUpstreamÚProcVersionSignatureÚUnameÚNonfreeKernelModules)r”rhrk)Ú extra_headersr¶Úpriority_fieldsr) rer6rÍr=rBrÁrÂrÃr®)rHruÚhdrrîÚorderr×rrrrqµsB    ÿ þ z#CrashDatabase._generate_upload_blobcCs`d}| ¡jdddD]"}|dvst|ƒdkr)|dvr)tr"||7}q |t|ƒ7}q |d7}q |S) zAReplace characters from tags which are not palatable to Launchpadr–ÚASCIIÚignore)Úerrorss%abcdefghijklmnopqrstuvwxyz0123456789 rs+-.r*)rerƒr)rRÚchr)Úklassr¤ÚresÚchrrrrÍçs  zCrashDatabase._filter_tag_names©N)FNN)r–)$Ú__name__Ú __module__Ú __qualname__Ú__doc__r9Úpropertyrbrirnryrsr‡r‰rµrÜrãrðrùrýrr r r rr0rÿrNrPrQrSrUrWrìrqÚ classmethodrÍrrrrr'=sJB (   # U ÿ S4   F q  72r'c@seZdZdZdd„ZdS)ÚHTTPSProgressConnectionzWImplement a HTTPSConnection with an optional callback function for upload progress.cCs¨ts t ||¡dSd}t|ƒ}d}||krRt||ƒt ¡}t |||||…¡||7}t ¡}|dkrL||dkrB|dK}n ||dkrL|dL}||ksdSdS)Nrigà?r+r)Ú_https_upload_callbackrÚsendr)Útime)rHrÚsentÚtotalÚ chunksizeÚt1Út2rrrrŠs$     ózHTTPSProgressConnection.sendN)r‚rƒr„r…rŠrrrrrˆs rˆc@seZdZdd„ZdS)ÚHTTPSProgressHandlercCs | t|¡Sr)Údo_openrˆ)rHÚreqrrrÚ https_open$s zHTTPSProgressHandler.https_openN)r‚rƒr„r”rrrrr‘"s r‘r{c Csd}d|}|atjj ¡}tjj d¡}| dd¡| |¡tjj   dd¡}| dd¡|  |  ¡  d ¡¡| |¡tƒ}tjjd krOtjj|d d } ntjj|d d } |  |¡t|| ¡ƒ} |  d d| ¡¡ttƒ} |  | ¡} |  ¡ d¡}|sJ‚|S)a Upload blob (file-like object) to Launchpad. progress_callback can be set to a function(sent, total) which is regularly called with the number of bytes already sent and total number of bytes to send. It is called every 0.5 to 2 seconds (dynamically adapted to upload bandwidth). Return None on error, or the ticket number on success. By default this uses the production Launchpad hostname. Set hostname to 'launchpad.dev' or 'staging.launchpad.net' to use another instance for testing. Nzhttps://%s/+storeblobÚ1zContent-Dispositionzform-data; name="FORM_SUBMIT"Ú applicationz octet-streamz*form-data; name="field.blob"; filename="x"ÚasciirF)Ú mangle_from_z Content-Typezmultipart/form-data; boundary=zX-Launchpad-Blob-Token)r‰rÄr×Ú multipartÚ MIMEMultipartrÛÚMIMETextÚ add_headerÚattachÚbaseÚMIMEBaseÚ set_payloadr¨r©rrSÚ version_infoÚmajorÚ generatorÚ GeneratorÚBytesGeneratorÚflattenrÚgetvalueÚ get_boundaryrr‘rÚinfor6) Úblobrvrorxr[rÚsubmitÚ form_blobÚ data_flatÚgenr“Úopenerrørrrrr(s.        rrÚ__main__)Úpatchc@sTeZdZdZdZdd„Zdd„Zedd„ƒZdNd d „Z d d „Z dNd d„Z dd„Z dd„Z dd„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd „Zd!d"„Zd#d$„Zd%d&„Zd'd(„Zd)d*„Zd+d,„Zd-d.„Ze ed/¡d0d1„ƒZe d2d3„ƒZ!d4d5„Z"dOd7d8„Z#d9d:„Z$d;d<„Z%d=d>„Z&d?d@„Z'dAdB„Z(dCdD„Z)dEdF„Z*dGdH„Z+dIdJ„Z,e dPdLdM„ƒZ-d6S)QÚ_TÚ coreutilscCsHts| ¡at|_t ¡|_|j ¡|j ¡d|jd<| d¡dS)Nr³rúlangpack-o-matic)r8Ú _get_instancerr˜Ú ref_reportÚ add_os_infoÚ add_user_infoÚ_create_projectrmrrrÚsetUprs    z_T.setUpcCs@|jjj|}|s|jjjj|d|||d|dddSdS)z8Create a project using launchpadlib to be used by tests.r›Úsummaryr†)r›Ú display_namerr»r†N)r8rbrkÚ new_project)rHrr.rrrr¹‚s  ûÿz_T._create_projectcCs |j ¡S)z1Get the Launchpad hostname for the given crashdb.)r8rsrmrrrroŽs z _T.hostnameFcCs°|stdurtS| ¡}| |j¡| ¡| ¡| ¡| | ¡d¡d|d<d|d<|  |j |¡}|  |¡|  ||¡}|  |dk¡t j d|j|f¡|sV|a|S) zÇGenerate SEGV crash report. This is only done once, subsequent calls will return the already existing ID, unless force_fresh is True. Return the ID. Nú!crash crashed with SIGSEGV in f()u "]¶" ÚShortGibberishõa b c d e ÿÿÿ Ú LongGibberishrz*(Created SEGV report: https://%s/bugs/%i) )Ú _segv_reportÚ_generate_sigsegv_reportÚadd_package_infoÚ test_packager·Ú add_gdb_infor¸Ú assertEqualr€Ú_get_bug_targetr8Ú assertTrueÚ _file_bugrSrTrUro)rHÚ force_freshÚrÚ bug_targetrˆrrrÚget_segv_report”s$    z_T.get_segv_reportcCsªtdurtSt d¡}d|d<d|d<d|d<| |j¡| ¡| ¡| | ¡d ¡|  |j |¡}|  |¡|  ||¡}|  |d k¡t j d |j|f¡|a|S) zFGenerate Python crash report. Return the ID. Nrú/bin/fooÚExecutablePathú…Traceback (most recent call last): File "/bin/foo", line 67, in fuzz print(weird) NameError: global name 'weird' is not definedrTzboogus pybogusr”úHfoo crashed with NameError in fuzz(): global name 'weird' is not definedrz,(Created Python report: https://%s/bugs/%i) )Ú_python_reportrr˜rÄrÅr·r¸rÇr€rÈr8rÉrÊrSrTrUro)rHrÌrÍrˆrrrÚget_python_report·s&   ÿ  z_T.get_python_reportcCsV|stdurtSd}|jjjjd||jjd}tj d|j |j f¡|s(|j a|j S)a­File a bug report with an uncommon description. This is only done once, subsequent calls will return the already existing ID, unless force_fresh is True. Example taken from real LP bug 269539. It contains only ProblemType/Architecture/DistroRelease in the description, and has free-form description text after the Apport data. Return the ID. Nzbproblem ProblemType: Package Architecture: amd64 DistroRelease: Ubuntu 8.10 more text and more zmixed description bug)r†r›råz3(Created uncommon description: https://%s/bugs/%i) ) Ú_uncommon_description_reportr8rbr™Ú createBugrnrSrTrUrorˆ)rHrËÚdescrÖrrrÚget_uncommon_description_reportÖs  ýz"_T.get_uncommon_description_reportc CsÒ|j | ¡¡}| |dd¡| |dd¡| |d|jd¡| |d|jd¡| |d|jd¡| | d¡|j d¡¡| | d ¡|j d ¡¡t|d  ¡ƒ}| |t|jjd t j   ¡gƒ¡| |d d ¡|  |d  d¡¡| |d|j¡|  |d |jd¡¡| d|d¡| d|d¡| d|d¡| t|dƒd¡| d|¡| d|¡| d|¡|j | ¡¡}t|d  ¡ƒ}| |td dddt j   ¡gƒ¡dS) z download()rrr|r¾r]rertruÚ UserGroupsr”rÚSignalÚ11rÐz/crashrr’r“zf (x=42)r8Ú StacktraceTopr9rgièr:Ú DisassemblyÚ RegistersÚboogusÚpybogusr N)r8rµrÎrÇr¶r6r$rr:rr;r<rÉrÚtest_srcpackagerYrÅÚassertInÚ assertGreaterr)rÔ)rHrÌr¤rrrÚtest_1_downloadús<  ÿÿ     ÿz_T.test_1_downloadcCsø|j | ¡¡}| d|¡| d|¡| d|¡| d|¡| d|¡| d|¡| |dd¡d |d <d |d<d |d<d |d<|j | ¡|d¡|j | ¡¡}| d|¡| d|¡| d|¡| d|¡| d|¡| d|¡| d|¡| |dd¡|jjj| ¡j }| d|¡| d|¡d|d <d |d<d |d<|j | ¡|d¡|j | ¡¡}| d|¡| d|¡| d|¡| d|¡| d|¡| d|¡| d|¡| |dd¡|jjj| ¡}d|_ z|  ¡Wn t y Ynwd|d <|j | ¡|d¡|j | ¡¡}| |dd¡|jjj| ¡}d|_ z|  ¡Wn t yEYnwd|d <|j | ¡|d¡|j | ¡¡}| |dd¡d|d<d|d<d|d<|j | ¡|d¡dS) zupdate_traces()rgr:rÝrÞr8r9r|r¾z?? ()rÜú long traceúthread even longer traceÚbogusÚFooBarzI can has a better retrace?rr¸ú=read () from /lib/libc.6.so foo (i=1) from /usr/lib/libfoo.soú good retrace!z$crash crashed with SIGSEGV in read()z)crash crashed with SIGSEGV in f() on exitz!good retrace with title amendmentz,crash crashed with SIGSEGV in read() on exitzcrash is crashyzgood retrace with custom titler–u"]¶" rÀÚStacktraceSourceÚtestsN) r8rµrÎrârÇrãÚ assertNotInrbr™r¤r†rÎr )rHrÌr¤rÖrrrÚtest_2_update_tracess€                       ÿ ÿz_T.test_2_update_tracescCsŠd}t d¡}||d<|j |d¡}| | d¡¡| d¡|d<|j |d¡}| | d¡¡d|d<|j |d¡}| | d ¡¡d S) z&get_comment_url() for non-ASCII titless1ä♥2rŽr|é*z1/ubuntu/+filebug/42?field.title=1%C3%A4%E2%99%A52r}r³rzC/ubuntu/+source/coreutils/+filebug/42?field.title=1%C3%A4%E2%99%A52N)rr˜r8r‡rÉrr©)rHr†rÌr[rrrÚtest_get_comment_urlms z_T.test_get_comment_urlcCs |jjjdd}|jjjjd|dd}|j}| |dk¡tj   d|j |f¡t   d¡}d  d ¡|d <d |d <d|d<d|d<d|d<|jj||ddd|j |¡}| |d d  d ¡¡| |dd¡| |dd¡| |dd¡| |jjj|jdg¡dS)z"update() with changing descriptionÚbashrÞztest description for test bug.Útestbug©r›rår†rú(https://%s/bugs/%i) rŽsbogus→r}ÚOneLinerú f() g() h(1)rÜúlineone linetwoÚShortGooúone two three four five sixÚDpkgTerminalLogsÚVarLogDistupgradeBinGooÚNotMeT©rÓr¸N)r8rnrçrbr™rÖrˆrÉrSrTrUrorr˜r©rÜrµrÇr¤©rHrÍrÖrˆrÌrrrÚtest_update_descriptionƒs0 ý  ÿz_T.test_update_descriptioncCs|jjjdd}|jjjjd|dd}|j}| |dk¡tj   d|j |f¡t   d¡}d |d <d |d <d |d<d|d<d|d<|jj||ddd|j |¡}| d |¡| d|¡| |dd¡| |dd¡| |dd¡| |jjj|jdg¡dS)zupdate() with appending commentrñrÞzPr0blem --- ProblemType: BugròrórrôrŽõbogus→rõrörÜr÷rørùrúárûÚmeowFrýrr¸N©r8rnrçrbr™rÖrˆrÉrSrTrUrorr˜rÜrµrírÇr¤rþrrrÚtest_update_comment£s2 ý    ÿz_T.test_update_commentcCs |jjjdd}|jjjjd|dd}|j}| |dk¡tj   d|j |f¡t   d¡}d |d <d |d <d |d<d|d<d|d<|jj||ddgd¢d|j |¡}| d |¡| |dd ¡| |dd¡| |dd¡| d|¡| |jjj|jg¡dS)zupdate() with a key filterrñrÞztest description for test bugròrórrôrŽrrõrörÜr÷rørùrúrrûrüT)rrørú)rÓrÕrNrrþrrrÚtest_update_filterÆs2 ý ÿ   z_T.test_update_filtercCs"| |j | ¡¡|jd¡dS)zget_distro_release()r]N)rÇr8rðrÎr¶rmrrrÚtest_get_distro_releaseçsÿz_T.test_get_distro_releasecCs$| |j | ¡¡|jdg¡dS)zget_affected_packages()rN)rÇr8rùrÎr¶rmrrrÚtest_get_affected_packagesís ÿz_T.test_get_affected_packagescCó,| |j | ¡¡¡| |j d¡¡dS)z is_reporter()r+N)rÉr8rýrÎÚ assertFalsermrrrÚtest_is_reporteróóz_T.test_is_reportercCr)z can_update()r+N)rÉr8rrÎr rmrrrÚtest_can_updateùr z_T.test_can_updatecCsø| |j | ¡¡d¡| |j | ¡¡d¡| ¡}| ¡}|jdd}|j |¡}|j |||¡| |j |¡|¡|j |||¡| |j |¡|¡| |j |¡d¡|j ||d¡| |j |¡d¡| |j |¡d¡|j | ¡¡}| d|¡| d|¡| d|¡| d|¡| d |¡| d |¡|j t   ¡||¡|j |||¡| |j |¡|¡|j t   ¡|d¡|j t   ¡|d¡|j ||d¡|j t   ¡|d¡| |j |¡d¡|j  ||¡|  |¡dS) zduplicate handlingNT©rËrrgrÝr;Ú ProcStatusrÞr9) rÇr8rÿrÎr0rØrµrNrírr˜rPÚ_verify_marked_regression)rHÚsegv_idÚ known_test_idÚknown_test_id2rÌrrrÚtest_duplicatesÿsF        ÿÿz_T.test_duplicatescCs†|j ¡}| | ¡|¡| | ¡|¡|j | ¡¡|j ¡}| | ¡|¡| || t | ¡gƒ¡¡| |j  | ¡¡d¡|  | ¡¡|j | ¡¡|j  | ¡¡|j ¡}| | ¡|¡| || t | ¡gƒ¡¡| |j  | ¡¡d¡|  | ¡¡|j | ¡¡|j  | ¡d¡|j ¡}| | ¡|¡| || t | ¡gƒ¡¡| |j  | ¡¡d¡dS)z-processing status markings for signal crashesNzI don't like your) r8r rârÎrírÔrQrÇÚunionr$r0Ú_mark_needs_retracerS)rHÚunretraced_beforeÚunretraced_afterrrrÚtest_marking_segv5s<  ÿ ÿ ÿÿz_T.test_marking_segvcCsÜ|jjjjd|jj|jjdd}tj d¡pd}t tj d¡d|dœƒ}|jjjd |j|jd d}|  ¡}|  |j |¡|  |j |¡| |j ¡|  ¡}|  |j |¡| || t|j gƒ¡¡| |j |j ¡d ¡d S) ú0processing status markings for a project CrashDBÚfoozubuntu distro retrace bug©r›r¤rår†r(rzÚLP_CREDENTIALSr´©r.r)Úbarzproject retrace bugN)r8rbr™rÖr:rnr4Úenvironr6r'r rârˆrírQrÇrr$r0)rHÚ distro_bugr)Ú project_dbÚ project_bugrrrrrÚtest_marking_projectXs6 ü þü ÿz_T.test_marking_projectcCs¤tj d¡pd}ttj d¡d|ddœƒ}| ¡}|j ¡}|jjjjddg|jj d d }t d |j ƒ| ¡}|j ¡}|  ||¡|  ||  t|j gƒ¡¡d S) rr(rzrÚubuntuÚfakearch)r-r)r/rzneed-fakearch-retracez&ubuntu distro retrace bug for fakearchrz4fake arch bug: https://staging.launchpad.net/bugs/%iN)r4rr6r'r r8rbr™rÖrnÚprintrˆrÇrr$)rHr)Ú fakearch_dbÚfakearch_unretraced_beforeÚsystemarch_unretraced_beforerÖÚfakearch_unretraced_afterÚsystemarch_unretraced_afterrrrÚtest_marking_foreign_arch{s, ÿþ  ü  ÿz_T.test_marking_foreign_archcCs|j ¡}| | ¡|¡| | ¡|¡|j | ¡|j¡|j ¡}| | ¡|¡| ||  t | ¡gƒ¡¡| |j  | ¡¡d¡dS)z2processing status markings for interpreter crashesN) r8r rârÔrírÎrUr¶rÇrr$r0)rHÚunchecked_beforeÚunchecked_afterrrrÚtest_marking_python—s  ÿz_T.test_marking_pythoncCsp|jdd}|j |¡}|j ||| ¡¡d|d<d|d<d|d<|j ||d ¡|j |¡}| d |¡d S) z¬updating an invalid crash This simulates a race condition where a crash being processed gets invalidated by marking it as a duplicate. Tr rérÜrår8rær9rêrgN)rÎr8rµrNrãrí)rHrˆrÌrrrÚtest_update_traces_invalid¤s   z_T.test_update_traces_invalidrcGs\dtj_| | ¡¡|j | ¡¡}| |d¡| | ¡¡| |j | ¡¡d¡dS)zÃget_fixed_version() for fixed bugs Other cases are already checked in test_marking_segv() (invalid bugs) and test_duplicates (duplicate bugs) for efficiency. z3.14N) r'rÚ return_valueÚ_mark_report_fixedrÎr8r0rÇÚ_mark_report_new)rHr…Ú fixed_verrrrÚtest_get_fixed_version¹s   z_T.test_get_fixed_versioncCs(tj d¡pd}ttj d¡d|dœƒS)zCreate a CrashDB instancer(rzrr$)r-r))r4rr6r')r~r)rrrrµÍs  ÿÿz_T._get_instancecCs<|j d¡}d|vr|jj|ddS|r|jj|S|jS)z&Return the bug_target for this report.r.rrÞ)r=r6rnrçrbrk)rHÚdbrur.rrrrÈ×s  z_T._get_bug_targetNc CsL|durd}|j |¡}trt |¡}nt |¡}| ¡| ¡}tr'| ¡p*|  ¡}|  ¡s1J‚tr7| ¡p:|  ¡}|  ¡rAJ‚|  ¡dksIJ‚|d|j dd  dd¡7}|jjjj||d  ¡|| d | ¡¡d } |D]}|  ¡rwJ‚| jd | ¡d|j dd| ¡d dqo|d ¡D]} |jjj| } | r¢| j| dq‘| jS)zLFile a bug report for a report. Return the bug ID. Nzsome descriptionr·z Tr¹r}rŸr”r|rr–Fr¼rmr5)r8rqrRrÄrÅrÆrtrÇrÈrÉrÊrËrÏr©rbr™rÖrr6r€rÑrÒr@rArˆ) rHrÍrur›r×rarØÚheaderrÙrÖÚ subscriberrrrrrÊâsD        ù  ü €z _T._file_bugcCs>|jjj|}|jj|jvr|j|jjg|_| ¡dSdS)z$Mark a report ID as needing retrace.N)r8rbr™r:r¤rÎrürrrrs  þz_T._mark_needs_retracecCs6|jjj|}d|jvr|jdg|_| ¡dSdS)z,Mark a report ID as needing duplicate check.r N)r8rbr™r¤rÎrürrrÚ_mark_needs_dupcheck$s   þz_T._mark_needs_dupcheckcCóB|jjj|}t|jƒ}t|ƒdksJ‚|d}d|_| ¡dS)zClose a report ID as "fixed".r+rróN©r8rbr™r'rär)rörΩrHrˆrÖr%rhrrrr2,ó   z_T._mark_report_fixedcCr:)zReopen a report ID as "new".r+rÚNewNr;r<rrrr36r=z_T._mark_report_newcCs |jjj|}| d|j¡dS)z.Verify that report ID is marked as regression.rON)r8rbr™râr¤rürrrr@sz_T._verify_marked_regressioncCsvtj d¡pd}ttj d¡d|dœƒ}| |jd¡t d¡}d|d <d |d <| ¡|  ¡| |  ¡d ¡|  ||¡}| |j d¡|  ||¡}| |d k¡tj d|j|f¡| |¡}d|d<d|d<d|d<| ||d¡| |¡}| | |¡d¡| ||| ¡¡| | |¡| ¡¡| | |¡d¡| ||d¡| | |¡d¡| | |¡d¡dS)z7reporting crashes against a project instead of a distror(rzrr´rNrrÏrÐrÑrTrÒrrôrérÜrår8rær9rêr)r4rr6r'rÇr-rr˜r·r¸r€rÈrrÊrÉrSrTrUrorµrãr0rNrØrÿ)rHr)r8rÌrÍrˆrrrÚ test_projectFsB ÿÿ  ÿ    z_T.test_projectcCsH|j | ¡¡}| |dd¡| |dd¡| |d d¡¡dS)z*download() of uncommon description formatsrr’reÚamd64r]zUbuntu N)r8rµrØrÇrÉrY)rHrÌrrrÚtest_download_robustnessvsz_T.test_download_robustnessc sxtj d¡pd}ttj d¡d|dddœƒ}d}|jj|jd j‰d }zst||d ƒD]N}|d 7}t j   d |¡|  t  ¡|| ¡¡|jj| ¡}|jd|jv}t‡fdd„|jDƒƒ}|dkrp| |¡| |¡q,| |¡| |¡q,Wt|||ƒD]}t j   d|¡|  t  ¡|d¡qƒnt|||ƒD]}t j   d|¡|  t  ¡|d¡qŸwt j   d¡dS)z,Escalating bugs with more than 10 duplicatesr(rzrr$Ú omgkittenszapport-hackers)r-r)r2r4rr4iV'é r+z%i r2csg|]}|jˆk‘qSr)rþ)r!Ús©rIrrra”sz&_T.test_escalation..r1zR%i NÚ )r4rr6r'rbr@r=rÚrangerSrTrUrNrr˜rÎr™r¤Úanyrr rÉ)rHr)r6ÚcountÚ first_dupr¯Úhas_escalation_tagÚhas_escalation_subscriptionrrErÚtest_escalationsB ýÿ    ôþþz_T.test_escalationcCs„| | ¡¡|j ¡}| | ¡|¡|jjj| ¡}|jr'd|_| ¡|j d}|jjj d|_ | ¡|j |jjj dd|j | ¡¡}|j | ¡|¡|j ¡}| | ¡|¡| || t| ¡gƒ¡¡|jjj| ¡}| |j djd¡| |j djd¡| |j djd¡| |j djd ¡| |j djd¡| |j djd ¡| |j | ¡¡d ¡d S) z9source package task fixup for marking interpreter crashesFrr$r³)rår>ràr+zcoreutils (Ubuntu)ráN)r9rÔr8r rârbr™r>rÎrärjråÚaddTaskrkrµrUrírÇrr$rdrörêr0)rHr-r¯rhrÌr.rrrÚtest_marking_python_task_mangle¡s4   ÿz"_T.test_marking_python_task_manglerÛc Cs0d}t ¡}tj ¡}z†t ¡}t t j |¡t  |¡t ddƒ }|  d¡Wdƒn1s1wYt gd¢¡dksAJ‚tj d¡sIJ‚tjgd¢tjd tj d ¡s[J‚t d g¡tjgd ¢tjd dksoJ‚tj |d¡|d <tj |d ¡f|d<||d<| ¡Wt  |¡|St  |¡w)aCreate a test executable which will die with a SIGSEGV, generate a core dump for it, create a problem report with those two arguments (ExecutablePath and CoreDump) and call add_gdb_info(). Return the apport.report.Report. Núcrash.cÚwzS int f(x) { int* p = 0; *p = x; return x+1; } int main() { return f(42); } )Úgccz-grPz-oÚcrashrrS)Úgdbz--batchú--exÚrunrUzgenerate-core-file corez./crash)ÚstdoutÚcoreÚsync)Úreadelfz-nrXrÐrgrÚ)r4Úgetcwdrrur˜rBrCrDrErFrGÚchdirrrUÚ subprocessÚcallrWÚexistsÚPIPEÚ check_callr¦rÆ)r~ÚsignalÚworkdirÚorig_cwdÚprÚfdrrrrÃÊs:    ÿ ÿ  ÿÿ   þz_T._generate_sigsegv_report)Fr)rÛ).r‚rƒr„rÅrárºr¹r†rorÎrÔrØrärîrðrÿrrrrr r rrr#r,r/r0r±Úobjectr'r5r‡rµrÈrÊrr9r2r3rr?rArMrOrÃrrrrr²hsV  # $"Q #!6##    :  0 ")r²)Nr{);r…rBrDÚos.pathr4rfr«rSrÄr‹rFÚhttplib2rÚiorr¡r¢Úurllib2rrrÚhttplibrÚurllibr r rRÚurllib.requestÚ urllib.parseÚ http.clientÚlaunchpadlib.errorsr Úlaunchpadlib.launchpadr Ú ImportErrorÚapport.crashdbrrWÚ expanduserr7rr&r8r'r‰rˆr‘rrr‚Úunittestr]Ú unittest.mockr±rÂrÓrÕÚTestCaser²ÚmainrrrrÚs|H         þ  F 7  à