Skip to content

Commit 520c77c

Browse files
authored
feat: added settings endpoints (#147)
1 parent 90c8b30 commit 520c77c

File tree

6 files changed

+96
-19
lines changed

6 files changed

+96
-19
lines changed

Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ install:
2020
cp misc/aw-server.service /usr/lib/systemd/user/aw-server.service
2121

2222
test:
23+
@# Note that extensive integration tests are also run in the bundle repo,
24+
@# for both aw-server and aw-server-rust, but without code coverage.
2325
python -c 'import aw_server'
2426
python -m pytest tests/test_server.py
2527

aw_server/api.py

+11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
from .__about__ import __version__
2323
from .exceptions import NotFound
24+
from .settings import Settings
2425

2526
logger = logging.getLogger(__name__)
2627

@@ -50,6 +51,7 @@ def g(self, bucket_id, *args, **kwargs):
5051
class ServerAPI:
5152
def __init__(self, db, testing) -> None:
5253
self.db = db
54+
self.settings = Settings(testing)
5355
self.testing = testing
5456
self.last_event = {} # type: dict
5557

@@ -354,3 +356,12 @@ def get_log(self):
354356
for line in log_file.readlines()[::-1]:
355357
payload.append(json.loads(line))
356358
return payload, 200
359+
360+
def get_setting(self, key):
361+
"""Get a setting"""
362+
return self.settings.get(key, None)
363+
364+
def set_setting(self, key, value):
365+
"""Set a setting"""
366+
self.settings[key] = value
367+
return value

aw_server/rest.py

+17
Original file line numberDiff line numberDiff line change
@@ -387,3 +387,20 @@ class LogResource(Resource):
387387
@copy_doc(ServerAPI.get_log)
388388
def get(self):
389389
return current_app.api.get_log(), 200
390+
391+
392+
# SETTINGS
393+
394+
395+
@api.route("/0/settings", defaults={"key": ""})
396+
@api.route("/0/settings/<string:key>")
397+
class SettingsResource(Resource):
398+
def get(self, key: str):
399+
data = current_app.api.get_setting(key)
400+
return jsonify(data)
401+
402+
def post(self, key: str):
403+
if not key:
404+
raise BadRequest("MissingParameter", "Missing required parameter key")
405+
data = current_app.api.set_setting(key, request.get_json())
406+
return data

aw_server/settings.py

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import json
2+
from pathlib import Path
3+
4+
from aw_core.dirs import get_config_dir
5+
6+
7+
class Settings:
8+
def __init__(self, testing: bool):
9+
filename = "settings.json" if not testing else "settings-testing.json"
10+
self.config_file = Path(get_config_dir("aw-server")) / filename
11+
self.load()
12+
13+
def __getitem__(self, key):
14+
return self.get(key)
15+
16+
def __setitem__(self, key, value):
17+
return self.set(key, value)
18+
19+
def load(self):
20+
if self.config_file.exists():
21+
with open(self.config_file) as f:
22+
self.data = json.load(f)
23+
else:
24+
self.data = {}
25+
26+
def save(self):
27+
with open(self.config_file, "w") as f:
28+
json.dump(self.data, f, indent=4)
29+
30+
def get(self, key: str, default=None):
31+
if not key:
32+
return self.data
33+
return self.data.get(key, default)
34+
35+
def set(self, key, value):
36+
if value:
37+
self.data[key] = value
38+
else:
39+
if key in self.data:
40+
del self.data[key]
41+
self.save()

tests/conftest.py

+16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
22

33
import pytest
4+
from aw_client import ActivityWatchClient
45
from aw_server.server import AWFlask
56

67
logging.basicConfig(level=logging.WARN)
@@ -14,3 +15,18 @@ def app():
1415
@pytest.fixture(scope="session")
1516
def flask_client(app):
1617
yield app.test_client()
18+
19+
20+
@pytest.fixture(scope="session")
21+
def aw_client():
22+
# TODO: Could it be possible to write a sisterclass of ActivityWatchClient
23+
# which calls aw_server.api directly? Would it be of use? Would add another
24+
# layer of integration tests that are actually more like unit tests.
25+
c = ActivityWatchClient("aw-client-test", testing=True)
26+
yield c
27+
28+
# Delete test buckets after all tests needing the fixture have been run
29+
buckets = c.get_buckets()
30+
for bucket_id in buckets:
31+
if bucket_id.startswith("test-"):
32+
c.delete_bucket(bucket_id)

tests/test_client.py

+9-19
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import logging
2-
from datetime import datetime, timezone, timedelta
32
import random
4-
from time import sleep
3+
from datetime import datetime, timedelta, timezone
54
from pprint import pprint
5+
from time import sleep
66

77
import pytest
8-
98
from aw_core.models import Event
10-
from aw_client import ActivityWatchClient
119

1210
logging.basicConfig(level=logging.WARN)
1311

@@ -16,21 +14,6 @@
1614
# layer of integration tests that are actually more like unit tests.
1715

1816

19-
@pytest.fixture(scope="session")
20-
def aw_client():
21-
# TODO: Could it be possible to write a sisterclass of ActivityWatchClient
22-
# which calls aw_server.api directly? Would it be of use? Would add another
23-
# layer of integration tests that are actually more like unit tests.
24-
c = ActivityWatchClient("client-test", testing=True)
25-
yield c
26-
27-
# Delete test buckets after all tests needing the fixture have been run
28-
buckets = c.get_buckets()
29-
for bucket_id in buckets:
30-
if bucket_id.startswith("test-"):
31-
c.delete_bucket(bucket_id)
32-
33-
3417
@pytest.fixture(scope="function")
3518
def bucket(aw_client):
3619
bucket_id = "test-" + str(random.randint(0, 10**5))
@@ -285,3 +268,10 @@ def test_midnight_heartbeats(aw_client, bucket):
285268
)
286269
pprint(recv_events_after_midnight)
287270
assert len(recv_events_after_midnight) == int(len(recv_events_merged) / 2)
271+
272+
273+
def test_settings(aw_client):
274+
aw_client.set_setting("test", "test")
275+
assert aw_client.get_setting("test") == "test"
276+
assert aw_client.get_setting("test2") is None
277+
assert aw_client.get_setting() == {"test": "test"}

0 commit comments

Comments
 (0)