# Buggy code
def __init__(self, granularity=None, points=None, timespan=None):
    if granularity is not None and points is not None and timespan is not None:
        if timespan != granularity * points:
            raise ValueError("timespan ≠ granularity × points")

    if granularity is not None and granularity <= 0:
        raise ValueError("Granularity should be > 0")

    if points is not None and points <= 0:
        raise ValueError("Number of points should be > 0")

    if granularity is None:
        if points is None or timespan is None:
            raise ValueError(
                "At least two of granularity/points/timespan must be provided"
            )
        granularity = round(timespan / float(points))
    else:
        granularity = float(granularity)

    if points is None:
        if timespan is None:
            self["timespan"] = None
        else:
            points = int(timespan / granularity)
            self["timespan"] = granularity * points
    else:
        points = int(points)
        self["timespan"] = granularity * points

    self["points"] = points
    self["granularity"] = granularity


# Traceback (ValueError)
Traceback (most recent call last):
File "/usr/lib64/python2.7/wsgiref/handlers.py", line 85, in run
self.result = application(self.environ, self.start_response)
File "/usr/lib/python2.7/site-packages/webob/dec.py", line 130, in __call__
resp = self.call_func(req, *args, **self.kwargs)
File "/usr/lib/python2.7/site-packages/webob/dec.py", line 195, in call_func
return self.func(req, *args, **kwargs)
File "/usr/lib/python2.7/site-packages/oslo_middleware/base.py", line 126, in __call__
response = req.get_response(self.application)
File "/usr/lib/python2.7/site-packages/webob/request.py", line 1299, in send
application, catch_exc_info=False)
File "/usr/lib/python2.7/site-packages/webob/request.py", line 1263, in call_application
app_iter = application(self.environ, start_response)
File "/usr/lib/python2.7/site-packages/paste/urlmap.py", line 216, in __call__
return app(environ, start_response)
File "/usr/lib/python2.7/site-packages/webob/dec.py", line 130, in __call__
resp = self.call_func(req, *args, **self.kwargs)
File "/usr/lib/python2.7/site-packages/webob/dec.py", line 195, in call_func
return self.func(req, *args, **kwargs)
File "/usr/lib/python2.7/site-packages/oslo_middleware/base.py", line 126, in __call__
response = req.get_response(self.application)
File "/usr/lib/python2.7/site-packages/webob/request.py", line 1299, in send
application, catch_exc_info=False)
File "/usr/lib/python2.7/site-packages/webob/request.py", line 1263, in call_application
app_iter = application(self.environ, start_response)
File "/usr/lib/python2.7/site-packages/webob/exc.py", line 1162, in __call__
return self.application(environ, start_response)
File "/usr/lib/python2.7/site-packages/gnocchi/rest/app.py", line 68, in __call__
return self.app(environ, start_response)
File "/usr/lib/python2.7/site-packages/pecan/middleware/recursive.py", line 56, in __call__
return self.application(environ, start_response)
File "/usr/lib/python2.7/site-packages/pecan/core.py", line 840, in __call__
return super(Pecan, self).__call__(environ, start_response)
File "/usr/lib/python2.7/site-packages/pecan/core.py", line 683, in __call__
self.invoke_controller(controller, args, kwargs, state)
File "/usr/lib/python2.7/site-packages/pecan/core.py", line 574, in invoke_controller
result = controller(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/gnocchi/rest/__init__.py", line 354, in get_all
return pecan.request.indexer.list_archive_policies()
File "/usr/lib/python2.7/site-packages/gnocchi/indexer/sqlalchemy.py", line 559, in list_archive_policies
return list(session.query(ArchivePolicy).all())
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/query.py", line 2613, in all
return list(self)
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/loading.py", line 86, in instances
util.raise_from_cause(err)
File "/usr/lib64/python2.7/site-packages/sqlalchemy/util/compat.py", line 202, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/loading.py", line 71, in instances
rows = [proc(row) for row in fetch]
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/loading.py", line 428, in _instance
loaded_instance, populate_existing, populators)
File "/usr/lib64/python2.7/site-packages/sqlalchemy/orm/loading.py", line 486, in _populate_full
dict_[key] = getter(row)
File "/usr/lib64/python2.7/site-packages/sqlalchemy/sql/type_api.py", line 1030, in process
return process_value(value, dialect)
File "/usr/lib/python2.7/site-packages/gnocchi/indexer/sqlalchemy_base.py", line 113, in process_result_value
return [archive_policy.ArchivePolicyItem(**v) for v in values]
File "/usr/lib/python2.7/site-packages/gnocchi/archive_policy.py", line 163, in __init__
raise ValueError("Number of points should be > 0")
ValueError: Number of points should be > 0

# Fixed code
def __init__(self, granularity=None, points=None, timespan=None):
    if granularity is not None and points is not None and timespan is not None:
        if timespan != granularity * points:
            raise ValueError("timespan ≠ granularity × points")

    if granularity is not None and granularity <= 0:
        raise ValueError("Granularity should be > 0")

    if points is not None and points <= 0:
        raise ValueError("Number of points should be > 0")

    if granularity is None:
        if points is None or timespan is None:
            raise ValueError(
                "At least two of granularity/points/timespan must be provided"
            )
        granularity = round(timespan / float(points))
    else:
        granularity = float(granularity)

    if points is None:
        if timespan is None:
            self["timespan"] = None
        else:
            points = int(timespan / granularity)
            if points <= 0:
                raise ValueError("Calculated number of points is < 0")
            self["timespan"] = granularity * points
    else:
        points = int(points)
        self["timespan"] = granularity * points

    self["points"] = points
    self["granularity"] = granularity