<div dir="ltr">Dear list,<div><br></div><div>I'm currently developing a plugin that adds algorithms that query an API. There are some very clear issues that may arise, such as hitting an API quota limit.</div><div><br></div><div>However, I couldn't find a way to provide clear error message to the user. </div><div><br></div><div>This is what I have in my <span style="color:rgb(220,220,170);background-color:rgb(30,30,30);font-family:Consolas,"Courier New",monospace;font-size:14px;white-space:pre">processAlgorithm(...)</span> method :<br></div><div><br></div><div><div style="color:rgb(212,212,212);font-family:Consolas,"Courier New",monospace;font-size:14px;white-space:pre;background-color:rgb(30,30,30)"><span style="color:rgb(197,134,192)">if</span> limit_reached:</div><div style="color:rgb(212,212,212);font-family:Consolas,"Courier New",monospace;font-size:14px;white-space:pre;background-color:rgb(30,30,30)">    feedback.reportError(<span style="color:rgb(206,145,120)">"API usage limit reached"</span>, <span style="color:rgb(156,220,254)">fatalError</span>=<span style="color:rgb(86,156,214)">True</span>)</div><div style="color:rgb(212,212,212);font-family:Consolas,"Courier New",monospace;font-size:14px;white-space:pre;background-color:rgb(30,30,30)">    <span style="color:rgb(197,134,192)">raise</span> QgsProcessingException(<span style="color:rgb(206,145,120)">"API usage limit warning"</span>)</div></div><div><br></div><div>It works well, but the error is hidden in the middle of a potentially long trace (see below) that is so cryptic for the typical user that he will miss the important message (which is "<span style="color:rgb(255,0,0);white-space:pre-wrap">API usage limit reached"</span>).</div><div><br></div><div>I tried to play a bit around with things like `raise QgsException(...) from None` or other things, but could find a way to provide better output for the user. And since it's from an algorithm, it's not possible to use iface.pushMessage() or any other UI mean to do so...</div><div><br></div><div>Any pointer would be greatly appreciated !</div><div><br></div><div>Cheers,</div><div><br></div><div>Olivier</div><div><br></div><div><br></div><div><br></div><div><br></div><div>Example output log :</div><div><br></div><div><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap">Processing algorithm…</p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><span style="font-weight:600">Algorithm 'Time Map - Simple' starting…</span></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap">Input parameters:</p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><span style="font-family:"Courier New"">{ 'INPUT_SEARCHES' : 'memory?geometry=Point&crs=EPSG:4326&field=full_id:string(0,0)&field=osm_id:string(0,0)&field=osm_type:string(0,0)&field=amenity:string(0,0)&field=name:string(0,0)&field=cuisine:string(0,0)&field=addr:housenumber:string(0,0)&field=addr:postcode:string(0,0)&field=addr:street:string(0,0)&field=diet:gluten_free:string(0,0)&field=diet:vegetarian:string(0,0)&field=phone:string(0,0)&field=wheelchair:string(0,0)&field=addr:city:string(0,0)&field=fhrs:id:string(0,0)&field=source:addr:string(0,0)&field=alt_name:string(0,0)&field=fhrs:authority:string(0,0)&field=fhrs:inspectiondate:string(0,0)&field=fhrs:rating:string(0,0)&field=addr:housename:string(0,0)&field=addr:unit:string(0,0)&field=dontimport:fhrs:addrline1:string(0,0)&field=dontimport:fhrs:addrline2:string(0,0)&field=dontimport:fhrs:businesstype:string(0,0)&field=opening_hours:string(0,0)&field=email:string(0,0)&field=website:string(0,0)&field=contact:phone:string(0,0)&field=wheelchair:description:string(0,0)&field=toilets:wheelchair:string(0,0)&field=toilets:string(0,0)&field=toilets:access:string(0,0)&field=opening_hours:url:string(0,0)&field=takeaway:string(0,0)&field=fhrs:confidence_management:string(0,0)&field=fhrs:hygiene:string(0,0)&field=fhrs:local_authority_id:string(0,0)&field=fhrs:structural:string(0,0)&field=outdoor_seating:string(0,0)&field=source:postcode:string(0,0)&field=wikidata:string(0,0)&field=payment:american_express:string(0,0)&field=old_name:string(0,0)&field=source:addr:postcode:string(0,0)&field=diet:raw:string(0,0)&field=diet:vegan:string(0,0)&field=facebook:string(0,0)&field=warning:string(0,0)&field=currency:XLT:string(0,0)&field=payment:cash:XLT-BXTP:string(0,0)&field=payment:text:XLT-BXTP:string(0,0)&field=postal_code:string(0,0)&field=addr:country:string(0,0)&field=brand:string(0,0)&field=brand:wikidata:string(0,0)&field=brand:wikipedia:string(0,0)&field=contact:website:string(0,0)&field=capacity:string(0,0)&field=operator:string(0,0)&field=smoking:string(0,0)&field=level:string(0,0)&field=postcode:string(0,0)&field=layer:string(0,0)&field=delivery:string(0,0)&field=contact:email:string(0,0)&field=addr:floor:string(0,0)&field=description:floor:string(0,0)&field=old_fhrs:id:string(0,0)&field=old_fhrs:local_authority_id:string(0,0)&field=addr:suburb:string(0,0)&field=wifi:string(0,0)&field=drive_in:string(0,0)&field=microbrewery:string(0,0)&field=branch:string(0,0)&field=tourism:string(0,0)&field=note:name:ko:string(0,0)&field=wikipedia:string(0,0)&field=name:en:string(0,0)&field=url:string(0,0)&field=name:zh:string(0,0)&field=old_cuisine:string(0,0)&field=diet:pescetarian:string(0,0)&field=seats:string(0,0)&field=bar:string(0,0)&field=type:string(0,0)&field=former_name:string(0,0)&field=food:string(0,0)&field=disused:string(0,0)&field=operator:wikidata:string(0,0)&field=disused:name:string(0,0)&field=addr:place:string(0,0)&field=contact:fax:string(0,0)&field=fax:string(0,0)&field=note:name:en:string(0,0)&field=note:name:zh:string(0,0)&field=alcohol:string(0,0)&field=entrance:string(0,0)&field=internet_access:fee:string(0,0)&field=brewery:string(0,0)&field=note:name:string(0,0)&field=instagram:string(0,0)&field=twitter:string(0,0)&field=building:level:string(0,0)&field=internet_access:string(0,0)&field=description:string(0,0)&field=trendy:string(0,0)&field=colour:string(0,0)&field=erected_by:string(0,0)&field=historic:string(0,0)&field=inscription:string(0,0)&field=memorial:string(0,0)&field=openplaques:id:string(0,0)&field=scheme:string(0,0)&field=addr:full:string(0,0)&field=number:string(0,0)&field=contact:twitter:string(0,0)&field=name:es:string(0,0)&field=name:gl:string(0,0)&field=uri:string(0,0)&field=indoor_seating:string(0,0)&field=music:string(0,0)&field=product:string(0,0)&field=contact:facebook:string(0,0)&field=ref:NPLG:UPRN:1:string(0,0)&field=drink:coffee:string(0,0)&field=drink:soft_drink:string(0,0)&field=drink:tea:string(0,0)&field=source:name:string(0,0)&field=wikimedia_commons:string(0,0)&field=access:string(0,0)&field=barrier:string(0,0)&field=building:string(0,0)&field=payment:bitcoin:string(0,0)&field=start_date:string(0,0)&field=shop:units:string(0,0)&field=source:position:string(0,0)&field=survey:date:string(0,0)&field=payment:cash:string(0,0)&field=payment:credit_cards:string(0,0)&field=payment:debit_cards:string(0,0)&field=camera:mount:string(0,0)&field=camera:type:string(0,0)&field=man_made:string(0,0)&field=surveillance:string(0,0)&field=surveillance:type:string(0,0)&field=surveillance:zone:string(0,0)&field=disused:amenity:string(0,0)&field=shop:string(0,0)&field=checkfirst:suggested:name:string(0,0)&field=source:date:string(0,0)&field=addr:interpolation:string(0,0)&field=diet:halal:string(0,0)&field=note_1:string(0,0)&field=designation:string(0,0)&field=addr:flat:string(0,0)&field=addr:flats:string(0,0)&field=organic:string(0,0)&field=memorial:type:string(0,0)&field=max_level:string(0,0)&field=min_level:string(0,0)&field=fhrs:name:string(0,0)&field=diet:string(0,0)&field=construction:string(0,0)&field=old_amenity:string(0,0)&field=happycow:id:string(0,0)&field=drive_through:string(0,0)&field=contact:instagram:string(0,0)&field=payment:mastercard:string(0,0)&field=payment:visa:string(0,0)&field=drink:wine:string(0,0)&field=payment:jcb:string(0,0)&field=contact:google_plus:string(0,0)&field=name:gsw:string(0,0)&field=drink:cider:string(0,0)&field=reservation:string(0,0)&field=name:ru:string(0,0)&field=name:nl:string(0,0)&field=name:lt:string(0,0)&field=name:ja:string(0,0)&field=name:ar:string(0,0)&field=name:it:string(0,0)&field=website:en:string(0,0)&field=name:pt:string(0,0)&field=amenity_1:string(0,0)&field=self_service:string(0,0)&field=highway:string(0,0)&field=lamp_mount:string(0,0)&field=name:pl:string(0,0)&field=stars:string(0,0)&field=drink:beer:string(0,0)&field=drink:lemonade:string(0,0)&field=drink:water:string(0,0)&field=breakfast:string(0,0)&field=drink:natural_wine:string(0,0)&field=name:ro:string(0,0)&field=drink:cola:string(0,0)&field=disused:shop:string(0,0)&field=not:addr:postcode:string(0,0)&field=source:addr:housenumber:string(0,0)&field=camera:direction:string(0,0)&field=real_ale:string(0,0)&field=not:addr:street:string(0,0)&field=baby_change:string(0,0)&field=name:fr:string(0,0)&field=automatic_door:string(0,0)&field=door:string(0,0)&field=serves_cars:bool(0,0)&field=is_drive_through:bool(0,0)&uid={98191443-a039-467a-a0c6-4dbfb08707cf}', 'INPUT_SEARCH_TYPE' : 0, 'INPUT_TIME' : '2019-05-29T12:00:00', 'INPUT_TRAVEL_TIME' : 15, 'INPUT_TRNSPT_TYPE' : 0, 'OUTPUT' : 'memory:', 'OUTPUT_RESULT_TYPE' : 0 }</span></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><br></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><span style="color:rgb(0,0,255)">Starting TimeMapSimpleAlgorithm...</span></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><span style="color:rgb(0,0,255)">Calling subcommand with following parameters...</span></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><span style="color:rgb(0,0,255)">{'INPUT_DEPARTURE_SEARCHES': <qgis._core.QgsVectorLayer object at 0x00000249EB1ADCA8>, 'INPUT_DEPARTURE_TRNSPT_TYPE': "'cycling'", 'INPUT_DEPARTURE_TIME': "'2019-05-29T12:00:00'", 'OUTPUT_RESULT_TYPE': 0, 'OUTPUT': 'memory:results', 'INPUT_DEPARTURE_TRAVEL_TIME': '900', 'INPUT_DEPARTURE_TRNSPT_WALKING_TIME': '900'}</span></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><span style="color:rgb(0,0,255)">Starting TimeMapAlgorithm...</span></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><span style="color:rgb(0,0,255)">Checking API limit warnings...</span></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><span style="color:rgb(255,0,0)">API usage limit reached !</span></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><span style="color:rgb(255,0,0)">Traceback (most recent call last):<br>File "C:/Users/Olivier/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\travel_time_platform_plugin\algorithms\advanced.py", line 383, in processAlgorithm<br>slices = self.processAlgorithmGetSlices(parameters, context, feedback)<br>File "C:/Users/Olivier/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\travel_time_platform_plugin\algorithms\advanced.py", line 234, in processAlgorithmGetSlices<br>self.processAlgorithmEnforceLimit(len(slices), parameters, context, feedback)<br>File "C:/Users/Olivier/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\travel_time_platform_plugin\algorithms\base.py", line 245, in processAlgorithmEnforceLimit<br>raise QgsProcessingException("API usage limit reached ") from None<br>_core.QgsProcessingException: API usage limit reached<br></span></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><span style="color:rgb(255,0,0)">There were errors executing the algorithm.</span></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><span style="color:rgb(255,0,0)">Traceback (most recent call last):<br>File "C:/Users/Olivier/AppData/Roaming/QGIS/QGIS3\profiles\default/python/plugins\travel_time_platform_plugin\algorithms\simple.py", line 111, in processAlgorithm<br>sub_id, sub_parameters, context=context, feedback=feedback<br>File "C:/OSGEO4~1/apps/qgis-ltr/./python/plugins\processing\tools\general.py", line 105, in run<br>return Processing.runAlgorithm(algOrName, parameters, onFinish, feedback, context)<br>File "C:/OSGEO4~1/apps/qgis-ltr/./python/plugins\processing\core\Processing.py", line 183, in runAlgorithm<br>raise QgsProcessingException(msg)<br>_core.QgsProcessingException: There were errors executing the algorithm.<br></span></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><span style="color:rgb(255,0,0)">Execution failed after 0.16 seconds</span></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap"><br></p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap">Loading resulting layers</p><p style="margin:0px;white-space:pre-wrap">
</p><p style="margin:0px;white-space:pre-wrap">Algorithm 'Time Map - Simple' finished</p></div><div><div style="color:rgb(212,212,212);background-color:rgb(30,30,30);font-family:Consolas,"Courier New",monospace;font-size:14px;line-height:19px;white-space:pre"><div><span style="color:rgb(86,156,214)"></span></div></div></div></div>