!f<dZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZ ddlmZddlmZmZddlmZddlmZddlZddlZddlZddlm Z!dZ"ejFjId Z%d Z&d Z'Gd d ejPjRZ)da*GddejVjXZ-Gddej\j^Z0ddZ1y#e$rdZYwxYw)z,Crash database implementation for Launchpad.N)FailedToDecompressContent) HTTPError RestfulError) Launchpad)lookup_web_root)impl productionz%~/.cache/apport/launchpad.credentialsc#K|D]P} |jj}|j}|jds|jdsM|Ry#ttf$r"tj j dYwxYww)Nz"Broken attachment on bug, ignoring.txt.gz) dataopenrrapportloggingerrorfilenameendswith) attachments attachmentfnames ?/usr/lib/python3/dist-packages/apport/crashdb_impl/launchpad.pyfilter_filenamer1s!  $$&Azz == DMM%$8G45  NN !E F  s-B A.B B .B B  B  B c&td|DS)Nc3K|]6}t|jjdj8yw)/N)int self_linksplitpop).0is r zid_set..?s-@Qs1;;$$S)--/0@s<>)set)taskss rid_setr&=s @%@ @@c,eZdZdZdZedZdZedZd$dZ de fd Z d Z d e jjd ede fd ZdZ d%dZd&dZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!d'dZ"dZ#d Z$d!Z%d"Z&e'd#Z(y)( CrashDatabasez5Launchpad implementation of crash database interface.chtjdrtjd|d<|sD|jd}|r+djt|j dddf}nt}t jjj||||jd|_ |jr d|vsJd d|vsJd d |vrd |d d |_ nd tjd |_ ||_||_|jsJd|_d|_tjd|jd|_|j$sLt'j(d|_t+j,t.j0|j$dyy)aOInitialize 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 overridden or set by $APPORT_LAUNCHPAD_INSTANCE environment. For example: "qastaging" or "staging". - 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_INSTANCElaunchpad_instance.z://distroprojectz/Must not set both "project" and "distro" optionz0Need to have either "project" or "distro" option architecturezneed--retraceNAPPORT_LAUNCHPAD_CACHE cache_dirzlaunchpadlib.cache.)prefixT) ignore_errors)osgetenvgetjoindefault_credentials_pathrrcrashdbr)__init__r0arch_tag packagingget_system_architectureoptionsauth_CrashDatabase__launchpad_CrashDatabase__lp_distro_CrashDatabase__lpcachetempfilemkdtempatexitregistershutilrmtree)selfrCrB lp_instances rr>zCrashDatabase.__init__EsD 990 1,.II6Q,RG( )!++&:;Kxx-{/@/@/J2/NO0$$--dD'Bkk(+ ;;( A@ A(W$ BA B$ W $#GN$;#> Nr'c |jr |jStItjj dtj ddtj d|jjdr|jjd}nt}tjj|j}|r4tjj|stj| tj d||j"dg|jd |_|jS#t$t&t(f$ri}t*j,j/d t1|d t3||jtj d Yd}~|jSd}~wwxYw)zReturn Launchpad instance.NzERROR: The launchpadlib Python rzK module is not installed. Please install the python3-launchpadlib package! r.r,zapport-collect WRITE_PRIVATEz1.0)launchpadlib_dirallow_access_levelscredentials_fileversionzZconnecting to Launchpad failed: %s You can reset the credentials by removing the file "%s"contentc)rDrsysstderrwriterTexitrBr:DEFAULT_LAUNCHPAD_INSTANCEr8pathdirnamerCisdirmakedirs login_withrFrOSError ValueErrorrrrgetattrstr)rMr,auth_dirrs r launchpadzCrashDatabase.launchpadsd   ## #   JJ  1#++a.1ABFG  HHQK <<  0 1!%!1!12F!G !; 77??499- BGGMM(3 KK ! (33 "!%%4$5!%  D "gz2  NN Jy#e*5   HHRLL s5EGAF>>Gc#K|jsy|D]j}|jj|jk(s=tjd|jd|jjsg|lyw)Nz^.+\(z.*\)$)r0bug_target_namelowerrematch)rMr%ts r_get_distro_taskszCrashDatabase._get_distro_taskssm{{  A  &&(DKK7288 U+Q->->-D-D-F<  s A6B9BcR|j|jr4|jj|j|_|jSd|jvr7|jj |jd|_|jSt d|jS)z,Return Launchpad distribution (e.g. ubuntu).r1z:distro or project needs to be specified in crashdb options)rEr0rf distributionsrBprojects SystemError)rMs r lp_distrozCrashDatabase.lp_distros    #{{#'>>#?#? #L dll*#'>>#:#:4<< ;R#S  "Pr'Nc|j|sJ|j|}t|||j}|j |sJ|S)aUpload 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_hostnameclose)rMreportprogress_callbackuser_message_callback blob_filetickets ruploadzCrashDatabase.uploadsT||F###..v6 Y(9DDUDUDWX v r'returnc|jjdt}tjj t |}|jS)z/Return the hostname for the Launchpad instance.r,)rBr:r[urllibparseurlparsernetloc)rMr,urls rrxzCrashDatabase.get_hostnamesC!\\-- "< ll##O4F$GHzzr'c i}|jd|j}|r||d<|j}d|vr|d}n|jjd}|r+d|d|d|dtj j |Sd |vr;d|d|jd |d d|dtj j | Sd|d|jd|dtj j |S) a8Return 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. Titlez field.title SnapSourcer1 https://bugs.rz /+filebug/? SourcePackagez /+source/)r:standard_titlerxrBrr urlencoder0)rMrzhandleargstitlertr1s rget_comment_urlzCrashDatabase.get_comment_urls& 7F$9$9$;< "'D $$& 6 !\*Gll&&y1G z7):fXFLL**4013  f $z4;;-8?+,JvhFLL**4013 H:Qt{{m:fX &&t,- / r'rzcrash_idc.d|jd|S)zReturn 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. rz/bugs/)rx)rMrzrs r get_id_urlzCrashDatabase.get_id_urls!t00236(DDr'cZtjj}|jj|}t j d|jt j}|s@t j d|jt jt jz}|sJd|jdjdjddjdd }d |vrZd |vrA|jd d\}}|jd d d z|jd dd z}n|jd dd }|jtj |d |vr |j"j%|d <d|vrqd|j(vrd|d<n]d|j(vrd|d<nId|j(vrd|d<n5d|j(vrd|d<n!t+dt-|j(|j/|j(d|vr|d|d<|j0|d<t3|j4D]}t6j8j;|j<\} } d|| <| dk(r,|jC|| < || jEd|| <f| dk(r4 tIjJ|5} | jC|| <dddtQd |j<|S#t&$r|j"|d <YwxYw#t>t@t*f$rYwxYw#tF$rYwxYw#1swYmxYw#tL$r=} dt-| vr|jOd |jC|| <Yd} ~ Od} ~ wwxYw)!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.UTF-8s  s  s sUname:rDate ProblemTypez apport-bugBug apport-crashCrashzapport-kernelcrash KernelCrashzapport-packagePackagez(cannot determine ProblemType from tags: r OriginalTitler r )fileobjNz Not a gzipzUnknown attachment type: ))rrzReportrfbugsrjsearch descriptionSMgroupencodereplacerloadioBytesIO date_createdctimeAttributeErrortagsrbrdadd_tagsrrrr8r\splitextrAssertionError TypeErrorreaddecodeUnicodeDecodeErrorgzipGzipFileraseekNotImplementedError) rMrrzbmrpart1part2rkeyextgzrs rdownloadzCrashDatabase.downloads~%%' NN   ) II*AMM244 @ 11=="$$+NALLLq GGAJ VG_ W[$ ' WWe $  k !K'"-!2!29a!@MM'51 kk'1-a01*//;A>  BJJ{+,    0!"!5!5!7v  &qvv%(-}%166)(/}%%/(5}%!QVV+(1}% >s166{mL  f &,WoF? #''w)!--8 Jww'' (;(;D$$& &&>D((* **((*l: ::HHQK+,V#//v?EEGGA nn))(3##4#077KD%),(9$&HCOKKM""%))NN4NA! !!.4" $ 1 1 3!%)))6!..0" " W3 3 3 s G II cztjjj|||||jj |}d|vr|j D]v}|jjjds)|jj|d|_|j|jj |}n|jr|jD]#}|jdk(s |j!% |j%|j }t'|}|j(dk(rd|_|j|j-}|rt/j0d|j}|ri|j3d|k7rU|j3d |z|j3d z|_ |j|jj |}|j5||y #t"$rY/wxYw#t*$rYwxYw#t"$rYVwxYw) zUpdate the given report ID for retracing results. This updates Stacktrace, ThreadStacktrace, StacktraceTop, and StacktraceSource. You can also supply an additional comment. r #distributionr CoreDump.gz UndecidedMediumz,^(.*crashed with SIG.* in )([^( ]+)(\(\).*$)r.N)rr=r) update_tracesrfr bug_taskstargetresource_type_linkrrrgetSourcePackagerhas_useful_stacktracerr removeFromBugrrmr importance StopIterationstacktrace_top_functionrjrkr_subscribe_triaging_team) rMrrzrrtaskafnrs rrzCrashDatabase.update_tracess $$22467Snn!!(+ f $  ;;11::?K"&.."A"A#O4#B#DKLLN..--h7C   ' ' )__ 77m+)   --cmm<Dz??k1&.DOLLN //1BHHLciiXr) ! R!''!* ' from the given report ID and return it.z"DistroRelease: ([-a-zA-Z0-9.+/ ]+)r.z)URL does not contain DistroRelease: field)rfrrjrrrrb)rMrrrs rget_distro_releasez CrashDatabase.get_distro_release sJnn!!(+ II:COO L 771: DEEr'cRtjd|jd}|jj|}g}|j D]Y}|j |jj}|s+|jdvr:|j|jd[|S)z5Return list of affected source packages for given ID.rz2/(?:(?P[^/]+)/)?\+source/(?P[^/]+)$>Invalid Won't Fix Fix Releasedsource) rjcompiler0rfrrrrrstatusrr)rMr bug_target_rerresultrrks rget_affected_packagesz#CrashDatabase.get_affected_packagess  T U nn!!(+MM 1D!(()>)>?E{{FF MM%++h/ 0  1 r'c|jj|}|jj|jjjk(S)z3Check whether the user is the reporter of given ID.)rfrownerrme)rMrrs r is_reporterzCrashDatabase.is_reporter$s9nn!!(+yy~~!2!2!7!777r'cJ|jj|}|jry|jj|jj jk(ry|jj j }|jjD] }|d|k(s yy)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) rfr duplicate_ofrrrr subscriptionsentries)rMrrrsubs r can_updatezCrashDatabase.can_update)snn!!(+    99>>T^^..33 3^^   ( ($$,, C=!R' r'c |jj|jd}t|S#t$rH}t j jdt|tjdYd}~yd}~wwxYw)z}Return an ID set of all crashes which have not been retraced yet and which happened on the current host architecture. 2011-08-01r created_since"connecting to Launchpad failed: %srVN) rr searchTasksr?r&rrrrrdrWrZrMrrs rget_unretracedzCrashDatabase.get_unretraced@sk >>--]],.D$<   NN !Es5z R HHRLL s14 B>BBc |jjdd}t|S#t$rH}tj j dt|tjdYd}~yd}~wwxYw)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-checkrrrrVN) rrrr&rrrrrdrWrZrs rget_dup_uncheckedzCrashDatabase.get_dup_uncheckedLsg >>--+<.D$<   NN !Es5z R HHRLL s'* A;>A66A;cP|jjd}t|S)aXReturn 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 OSError). r)r)rrrr&)rMrs r get_unfixedzCrashDatabase.get_unfixed]s%~~))~)>d|r'c|jjjd||jj}|djS)zReturn 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)rr main_archivegetPublishedSourcescurrent_seriessource_package_version)rMpackagesourcess r_get_source_versionz!CrashDatabase._get_source_versionisI ..--AA..77B  qz000r'c: jj|}|jryt |j }j rdj jd t t fd|}|st tfd|}|ryt|dkDr,tjjdj |y|r=|j} j|jj!d St t fd |}|rt t fd |}|syyt td |}|ryt td |ryy#t$rYywxYw#t"$rYywxYw)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 OSError). invalid()c^|jdk(xr|jjvSNrr bug_target_display_namerirdistro_identifiers rz1CrashDatabase.get_fixed_version..s0!>"R)T-I-I-O-O-QQr'c|jdk(xr5|jjjjk(Sr5)r rhrir0)rrMs rr:z1CrashDatabase.get_fixed_version..s=T[[N%B&P 00668DKKExpiredrrr6r8s rr:z1CrashDatabase.get_fixed_version..s1T[[4W%W&V-1M1M1S1S1UUr'c\|jdvxr|jjvS)N)rrr=r6r8s rr:z1CrashDatabase.get_fixed_version..s8#F*G*D 1#;;AAC!Dr'c |jdk(Sr5r rs rr:z1CrashDatabase.get_fixed_version..sDKK>$Ar'c |jdk(S)Nrr@rAs rr:z1CrashDatabase.get_fixed_version..s y(@r'N)rfrKeyErrorrlistrr0rifilterlenrrwarningr r/r7r IndexError) rMrrr% fixed_tasks fixed_distror invalid_tasksnon_invalid_tasksr9s ` @rget_fixed_versionzCrashDatabase.get_fixed_versionws$ ##H-A >>Q[[! ;;"#DKK$5$5$7#8 : RK#P   ;!#&&BKK  "(%3344:: ProcMaps.txt Registers.txtProcStatus.txtStacktrace.txtDisassembly.txtThreadStacktrace.txtrzThank 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 #aE, 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 duplicaterF escalation_tag escalated_tagz invalid escalation_subscriptionpersonzapport-request-retraceapport-failed-retracez'Updated stack trace from duplicate bug ) StacktraceThreadStacktracer DependenciesProcMaps ProcCmdline)rzbugpattern-needed)zActive DevelopmentzCurrent Stable Release SupportedzPre-release Freeze)"rfrrdrrOrrrGrrrrrprivaterrF duplicatesrBr:rpeople subscriberrremoverbrrseriesr rrr$ difference_dirty_attributes)rMrzr master_idrmasterr master_tagspr tags_to_copyri dupe_tags missing_tagstags rclose_duplicatezCrashDatabase.close_duplicatesnn!!(+ I% K!#h-0IJ K%^^((3F"",,"II 99(NN**4 !  __ 77)  ..%%h/C NNK  2  ..%%h/C{{# ###) !++K6$$%+$ 4 %56kI ((+F&'#. %561#FKNN$.= ((+F&'--dll;T.UVA$$A$.++-(K7*k9 =hZH   ,,Y7KKNHH45HH56  NN$ 00L..// 1==) ##FKK0 1CHH I ++K$// C?c|jj|}d|vr|jD]w}|jjj ds)|j j|d|_ |j|jj|}nd|jvr|jdd}|jd||_ |jd|vrQ|jD]B}d|jjvs|jdk(s,d|_ |jD|j||y#t$rYwxYw) z/Mark crash id as checked for being a duplicate.rrrr!N Tracebackrr)rfrrrrrrrrrrrrhrr)rMrrzrrrs r_mark_dup_checkedzCrashDatabase._mark_dup_checkeds?nn!!(+ f $ ;;11::?K"&.."A"A#O4#B#DK "nn11(;   "SXX - A HH+ ,CH KKMf$MM+D&$++*H*HH??k9.6DO LLN + %%c62#%s8)E EEctjjj||}|s|S||d< tj j |d5}|j}|jds dddy|D]9}|jdrd|vsd|vr dddyn|jr9nddd|S#1swY|SxYw#t$r|cYSwxYw) aCheck 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:NTstags:sapport-failed-retracesapport-request-retrace) rr=r)knownrrequesturlopenreadline startswithstripra)rMrzrrlines rrzCrashDatabase.knowns*nn**00v>J!$} ''3%v7 1zz|w/    Dx04<8D@#'   ::<  2 3 2  J sM"C#C :CC "C+C >C C CCC C&%C&cd|vr|djddk7ry|jjdd}|jjd|}|j t |jjdjd|jDcgc]!}t |jd d d #c}vr|j| yycc}w)z-Subscribe the right triaging team to the bug. DistroReleaserUbuntuN triaging_teamzubuntu-crashes-universe~rrr.)maxsplitr/r[) rrBr:rf _root_urirrdrrrg)rMrrzteamr\rs rrz&CrashDatabase._subscribe_triaging_teams f $)@)F)F)H)Kx)W ||1JKNN,,-Qtf5~~c$..":":;R@FFsK;>;L;LP 47CHNN3N +B /P   MMM ( P s!&Ccdd|dji}|jd}|r|dk(r|jd}|r|dxxd|z cc<d|vr"|dxxd|j|dz cc<d|vro|rRd |vsd |vsd |vrFd |d <|jd|jjdd|d<|dxxd|dz cc<nd|vrd |d <d|d<|dxxdz cc<d|vrd|dvr |dxxdz cc<d|vr|d|d<gd}t j }|j ||gd||j|jd|S)zGenerate a multipart/MIME temporary file for uploading. You have to close the returned file object after you are done with it. rzapport-rPackageArchitectureall Architecture rVmCoreCoreDumpLaunchpadPrivateyesPrivateLaunchpadSubscribeinitial_subscriberr Subscribersz need-r3r}z need-duplicate-checkDuplicateSignaturer!CheckboxSubmissionzHWDB-Submission) rrr Regression ReproducibleTestedUpstreamProcVersionSignatureUnameNonfreeKernelModules)rrr) extra_headersrpriority_fieldsr) rir:rrBrGrrrr)rMrzhdrrorderrs rrvz#CrashDatabase._generate_upload_blob*s  !6! ?@A JJ, -AJ >*A KQqc7 "K V  KQt55fVnEFG GK f $F"'%/!&I%+ZZ(LL$$%98D&M"F s(33 &!&I%-M"F 66 6 ).DCPVK.W K2 2K 6 )%+,@%AC! "  %%' H!   !  r'cd}|jjddD],}|dvst|dkDr|dvr|t|z }(|dz }.|S) zJReplace characters from tags which are not palatable to Launchpad.rASCIIignore)errorss%abcdefghijklmnopqrstuvwxyz0123456789 rs+-.r-)rirrFchr)rreschs rrzCrashDatabase._filter_tag_namesnse**,%%gh%? B==C1 vs2ws    r')NN)FNN)rN))__name__ __module__ __qualname____doc__r>propertyrfrmrrrrdrxrrrzrrrrrrrr rrrr"r$r/rMrrtrvrxr{r~rrrv staticmethodrr'rr)r)Bs?FOP( ( T    $c$ LE!5!5EEEaP!Vp13fF$8 . "  1dL]~$ 63B7r)"BH  r'r)ceZdZdZdZy)HTTPSProgressConnectionzWImplement a HTTPSConnection with an optional callback function for upload progress.cts+tjjj ||yd}t |}d}||krt||t j }tjjj |||||z||z }t j }|dkDr||z dkr|dz}n ||z dkDr|dz}||kryy)Nrig?r.r)_https_upload_callbackhttpclientHTTPSConnectionsendrFtime)rMr senttotal chunksizet1t2s rrzHTTPSProgressConnection.sends% KK ' ' , ,T4 8 D  Ul "4 /B KK ' ' , ,T4y@P3R S I DB47S=!OI"Wq[!OIUlr'N)rrrrrrr'rrrs $r'rceZdZdZdZy)HTTPSProgressHandlerzTImplement a HTTPSHandler with an optional callback function for upload progress.c.|jt|Sr)do_openr)rMreqs r https_openzHTTPSProgressHandler.https_opens||3S99r'N)rrrrrrr'rrrs :r'rcd}d|d}|atjjj }tjj j d}|jdd|j|tjjjdd}|jdd |j|jjd |j|tj}tj j#|d } | j%|t&j(j+||j-} | jd d|j/t&j(j1t2} | j5| } | j7j9d}|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', 'qastaging.launchpad.net', or 'staging.launchpad.net' to use another instance for testing. Nzhttps://z /+storeblob1zContent-Dispositionzform-data; name="FORM_SUBMIT" applicationz octet-streamz*form-data; name="field.blob"; filename="x"asciiF) mangle_from_z Content-Typezmultipart/form-data; boundary=zX-Launchpad-Blob-Token)rrr multipart MIMEMultipartrMIMEText add_headerattachbaseMIMEBase set_payloadrrrr generatorBytesGeneratorflattenrrRequestgetvalue get_boundary build_openerrrinfor:) blobr{rtr~rr submit form_blob data_flatgenropenerr s rrwrwsF XJk *C/ ::   - - /D ZZ__ % %c *F +-LMKK ((GI K$))+,,W56KK  I // ( ( ( GCKK .. i&8&8&: ;CNN89J9J9L8MN^^ ( ()= >F [[ F [[]  7 8F M6 Mr')Nz launchpad.net)2rrIrr http.clientrros.pathr8rjrKrWrGr urllib.parserurllib.requesthttplib2rlaunchpadlib.errorsrrlaunchpadlib.launchpadrlaunchpadlib.urisr ImportErrorapport.crashdbrapport.logging apport.reportapport.packaging_implrr@r[r\ expanduserr<rr&r=r)rrrrr HTTPSHandlerrrwrr'rrs2     2;01 3)77--.UV A yFNN00y@"$dkk99$::6>>66:1U$IsC++C54C5