Handling errors with Genie - genie

I am trying to refactor a python class into Genie, but I am stuck with how to handle errors. Some pointers would be greatly appreciated.
If I understood properly, the way of handling errors with Genie is using Try...except blocks, but how to translate the following type of error handling into this paradigm:
# Enable dictionary/list-style access to options and arguments.
def __getitem__(self, key):
if isinstance(key, int):
if key < len(self.arguments):
return self.arguments[key]
else:
raise ArgParserError(
"positional argument index [%s] is out of bounds" % key
)
else:
option = self._get_opt(key)
return option.value
The code I am at right now looks like (in Genie):
def getitem (key:int):string
if key.is_int()
if key < len(_arguments)
return _arguments[key]
else
raise ArgParserError(
"positional argument index [%s] is out of bounds", key
)
else
var option = _get_opt(key)
return option.value
This is a dummy code, I am only modelling the problem and I am aware that it will not compile as is. I am only looking for a pointer on how to transate the '''raise''' command from python.

You need to define the error type as an exception and then identify that your getitem function raises such an error:
exception ArgParserError
OUT_OF_BOUNDS
def getitem( key:int ):string raises ArgParserError
if key < len(_arguments)
return _arguments[key]
else
raise new ArgParserError.OUT_OF_BOUNDS(
"positional argument index [%s] is out of bounds", key
)
Genie is statically typed so the if key.is_int() is unnecessary. The Vala compiler will check at compile time that all calls to the getitem function pass an integer as the argument.
An alternative approach is to use an out parameter for the result value and use the function's return value to signal if the result is valid:
def getitem( key:uint, out value:string ):bool
result:bool = false
value = ""
if key < _arguments.length
value = _arguments[ key ]
result = true
else
info( "positional argument index [%s] is out of bounds", key )
return result
By making the key an unsigned integer, uint, a negative index can't be passed. The call to info() will log some details of the out of bounds index should you need it for debugging later.

Related

Return Statement is not working properly in recursive function of Python

