# Validator for vertices of a polygon

Posted on

Problem

There is an object which has few properties. I wrote a function for test cases which check if the properties are satisfied or not. The function should throw an exception if the property is not satisfied.

But, I think there are better ways to write those test cases. A subset of the property of the object is as follows:

x[‘polygon’] is a list of >= 3 integer (x,y) pairs representing the
corners of the polygon in clockwise or anticlockwise order.

Current function is as follows:

``````def validate_object(x):
"""This function validates an object x that is supposed to represent an object
inside an image, and throws an exception on failure.
Specifically it is checking that:
x['polygon'] is a list of >= 3 integer (x,y) pairs representing the corners
of the polygon in clockwise or anticlockwise order.
"""
if type(x) != dict:
raise ValueError('dict type input required.')

if 'polygon' not in x:
raise ValueError('polygon object required.')

if not isinstance(x['polygon'], (list,)):
raise ValueError('list type polygon object required.')

points_list = x['polygon']
if len(points_list) < 3:
raise ValueError('More than two points required.')

for x, y in points_list:
if type(x) != int or type(y) != int:
raise ValueError('integer (x,y) pairs required.')

return
``````

It would be really helpful if someone could please suggest better ways of writing those test cases.

Solution

In Python, if you do not specify the return value of a function, then by default it will return `None`. So no need to hard code `return` in your case.

You do not need to create the extra variable `points_list` as you can directly write:

``````  if len(x['polygon']) < 3:
raise ValueError('More than two points required.')
``````

and:

`````` for x, y in x['polygon']:
if type(x) != int or type(y) != int:
raise ValueError('integer (x,y) pairs required.')
``````

Of course, choosing a meaningful and significant name for the object `x` will be better.

When we check `if stuff in some_iterable` we get `True` or `False`. I mean that a `ValueError` exception is not the most suitable thing that can happen here.

`isnstance()` returns `True` or `False`, and may raise a `TypeError` exception under certain conditions (check the link), so here also raising a `ValueError` may not be appropriate.

Because when you raise the exception, you communicate to the user only what he needs to know (through the messages you specified for each case) and because of the last 2 points I mentioned previously, I suggest you to create a custom exception which message can be overridden for each situation:

``````class InvalidPolygonObject(Exception):
pass
``````

And your function can be written this way:

``````def validate_object(polygon_object):
if type(polygon_object) != dict:
raise InvalidPolygonObject('dict type input required.')

if 'polygon' not in polygon_object:
raise InvalidPolygonObject('polygon object required.')

if not isinstance(polygon_object['polygon'], (list,)):
raise InvalidPolygonObject('list type polygon object required.')

if len(polygon_object['polygon']) < 3:
raise InvalidPolygonObject('More than two points required.')

for x, y in polygon_object['polygon']:
if type(x) != int or type(y) != int:
raise InvalidPolygonObject('integer (x,y) pairs required.')
``````