diff options
| -rw-r--r-- | overlays/worktime/default.nix | 2 | ||||
| -rwxr-xr-x | overlays/worktime/worktime.py | 15 |
2 files changed, 14 insertions, 3 deletions
diff --git a/overlays/worktime/default.nix b/overlays/worktime/default.nix index 20c0b90f..699e00c0 100644 --- a/overlays/worktime/default.nix +++ b/overlays/worktime/default.nix | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | phases = [ "buildPhase" "checkPhase" "installPhase" ]; | 6 | phases = [ "buildPhase" "checkPhase" "installPhase" ]; |
| 7 | 7 | ||
| 8 | python = prev.python39.withPackages (ps: with ps; [pyxdg python-dateutil uritools requests configparser tabulate]); | 8 | python = prev.python39.withPackages (ps: with ps; [pyxdg python-dateutil uritools requests configparser tabulate backoff]); |
| 9 | buildInputs = [ python ]; | 9 | buildInputs = [ python ]; |
| 10 | 10 | ||
| 11 | buildPhase = '' | 11 | buildPhase = '' |
diff --git a/overlays/worktime/worktime.py b/overlays/worktime/worktime.py index 166bea1c..46197b6e 100755 --- a/overlays/worktime/worktime.py +++ b/overlays/worktime/worktime.py | |||
| @@ -30,6 +30,9 @@ from tabulate import tabulate | |||
| 30 | from itertools import groupby | 30 | from itertools import groupby |
| 31 | from functools import cache | 31 | from functools import cache |
| 32 | 32 | ||
| 33 | import backoff | ||
| 34 | |||
| 35 | |||
| 33 | class TogglAPISection(Enum): | 36 | class TogglAPISection(Enum): |
| 34 | TOGGL = '/api/v8' | 37 | TOGGL = '/api/v8' |
| 35 | REPORTS = '/reports/api/v2' | 38 | REPORTS = '/reports/api/v2' |
| @@ -62,7 +65,17 @@ class TogglAPI(object): | |||
| 62 | return uri | 65 | return uri |
| 63 | 66 | ||
| 64 | def _query(self, url, method): | 67 | def _query(self, url, method): |
| 68 | response = self._raw_query(url, method) | ||
| 69 | response.raise_for_status() | ||
| 70 | return response | ||
| 65 | 71 | ||
| 72 | @backoff.on_predicate( | ||
| 73 | backoff.expo, | ||
| 74 | factor=0.1, max_value=2, | ||
| 75 | predicate=lambda r: r.status_code == 429, | ||
| 76 | max_time=10, | ||
| 77 | ) | ||
| 78 | def _raw_query(self, url, method): | ||
| 66 | headers = {'content-type': 'application/json'} | 79 | headers = {'content-type': 'application/json'} |
| 67 | response = None | 80 | response = None |
| 68 | 81 | ||
| @@ -73,8 +86,6 @@ class TogglAPI(object): | |||
| 73 | else: | 86 | else: |
| 74 | raise ValueError(f"Undefined HTTP method “{method}”") | 87 | raise ValueError(f"Undefined HTTP method “{method}”") |
| 75 | 88 | ||
| 76 | response.raise_for_status() | ||
| 77 | |||
| 78 | return response | 89 | return response |
| 79 | 90 | ||
| 80 | def get_billable_hours(self, start_date, end_date=datetime.now(timezone.utc), rounding=False): | 91 | def get_billable_hours(self, start_date, end_date=datetime.now(timezone.utc), rounding=False): |
