Love to use pylance, but unable to fix this issue in dictionary get, pylance prompt message as shown in the image
def validate_amount():
try:
json_data = request.json
def isfloat(num: str) -> bool:
try:
float(num)
return True
except ValueError:
return False
amount_val = json_data.get('amount','0.0')
amount_in_words = json_data.get('amount2words','')
if isfloat(amount_val):
split_amt = amount_val.split('.')
response = split_amt
except Exception as e:
response = f'An Error Occurred - {e}'
Below is the image for reference
I'm trying to raise an exception in FastAPI when an object with a specific key already exists (e.g. RethinkDb return "Duplicated key" error). Probably something wrong with my method logic, but can't get what exactly.
#router.post("/brands", response_model=Brand, status_code=status.HTTP_201_CREATED)
def add_brand(brand: Brand):
with r.connect('localhost', 28015, 'expressparts').repl() as conn:
try:
result = r.table("brands").insert({
"id": brand.id,
"name": brand.name}).run(conn)
if result['errors'] > 0:
error = result['first_error'].split(":")[0]
raise HTTPException(
status_code=400, detail=f"Error raised: {error}")
else:
return brand
except Exception as err:
print(err)
You have a try-catch and it captures all the errors that occured. You are just capturing your own Exception which is isn't actually been raised yet.
#router.post("/brands", response_model=Brand, status_code=status.HTTP_201_CREATED)
def add_brand(brand: Brand):
with r.connect('localhost', 28015, 'expressparts').repl() as conn:
result = r.table("brands").insert({
"id": brand.id,
"name": brand.name}).run(conn)
if result['errors'] > 0:
error = result['first_error'].split(":")[0]
raise HTTPException(
status_code=400, detail=f"Error raised: {error}")
else:
return brand
This should be working fine.
I have inherited this chunk of code:
def _api_call(self, url, query=None, raw_query='', top=None, select=None, order_by=None, fetch_all=True,
full_response=False, timeout=10, retries=3, debugging=False):
if fetch_all and full_response:
# these parameters are not compatible
raise APIQueryException(message='fetch_all and full_response cannot be used together')
query_string = self._encode_query(query, top, select, order_by)
if query_string or raw_query:
query_string = '?' + query_string + raw_query
# get API signature headers for the new request from the api_auth singleton
headers = api_auth.generate_headers(path=url, method='GET')
service_end_point = 'https://%(portal)s.company.com%(url)s%(query_string)s' % {
'portal': self._portal,
'url': url,
'query_string': query_string,
}
retries_left = retries + 1 or 1
stop = False
kwargs = {'headers': headers, 'timeout': timeout, 'fetch_all': fetch_all}
accumulated_results = []
while not stop:
service_end_point, _tmp_res, stop = self._single_api_call(service_end_point, retries_left, stop, **kwargs)
accumulated_results.extend(_tmp_res)
return accumulated_results
def _single_api_call(self, service_end_point, retries_left, stop, debugging=True,**kwargs):
_res = []
headers = kwargs.pop('headers')
timeout = kwargs.pop('timeout')
fetch_all = kwargs.pop('fetch_all')
try:
while True:
if debugging:
print('Company Service API:', service_end_point)
result = requests.get(url=service_end_point, headers=headers, timeout=timeout)
break
except RequestException as e:
if retries_left > 0:
if debugging:
print('Company Service API EXCEPTION, retrying:', str(e))
retries_left -= 1
else:
raise
except requests.Timeout as e:
raise APITimeoutException(e, message='API request timeout')
except requests.ConnectionError as e:
raise APIRequestException(e, message='API request DNS error or connection refused')
except requests.TooManyRedirects as e:
raise APIRequestException(e, message='API request had too many redirects')
except requests.HTTPError as e:
raise APIRequestException(e, message='API request returned HTTP error status code')
if result.status_code == 400:
# Company often reports "Bad Request" if the query
# parameters are not acceptable
raise APIQueryException(message='API request failed, Company rejected query terms')
try:
parsed_result = json.loads(result.content)
except ValueError as e:
# an unknown failure mode
raise APIRequestException(
message='API request failed; no JSON returned; server said {}'.format(result.content))
if 'value' in parsed_result:
_res.extend(parsed_result['value'])
else:
pass
if '#odata.nextLink' in parsed_result and fetch_all:
service_end_point = parsed_result['#odata.nextLink']
else:
# no more pages
stop = True
return service_end_point, _res, stop
this works fine
call_1 = api_obj._api_call(url, *args, **kwargs)
len(call_1)
3492
however I'm trying to refactor it in order to use a generator, but I'm messing something up.
I made the following changes to the while not stop section of the _api_call method:
while not stop:
try:
service_end_point, _tmp_res, stop = self._single_api_call(service_end_point, retries_left, stop, **kwargs)
accumulated_results.extend(_tmp_res)
if stop:
raise StopIteration
else:
yield _tmp_res
except StopIteration:
return accumulated_results
I see that each single call is computed, but the result is:
call_2 = api_obj._api_call(url, *args, **kwargs)
len(call_2)
3
each of the three item is a list with 1000 items, so I have a total of 3000 items in separate list, and not 3492 as in the original implementation.
How can I change/rewrite this in order to achieve that?
You're trying to do it both ways at once, both yielding and returning. That is legal, but it doesn't mean what you probably want it to mean.
Also, you don't need to raise a StopIteration just to handle it and turn it into a return which the generator protocol is just going to turn back into a StopIteration. Just return and knock out two of those steps (and two extra chances to get something wrong). Or, in this case, we can just fall off the end of the while not stop: loop, just like the original code, and leave off the return because we then fall off the end of the function.
Meanwhile, your old code was adding each _tmp_res onto the list with extend, not append, which has the effect of "flattening" the list—if _tmp_res is a list of 1000 items, extend adds 1000 items onto the end of the list. But yield _tmp_res will just yield that 1000-item sub-list. You probably want yield from here:
while not stop:
service_end_point, _tmp_res, stop = self._single_api_call(service_end_point, retries_left, stop, **kwargs)
yield from _tmp_res
If you don't understand what yield from means, it's roughly equivalent (in this case) to:
for element in _tmp_res:
yield element
In general, yield from is much more powerful, but we don't need any of that power here. It will still be more efficient (although probably not enough to make a difference), and of course it's shorter and simpler, and it makes more sense once you wrap your head around the idea. But if your code needs to work in Python 2.7, you don't have yield from, so you'll have to use the loop over yield instead.
I am giving a wrong input and I want an exception to be raised. Somehow this is not happening. This is my unit test code:
def test_invalid_bag_json_conversion_1(self):
file_name = "../test/test_files/wrong_bag.bag"
ru = RosbagUploader(file_name, self.json_output, "", "", "", "")
status = ru.start()
self.assertRaises(Exception, RosbagUploader, file_name, self.json_output, "", "", "", "")
self.assertEquals(ReturnCodes.FAIL, status)
and my code that I am testing:
class RosbagUploader(object):
"""
#brief Uploads deserialized input Rosbag file to ElasticSearch or
stores it locally
"""
def __init__(self, _rosbag_filepath, _json_filename, _es_addr, _es_index,
_es_type, _buffer_size):
self.overall_status = ReturnCodes.SUCCESS
self._rosbag_filepath = _rosbag_filepath
self._json_filename = _json_filename
self._buffer_size = _buffer_size if _buffer_size > 0 else 5000
self._es_type = _es_type
self._es_addr = _es_addr
self._es_index = _es_index
self._es_buff = []
try:
self._rosbag = rosbag.Bag(_rosbag_filepath, "r")
if self._es_addr:
self._es = Elasticsearch() if _es_addr == "" else \
Elasticsearch([_es_addr])
self._total_num_record = self._rosbag.get_message_count()
except:
print("[ERROR] {}".format(sys.exc_info()))
self.overall_status = ReturnCodes.FAIL
It shows the output that the exception is raised as below:
[ERROR] (<class 'rosbag.bag.ROSBagException'>, ROSBagException(), <traceback object at 0x7fdcb463e8c0>)
EException AttributeError: "'RosbagUploader' object has no attribute '_rosbag'" in <bound method RosbagUploader.__del__ of <rosbag_deserializer_core.RosbagUploader object at 0x7fdcb4899ad0>> ignored
Which is what it should do. But why doesnt it raise the exception?
You are essentially ignoring the exception since you are not re-raising after the print statement:
try:
[...]
except:
print("[ERROR] {}".format(sys.exc_info()))
self.overall_status = ReturnCodes.FAIL
You need to re-raise for callers to receive the exception:
try:
[...]
except:
print("[ERROR] {}".format(sys.exc_info()))
self.overall_status = ReturnCodes.FAIL
raise
Do you have a __del__ destruction method? Seems to be failing there.
in my view I am executing this piece of code:
try:
activeterm = LeaseTerm.objects.get(lease=lease, is_active = True)
except LeaseTenant.DoesNotExist:
activeterm = None
And I expected there will be no value in LeaseTerm I will get exception but I am getting an error:
LeaseTerm matching query does not exist.
But I expected that I have handled the exception and flow should continue.
What is my miss understanding?
Please retry with:
try:
activeterm = LeaseTerm.objects.get(lease=lease, is_active = True)
except LeaseTerm.DoesNotExist: # LeaseTerm
activeterm = None