From b833cf05a90761d75477120640eef90a38833a6a Mon Sep 17 00:00:00 2001 From: Stefan Huber Date: Mon, 19 Dec 2022 08:52:24 +0100 Subject: [PATCH] Add restpublish.py --- restpublish.py | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 restpublish.py diff --git a/restpublish.py b/restpublish.py new file mode 100644 index 0000000..9310d7a --- /dev/null +++ b/restpublish.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +# +# FLASK_APP=restpublish.py flask run + +import datetime + +import flask +from flask_restful import Resource, Api + + +class Element: + def __init__(self, key, value): + self.key = key + self.update(value) + + def update(self, value): + self.value = value + self.ctime = datetime.datetime.now() + + def is_expired(self, maxage): + return datetime.datetime.now() - self.ctime >= maxage + + +class ElementStore: + def __init__(self): + self.key_dict = dict() + self.chronolist = list() + + def insert(self, key, value): + if key in self.key_dict: + el = self.key_dict[key] + el.update(value) + else: + el = Element(key, value) + self.key_dict[key] = el + self.chronolist.append(el) + return el + + def remove(self, key): + del self.key_dict[key] + self.chronolist = [el for el in self.chronolist if el.key != key] + + def garbagecollect(self): + maxage = datetime.timedelta(7) + oldestctime = datetime.datetime.now() - maxage + def is_expired(el): + return el.ctime < oldestctime + + # Get idx such that self.chronolist[:idx] is expired and + # self.chronolist[idx:] is not expired. + idx = 0 + while idx < len(self.chronolist) - 1: + if not is_expired(self.chronolist[idx]): + break + idx += 1 + + for el in self.chronolist[:idx]: + del self.key_dict[el.key] + + self.chronolist = self.chronolist[idx:] + + +class EntryPoint(Resource): + def get(self): + return { 'elements': [el.key for el in store.chronolist] } + +class ElementPoint(Resource): + def get(self, key): + if key not in store.key_dict: + return { 'message': 'No such element'}, 404 + + el = store.key_dict[key] + return { 'key': key, 'value': el.value, 'ctime': str(el.ctime) } + + def delete(self, key): + if key in store.key_dict: + store.remove(key) + return { 'message': 'ok'} + + def post(self, key): + req = flask.request.get_json(force=True) + + if 'value' not in req: + return {'message': 'No value given.'}, 403 + + el = store.insert(key, req['value']) + store.garbagecollect() + return { 'key': key, 'value': el.value, 'ctime': str(el.ctime) } + + +# Map of keys to values +store = ElementStore() + +app = flask.Flask(__name__) +api = Api(app) +api.add_resource(EntryPoint, "/") +api.add_resource(ElementPoint, "/") + -- 2.39.5