Hi i have a python code for DFS algorithm. I need to return when i reached to "GoalNode". But my function don't return, it works until the reach all the nodes. I guess problem is i don't know how recursive function works. My function must stop in bolded code lines. How can i solve this problem
def DFS(visited, StartNode, GoalNode):
index =(list(MainDictionary).index(StartNode))
visited[index] = True
print(StartNode)
**# it has to return here out put must be only F - C but function reaches all the nodes
if StartNode == GoalNode:
return**
#This line is for accessing my dictionary data type
values = ReturnKeyVal(StartNode)
for key in values:
index =(list(values).index(key))
if visited[index] == False and values[key] != 0:
DFS(visited, key, GoalNode)
def ReturnKeyVal(Target):
for keys, values in MainDictionary.items():
if keys == Target:
return values
visited = [False] * (len(MainDictionary))
DFS(visited,"F", "C")
While I have other questions about your code (Because I can't figure out what ReturnKeyVal is supposed to do, if MainDictionary is a normal python dictionary it would just return the value corresponding to the key but if you just wanted to do that why would you write a function for it? Getting the corresponding value is what keys are for. Which is why I asked for the MainDictionary.) the problem is pretty simple: You don't check whether a function call has found the goal so the loop will continue regardless of whether it has been found. The return just ends the current function call not the entire recursion. Return true if it is found and then check the return value and keep returning true.

return value (Python best practices)

I have one function (F1) returning the values of (a, b, c)
and other function (F2) using those values. I need to check on F2 if "a is None".
This is the first function (F1)
def get_info():
msg = get_msg()
number = get_number()
if msg is not None:
return msg, number
return False, False
Secound function (F2)
def save_log():
msg, number = get_info()
if msg:
do_more_stuff
If I don't do return False, False in the first function I get TypeError: 'bool' object is not iterable in the second function.
Do I have a better way of returning those values other than return False, False.
What is the pythonic best practice in this situation?
Thanks
This is what a solution using errors/exceptions would look like. get_msg (and maybe get_number if applicable) would raise an exception when they fail to return a value, instead of returning a value that indicates failure.
class MessageRetrievalError(Exception):
pass
def get_msg():
message = message_code()
if message is None:
raise MessageRetrievalError
return message
def get_info():
return get_msg(), get_number()
def save_log():
try:
msg, number = get_info()
do_more_stuff
except MessageRetrievalError:
do_other_stuff

Python 3: best way to implement your own type with constraints

I'm doing a Python 3 based data conversion and certain character based fields I operate on have specific character allowances and length constraints applied to them.
I'd want to have some sort of swappable/configurable constraint function I roll myself that I could call.
Can you extend str?
Is it best to define a class for this and make variables implementations of that class.
Or are there simpler ways to do this with Python 3?
I'm wondering if anyone can give me pointers as to what to Google for inspiration?
(My initial thoughts are to look at SQLAlchemy's internal code for inspiration for things like Column).
EDIT: SQLAlchemy's code is too sophisticated for this scenario!
For example a type that only allows:
alphanumerics (upper+lowercase)
numerics
plus a selection of special characters.
This may vary by field, but some may use same function.
Hence desire to create custom re-usable types.
I'll do character stripping or substitution.
Then one may only allow 50 chars, whilst another may allow 500 etc.
I'll pass back a tuple with original value, converted value, a boolean to indicate truncation occurred
This is what I ended up with:
valobj.py
import utils
class UDT:
def __init__(self, converter, maxlen, value):
if utils.getClassName(converter) != 'function':
raise TypeError(f'converter {converter} is not a function')
if int(maxlen) <= 0:
raise TypeError(f'maxlen {maxlen} must be 1 or more')
if utils.getClassName(value) != 'str':
raise TypeError(f'value {value} is not a Python String')
self.converter = converter
self.maxlen = int(maxlen)
self.value = value
def convert(self):
intermed = self.converter(self.value)
truncated = len(intermed) > self.maxlen
result = intermed[:self.maxlen] if truncated else intermed
return (result, truncated, self.value)
class Job:
def __init__(self, name):
self._name_tuple = UDT(utils.fix_chars, 64, name).convert()
utils.py
import string
def getClassName(arg):
return(str(type(arg)).replace("<class '","").replace("'>",""))
def fix_chars(text) -> str:
result = ''
for c in text:
if ( (string.ascii_letters.find(c) != -1)
or (string.digits.find(c) != -1)
or ('._-#'.find(c) != -1)
):
result += c
else:
result += '_'
result = tidy_up_str(result)
return (result)
def tidy_up_str(text) -> str:
result = text
result = result.replace('_-_', '_')
while result.find('__') != -1:
result = result.replace('__', '_')
if result.endswith('_'):
result = result[:-1]
return result

Best way to handle exceptions in functon args?

I was recently coding a few Python 3.x programs and I wonder what is the best way of handling simple exceptions in python function args. In this example I'm going with checking if inserted value can be converted to int. I've come up with two ways of doing this:
def test_err_try(x, y, z):
try:
int(x)
int(y)
int(z)
except ValueError or TypeError: #try handler
return 'Bad args.'
##code##
or
def test_err_if(x, y, z):
if type(x) != int or type(y) != int or type(z) != int: #if handler
raise ValueError('Bad args.')
else:
##code##
I know that there is a difference in what the handlers are returning - in the first case it's just string 'Bad args.' and in the second it is ValueError exception.
What is the best (or rather simplest and shortest) way? First, second or neither and there is a better one?
The answer depends on your use case. If you are building a function which will be exposed to an end user, then the try except block offers more functionality because it will allow any variable which can be converted to an int. In this case I would suggest raising an error rather than having the function return a string:
try:
x = int(x)
y = int(y)
z = int(z)
except ValueError:
raise TypeError("Input arguments should be convertible to int")
If the function is meant for internal use within your program, then it is best to use the assert statement because its evaluation can be disabled once you are finished debugging your program.
assert type(x) is int
assert type(y) is int
assert type(z) is int

Why does this code return none

why does the following code returns none:
j = 22
def test(j):
if j > 0:
print('j>0')
else:
print('j<0')
Output:
j>0
None
A function in Python always has a return value, even if you do not use a return statement, defaulting to None
Because the test function doesn't return a value, it ends up returning the object None. that's why it ended up printing None Since you do not have a return value specified
you may not use print in your function, but return a string instead
def test(j):
if j > 0:
return 'j>0'
else:
return 'j<0'
then call it like this: print it when calling the function
print(test(22))
see answer's here for more detail

Resources