Skip to content

Commit

Permalink
Merge pull request #83 from dougthor42/metric-api-patch
Browse files Browse the repository at this point in the history
Metric api patch
  • Loading branch information
dougthor42 committed Feb 19, 2019
2 parents 6939314 + 8c9fddc commit c04a63c
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
+ `DELETE /api/v1/metric/<metric_name>` has been implemented (#78)
+ `POST /api/v1/metric` has been implemented (#74)
+ `PUT /api/v1/metric/<metric_name>` has been implemented (#75)
+ `PATCH /api/v1/metric/<metric_name>` has been implemented (#83)


## v0.3.0 (2019-01-28)
Expand Down
99 changes: 99 additions & 0 deletions src/trendlines/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from peewee import DoesNotExist
from peewee import IntegrityError
from playhouse.shortcuts import model_to_dict
from playhouse.shortcuts import update_model_from_dict

from trendlines import logger
from . import db
Expand Down Expand Up @@ -369,3 +370,101 @@ def put_metric(metric):
}

return jsonify(rv), 200


@api.route("/api/v1/metric/<metric>", methods=["PATCH"])
def patch_metric(metric):
"""
Update the values for a given metric.
This cannot change the ``metric_id`` value.
Accepts JSON data with the following format:
.. code-block::json
{
"name": {string, optional},
"units": {string, optional},
"upper_limit": {float, optional},
"lower_limit": {float, optional}
}
Returns
-------
200 :
Success. Returned JSON data has two keys: ``old_value`` and
``new_value``, each containing only the changed items of the
:class:`orm.Metric` object.
404 :
The requested metric is not found.
409 :
The target metric name already exists.
See Also
--------
:func:`routes.get_metric_as_json`
:func:`routes.post_metric`
:func:`routes.delete_metric`
:func:`routes.put_metric`
"""
# XXX: This is essentially the same code as `put`... Gotta refactor ASAP
data = request.get_json()

# First see if our item actually exists
try:
metric = db.Metric.get(db.Metric.name == metric)
old_name = metric.name
old_units = metric.units
old_lower = metric.lower_limit
old_upper = metric.upper_limit
except DoesNotExist:
http_status = 404
detail = "The metric '{}' does not exist".format(metric)
resp = utils.Rfc7807ErrorResponse(
type_="metric-not-found",
title="Metric not found",
status=http_status,
detail=detail,
)
logger.warning("API error: %s" % detail)
return resp.as_response(), http_status

metric = update_model_from_dict(metric, data)

try:
metric.save()
except IntegrityError:
# Failed the unique constraint on Metric.name
http_status = 409
detail = ("Unable to change metric name '{}': target name '{}'"
" already exists.")
detail = detail.format(old_name, metric.name)
resp = utils.Rfc7807ErrorResponse(
type_="integrity-error",
title="Constraint Failure",
status=http_status,
detail=detail,
)
logger.warning("API error: %s" % detail)
return resp.as_response(), http_status

old = {
"name": old_name,
"units": old_units,
"lower_limit": old_lower,
"upper_limit": old_upper,
}
new = {
"name": metric.name,
"units": metric.units,
"lower_limit": metric.lower_limit,
"upper_limit": metric.upper_limit,
}

# This seems... silly.
rv = {'old_value': {}, 'new_value': {}}
for item in data.keys():
rv['old_value'][item] = old[item]
rv['new_value'][item] = new[item]

return jsonify(rv), 200
38 changes: 38 additions & 0 deletions tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,41 @@ def test_api_put_metric_idempotence(client, populated_db):
d = rv.get_json()
# Then verify that they *didn't* change.
assert d['old_value'] == d['new_value']


def test_api_patch_metric(client, populated_db):
data = {"units": "pears"}
rv = client.patch("/api/v1/metric/foo", json=data)
assert rv.status_code == 200
assert rv.is_json
d = rv.get_json()
assert d['old_value']['units'] is None
assert d['new_value']['units'] == "pears"
assert 'name' not in d['old_value'].keys()
assert 'name' not in d['new_value'].keys()
assert 'lower_limit' not in d['old_value'].keys()
assert 'lower_limit' not in d['new_value'].keys()


def test_api_patch_metric_not_found(client, populated_db):
name = "missing"
data = {"units": "pears"}
rv = client.patch("/api/v1/metric/{}".format(name), json=data)
assert rv.status_code == 404
assert rv.is_json
d = rv.get_json()
assert name in d['detail']
assert "does not exist" in d['detail']


def test_api_patch_metric_duplicate_name(client, populated_db):
new_name = "foo.bar"
old_name = "old_data"
data = {"name": new_name}
rv = client.patch("/api/v1/metric/{}".format(old_name), json=data)
assert rv.status_code == 409
assert rv.is_json
d = rv.get_json()
assert old_name in d['detail']
assert new_name in d['detail']
assert "Unable to change metric name" in d['detail']

0 comments on commit c04a63c

Please sign in to comment.