diff options
author | Gregor Kleen <gkleen@yggdrasil.li> | 2023-04-04 10:34:46 +0200 |
---|---|---|
committer | Gregor Kleen <gkleen@yggdrasil.li> | 2023-04-04 10:34:46 +0200 |
commit | f9476f8b1dda0efdcedd0e5e0615f15d0d9f4cde (patch) | |
tree | 5f25ea51197000313a28d20e16a6eb3eda775d1f | |
parent | dce843e98018baffd6a7d2d157d3362d1395fb0f (diff) | |
download | nixos-f9476f8b1dda0efdcedd0e5e0615f15d0d9f4cde.tar nixos-f9476f8b1dda0efdcedd0e5e0615f15d0d9f4cde.tar.gz nixos-f9476f8b1dda0efdcedd0e5e0615f15d0d9f4cde.tar.bz2 nixos-f9476f8b1dda0efdcedd0e5e0615f15d0d9f4cde.tar.xz nixos-f9476f8b1dda0efdcedd0e5e0615f15d0d9f4cde.zip |
...
-rw-r--r-- | overlays/worktime/poetry.lock | 30 | ||||
-rw-r--r-- | overlays/worktime/pyproject.toml | 2 | ||||
-rwxr-xr-x | overlays/worktime/worktime/__main__.py | 44 |
3 files changed, 38 insertions, 38 deletions
diff --git a/overlays/worktime/poetry.lock b/overlays/worktime/poetry.lock index 7a9a9b86..eab1d070 100644 --- a/overlays/worktime/poetry.lock +++ b/overlays/worktime/poetry.lock | |||
@@ -110,22 +110,6 @@ files = [ | |||
110 | ] | 110 | ] |
111 | 111 | ||
112 | [[package]] | 112 | [[package]] |
113 | name = "configparser" | ||
114 | version = "5.3.0" | ||
115 | description = "Updated configparser from stdlib for earlier Pythons." | ||
116 | category = "main" | ||
117 | optional = false | ||
118 | python-versions = ">=3.7" | ||
119 | files = [ | ||
120 | {file = "configparser-5.3.0-py3-none-any.whl", hash = "sha256:b065779fd93c6bf4cee42202fa4351b4bb842e96a3fb469440e484517a49b9fa"}, | ||
121 | {file = "configparser-5.3.0.tar.gz", hash = "sha256:8be267824b541c09b08db124917f48ab525a6c3e837011f3130781a224c57090"}, | ||
122 | ] | ||
123 | |||
124 | [package.extras] | ||
125 | docs = ["jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx"] | ||
126 | testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "types-backports"] | ||
127 | |||
128 | [[package]] | ||
129 | name = "idna" | 113 | name = "idna" |
130 | version = "3.4" | 114 | version = "3.4" |
131 | description = "Internationalized Domain Names in Applications (IDNA)" | 115 | description = "Internationalized Domain Names in Applications (IDNA)" |
@@ -214,6 +198,18 @@ files = [ | |||
214 | widechars = ["wcwidth"] | 198 | widechars = ["wcwidth"] |
215 | 199 | ||
216 | [[package]] | 200 | [[package]] |
201 | name = "toml" | ||
202 | version = "0.10.2" | ||
203 | description = "Python Library for Tom's Obvious, Minimal Language" | ||
204 | category = "main" | ||
205 | optional = false | ||
206 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" | ||
207 | files = [ | ||
208 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, | ||
209 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, | ||
210 | ] | ||
211 | |||
212 | [[package]] | ||
217 | name = "uritools" | 213 | name = "uritools" |
218 | version = "4.0.1" | 214 | version = "4.0.1" |
219 | description = "URI parsing, classification and composition" | 215 | description = "URI parsing, classification and composition" |
@@ -245,4 +241,4 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] | |||
245 | [metadata] | 241 | [metadata] |
246 | lock-version = "2.0" | 242 | lock-version = "2.0" |
247 | python-versions = "^3.10" | 243 | python-versions = "^3.10" |
248 | content-hash = "30e7918385e12f686b92da70a0be69cd22879892239b65e399828c24d13ca262" | 244 | content-hash = "0d556c1b7f4ca6764a006e10ef9949359911925a9dae09d25a3c3d26d8966790" |
diff --git a/overlays/worktime/pyproject.toml b/overlays/worktime/pyproject.toml index f3fd3dfa..61257422 100644 --- a/overlays/worktime/pyproject.toml +++ b/overlays/worktime/pyproject.toml | |||
@@ -10,9 +10,9 @@ pyxdg = "^0.28" | |||
10 | python-dateutil = "^2.8.2" | 10 | python-dateutil = "^2.8.2" |
11 | uritools = "^4.0.1" | 11 | uritools = "^4.0.1" |
12 | requests = "^2.28.2" | 12 | requests = "^2.28.2" |
13 | configparser = "^5.3.0" | ||
14 | tabulate = "^0.9.0" | 13 | tabulate = "^0.9.0" |
15 | backoff = "^2.2.1" | 14 | backoff = "^2.2.1" |
15 | toml = "^0.10.2" | ||
16 | 16 | ||
17 | [tool.poetry.scripts] | 17 | [tool.poetry.scripts] |
18 | worktime = "worktime.__main__:main" | 18 | worktime = "worktime.__main__:main" |
diff --git a/overlays/worktime/worktime/__main__.py b/overlays/worktime/worktime/__main__.py index ed7880db..2dc9ed72 100755 --- a/overlays/worktime/worktime/__main__.py +++ b/overlays/worktime/worktime/__main__.py | |||
@@ -3,7 +3,7 @@ from requests.exceptions import HTTPError | |||
3 | from requests.auth import HTTPBasicAuth | 3 | from requests.auth import HTTPBasicAuth |
4 | from datetime import * | 4 | from datetime import * |
5 | from xdg import (BaseDirectory) | 5 | from xdg import (BaseDirectory) |
6 | import configparser | 6 | import toml |
7 | from uritools import uricompose | 7 | from uritools import uricompose |
8 | 8 | ||
9 | from dateutil.easter import * | 9 | from dateutil.easter import * |
@@ -30,6 +30,8 @@ from functools import cache | |||
30 | 30 | ||
31 | import backoff | 31 | import backoff |
32 | 32 | ||
33 | from pathlib import Path | ||
34 | |||
33 | 35 | ||
34 | class TogglAPISection(Enum): | 36 | class TogglAPISection(Enum): |
35 | TOGGL = '/api/v8' | 37 | TOGGL = '/api/v8' |
@@ -201,10 +203,8 @@ class Worktime(object): | |||
201 | 203 | ||
202 | @staticmethod | 204 | @staticmethod |
203 | def config(): | 205 | def config(): |
204 | config = configparser.ConfigParser() | ||
205 | config_dir = BaseDirectory.load_first_config('worktime') | 206 | config_dir = BaseDirectory.load_first_config('worktime') |
206 | config.read(f"{config_dir}/worktime.ini") | 207 | return toml.load(Path(config_dir) / 'worktime.toml') |
207 | return config | ||
208 | 208 | ||
209 | def ordinal_workday(self, date): | 209 | def ordinal_workday(self, date): |
210 | start_date = datetime(date.year, 1, 1, tzinfo=tzlocal()).date() | 210 | start_date = datetime(date.year, 1, 1, tzinfo=tzlocal()).date() |
@@ -222,14 +222,18 @@ class Worktime(object): | |||
222 | 222 | ||
223 | config = Worktime.config() | 223 | config = Worktime.config() |
224 | config_dir = BaseDirectory.load_first_config('worktime') | 224 | config_dir = BaseDirectory.load_first_config('worktime') |
225 | api = TogglAPI(api_token=config['TOGGL']['ApiToken'], workspace_id=config['TOGGL']['Workspace'], client_ids=config.get('TOGGL', 'ClientIds', fallback=None)) | 225 | api = TogglAPI( |
226 | date_format = config.get('WORKTIME', 'DateFormat', fallback='%Y-%m-%d') | 226 | api_token=config.get("TOGGL", {}).get("ApiToken", None), |
227 | 227 | workspace_id=config.get("TOGGL", {}).get("Workspace", None), | |
228 | start_date = start_datetime or datetime.strptime(config['WORKTIME']['StartDate'], date_format).replace(tzinfo=tzlocal()) | 228 | client_ids=config.get("TOGGL", {}).get("ClientIds", None) |
229 | ) | ||
230 | date_format = config.get("WORKTIME", {}).get("DateFormat", '%Y-%m-%d') | ||
231 | |||
232 | start_date = start_datetime or datetime.strptime(config.get("WORKTIME", {}).get("StartDate"), date_format).replace(tzinfo=tzlocal()) | ||
229 | end_date = end_datetime or self.now | 233 | end_date = end_datetime or self.now |
230 | 234 | ||
231 | try: | 235 | try: |
232 | with open(f"{config_dir}/reset", 'r') as reset: | 236 | with open(Path(config_dir) / "reset", 'r') as reset: |
233 | for line in reset: | 237 | for line in reset: |
234 | stripped_line = line.strip() | 238 | stripped_line = line.strip() |
235 | reset_date = datetime.strptime(stripped_line, date_format).replace(tzinfo=tzlocal()) | 239 | reset_date = datetime.strptime(stripped_line, date_format).replace(tzinfo=tzlocal()) |
@@ -241,13 +245,13 @@ class Worktime(object): | |||
241 | raise e | 245 | raise e |
242 | 246 | ||
243 | 247 | ||
244 | hours_per_week = float(config.get('WORKTIME', 'HoursPerWeek', fallback=40)) | 248 | hours_per_week = float(config.get("WORKTIME", {}).get("HoursPerWeek", 40)) |
245 | self.workdays = set([int(d.strip()) for d in config.get('WORKTIME', 'Workdays', fallback='1,2,3,4,5').split(',')]) | 249 | self.workdays = set([int(d.strip()) for d in config.get("WORKTIME", {}).get("Workdays", '1,2,3,4,5').split(',')]) |
246 | self.time_per_day = timedelta(hours = hours_per_week) / len(self.workdays) | 250 | self.time_per_day = timedelta(hours = hours_per_week) / len(self.workdays) |
247 | 251 | ||
248 | holidays = dict() | 252 | holidays = dict() |
249 | 253 | ||
250 | leave_per_year = int(config.get('WORKTIME', 'LeavePerYear', fallback=30)) | 254 | leave_per_year = int(config.get("WORKTIME", {}).get("LeavePerYear", 30)) |
251 | for year in range(start_date.year, end_date.year + 1): | 255 | for year in range(start_date.year, end_date.year + 1): |
252 | holidays |= {k: v * self.time_per_day for k, v in Worktime.holidays(year).items()} | 256 | holidays |= {k: v * self.time_per_day for k, v in Worktime.holidays(year).items()} |
253 | leave_frac = 1 | 257 | leave_frac = 1 |
@@ -256,7 +260,7 @@ class Worktime(object): | |||
256 | self.leave_budget |= {year: floor(leave_per_year * leave_frac)} | 260 | self.leave_budget |= {year: floor(leave_per_year * leave_frac)} |
257 | 261 | ||
258 | try: | 262 | try: |
259 | with open(f"{config_dir}/reset-leave", 'r') as excused: | 263 | with open(Path(config_dir) / "reset-leave", 'r') as excused: |
260 | for line in excused: | 264 | for line in excused: |
261 | stripped_line = line.strip() | 265 | stripped_line = line.strip() |
262 | if stripped_line: | 266 | if stripped_line: |
@@ -273,7 +277,7 @@ class Worktime(object): | |||
273 | 277 | ||
274 | for excused_kind in {'excused', 'leave'}: | 278 | for excused_kind in {'excused', 'leave'}: |
275 | try: | 279 | try: |
276 | with open(f"{config_dir}/{excused_kind}", 'r') as excused: | 280 | with open(Path(config_dir) / excused_kind, 'r') as excused: |
277 | for line in excused: | 281 | for line in excused: |
278 | stripped_line = line.strip() | 282 | stripped_line = line.strip() |
279 | if stripped_line: | 283 | if stripped_line: |
@@ -314,7 +318,7 @@ class Worktime(object): | |||
314 | end_day = end_date.date() | 318 | end_day = end_date.date() |
315 | 319 | ||
316 | try: | 320 | try: |
317 | with open(f"{config_dir}/pull-forward", 'r') as excused: | 321 | with open(Path(config_dir) / "pull-forward", 'r') as excused: |
318 | for line in excused: | 322 | for line in excused: |
319 | stripped_line = line.strip() | 323 | stripped_line = line.strip() |
320 | if stripped_line: | 324 | if stripped_line: |
@@ -357,7 +361,7 @@ class Worktime(object): | |||
357 | extra_days_to_work = dict() | 361 | extra_days_to_work = dict() |
358 | 362 | ||
359 | try: | 363 | try: |
360 | with open(f"{config_dir}/days-to-work", 'r') as extra_days_to_work_file: | 364 | with open(Path(config_dir) / "days-to-work", 'r') as extra_days_to_work_file: |
361 | for line in extra_days_to_work_file: | 365 | for line in extra_days_to_work_file: |
362 | stripped_line = line.strip() | 366 | stripped_line = line.strip() |
363 | if stripped_line: | 367 | if stripped_line: |
@@ -413,7 +417,7 @@ class Worktime(object): | |||
413 | 417 | ||
414 | self.time_to_work += self.time_pulled_forward | 418 | self.time_to_work += self.time_pulled_forward |
415 | 419 | ||
416 | self.time_worked += api.get_billable_hours(start_date, self.now, rounding = config.getboolean('WORKTIME', 'rounding', fallback=True)) | 420 | self.time_worked += api.get_billable_hours(start_date, self.now, rounding = config.get("WORKTIME", {}).get("rounding", True)) |
417 | 421 | ||
418 | def worktime(**args): | 422 | def worktime(**args): |
419 | worktime = Worktime(**args) | 423 | worktime = Worktime(**args) |
@@ -520,7 +524,7 @@ def diff(now, **args): | |||
520 | 524 | ||
521 | def holidays(year, **args): | 525 | def holidays(year, **args): |
522 | config = Worktime.config() | 526 | config = Worktime.config() |
523 | date_format = config.get('WORKTIME', 'DateFormat', fallback='%Y-%m-%d') | 527 | date_format = config.get("WORKTIME", {}).get("DateFormat", '%Y-%m-%d') |
524 | 528 | ||
525 | table_data = [] | 529 | table_data = [] |
526 | 530 | ||
@@ -534,8 +538,8 @@ def leave(year, table, **args): | |||
534 | def_year = datetime.now(tzlocal()).year | 538 | def_year = datetime.now(tzlocal()).year |
535 | worktime = Worktime(**dict(**args, end_datetime = datetime(year = (year if year else def_year) + 1, month = 1, day = 1, tzinfo=tzlocal()) - timedelta(microseconds=1))) | 539 | worktime = Worktime(**dict(**args, end_datetime = datetime(year = (year if year else def_year) + 1, month = 1, day = 1, tzinfo=tzlocal()) - timedelta(microseconds=1))) |
536 | config = Worktime.config() | 540 | config = Worktime.config() |
537 | date_format = config.get('WORKTIME', 'DateFormat', fallback='%Y-%m-%d') | 541 | date_format = config.get("WORKTIME", {}).get("DateFormat", '%Y-%m-%d') |
538 | leave_expires = config.get('WORKTIME', 'LeaveExpires', fallback=None) | 542 | leave_expires = config.get("WORKTIME", {}).get("LeaveExpires", None) |
539 | if leave_expires: | 543 | if leave_expires: |
540 | leave_expires = datetime.strptime(leave_expires, '%m-%d').date() | 544 | leave_expires = datetime.strptime(leave_expires, '%m-%d').date() |
541 | 545 | ||