diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2024-09-27 09:47:43 +0200 |
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2024-09-27 09:47:43 +0200 |
| commit | 53bdb0113d8cd362dc4551296980fe13fe0a5afb (patch) | |
| tree | 2633534d24597c655703c09922c4f747a150cae5 | |
| parent | df17630c7e18f846370e2595472513f1b52bf99c (diff) | |
| download | nixos-53bdb0113d8cd362dc4551296980fe13fe0a5afb.tar nixos-53bdb0113d8cd362dc4551296980fe13fe0a5afb.tar.gz nixos-53bdb0113d8cd362dc4551296980fe13fe0a5afb.tar.bz2 nixos-53bdb0113d8cd362dc4551296980fe13fe0a5afb.tar.xz nixos-53bdb0113d8cd362dc4551296980fe13fe0a5afb.zip | |
...
| -rw-r--r-- | .sops.yaml | 3 | ||||
| -rw-r--r-- | flake.lock | 21 | ||||
| -rw-r--r-- | flake.nix | 2 | ||||
| -rwxr-xr-x | overlays/worktime/worktime/__main__.py | 33 |
4 files changed, 38 insertions, 21 deletions
| @@ -5,6 +5,9 @@ keys: | |||
| 5 | - &machine_sif age1fj65apkhfkrwyv5tx6zcs9nkjg8267fy733qph30sc7zfn7vapjqkd5kne | 5 | - &machine_sif age1fj65apkhfkrwyv5tx6zcs9nkjg8267fy733qph30sc7zfn7vapjqkd5kne |
| 6 | 6 | ||
| 7 | creation_rules: | 7 | creation_rules: |
| 8 | - path_regex: ^hosts/surtr/email/ca | ||
| 9 | key_groups: | ||
| 10 | - age: [ *admin_gkleen ] | ||
| 8 | - path_regex: surtr\/?[^\/]*$ | 11 | - path_regex: surtr\/?[^\/]*$ |
| 9 | key_groups: | 12 | key_groups: |
| 10 | - age: [ *admin_gkleen, *machine_surtr ] | 13 | - age: [ *admin_gkleen, *machine_surtr ] |
| @@ -29,6 +29,7 @@ | |||
| 29 | "ca-util": { | 29 | "ca-util": { |
| 30 | "inputs": { | 30 | "inputs": { |
| 31 | "flake-parts": "flake-parts_2", | 31 | "flake-parts": "flake-parts_2", |
| 32 | "leapseconds": "leapseconds", | ||
| 32 | "nixpkgs": [ | 33 | "nixpkgs": [ |
| 33 | "nixpkgs" | 34 | "nixpkgs" |
| 34 | ], | 35 | ], |
| @@ -38,16 +39,16 @@ | |||
| 38 | "pre-commit-hooks-nix": "pre-commit-hooks-nix_2" | 39 | "pre-commit-hooks-nix": "pre-commit-hooks-nix_2" |
| 39 | }, | 40 | }, |
| 40 | "locked": { | 41 | "locked": { |
| 41 | "lastModified": 1701974982, | 42 | "lastModified": 1727074335, |
| 42 | "narHash": "sha256-crVlSEyoox6g8dpndqCgts3i6otVoGfDUmPz2ltG3IY=", | 43 | "narHash": "sha256-Sn7wqhrXargYzdw19m2mtBceQnW3VdhVneXRjl0iV3U=", |
| 43 | "owner": "gkleen", | 44 | "owner": "gkleen", |
| 44 | "repo": "ca", | 45 | "repo": "ca", |
| 45 | "rev": "8cfabef934ee8219d12b9ba46e2b2f4d6dc61f8d", | 46 | "rev": "9d681fe550639eab54cc402de4852e9a438b9757", |
| 46 | "type": "gitlab" | 47 | "type": "gitlab" |
| 47 | }, | 48 | }, |
| 48 | "original": { | 49 | "original": { |
| 49 | "owner": "gkleen", | 50 | "owner": "gkleen", |
| 50 | "ref": "v2.3.3", | 51 | "ref": "v3.0.0", |
| 51 | "repo": "ca", | 52 | "repo": "ca", |
| 52 | "type": "gitlab" | 53 | "type": "gitlab" |
| 53 | } | 54 | } |
| @@ -390,6 +391,18 @@ | |||
| 390 | "type": "github" | 391 | "type": "github" |
| 391 | } | 392 | } |
| 392 | }, | 393 | }, |
| 394 | "leapseconds": { | ||
| 395 | "flake": false, | ||
| 396 | "locked": { | ||
| 397 | "narHash": "sha256-5ZaoY/bScQS7EGJRHu6vj9XWhbObmxNEaGugaGU7+lg=", | ||
| 398 | "type": "file", | ||
| 399 | "url": "https://data.iana.org/time-zones/tzdb/leap-seconds.list" | ||
| 400 | }, | ||
| 401 | "original": { | ||
| 402 | "type": "file", | ||
| 403 | "url": "https://data.iana.org/time-zones/tzdb/leap-seconds.list" | ||
| 404 | } | ||
| 405 | }, | ||
| 393 | "nix-github-actions": { | 406 | "nix-github-actions": { |
| 394 | "inputs": { | 407 | "inputs": { |
| 395 | "nixpkgs": [ | 408 | "nixpkgs": [ |
| @@ -131,7 +131,7 @@ | |||
| 131 | type = "gitlab"; | 131 | type = "gitlab"; |
| 132 | owner = "gkleen"; | 132 | owner = "gkleen"; |
| 133 | repo = "ca"; | 133 | repo = "ca"; |
| 134 | ref = "v2.3.3"; | 134 | ref = "v3.0.0"; |
| 135 | inputs = { | 135 | inputs = { |
| 136 | nixpkgs.follows = "nixpkgs"; | 136 | nixpkgs.follows = "nixpkgs"; |
| 137 | poetry2nix.follows = "poetry2nix"; | 137 | poetry2nix.follows = "poetry2nix"; |
diff --git a/overlays/worktime/worktime/__main__.py b/overlays/worktime/worktime/__main__.py index 21316182..c2c1829c 100755 --- a/overlays/worktime/worktime/__main__.py +++ b/overlays/worktime/worktime/__main__.py | |||
| @@ -6,6 +6,8 @@ from xdg import BaseDirectory | |||
| 6 | import toml | 6 | import toml |
| 7 | from uritools import (uricompose) | 7 | from uritools import (uricompose) |
| 8 | 8 | ||
| 9 | from inspect import signature | ||
| 10 | |||
| 9 | from dateutil.easter import * | 11 | from dateutil.easter import * |
| 10 | from dateutil.tz import * | 12 | from dateutil.tz import * |
| 11 | from dateutil.parser import isoparse | 13 | from dateutil.parser import isoparse |
| @@ -633,14 +635,15 @@ def holidays(year, table_format, **args): | |||
| 633 | 635 | ||
| 634 | def leave(year, table, table_format, **args): | 636 | def leave(year, table, table_format, **args): |
| 635 | def_year = datetime.now(tzlocal()).year | 637 | def_year = datetime.now(tzlocal()).year |
| 636 | worktime = Worktime(**dict(**args, end_datetime = datetime(year = (year if year else def_year) + 1, month = 1, day = 1, tzinfo=tzlocal()) - timedelta(microseconds=1))) | ||
| 637 | config = Worktime.config() | 638 | config = Worktime.config() |
| 638 | date_format = config.get("WORKTIME", {}).get("DateFormat", '%Y-%m-%d') | ||
| 639 | leave_expires = config.get("WORKTIME", {}).get("LeaveExpires", None) | 639 | leave_expires = config.get("WORKTIME", {}).get("LeaveExpires", None) |
| 640 | if leave_expires: | 640 | if leave_expires: |
| 641 | leave_expires = datetime.strptime(leave_expires, '%m-%d').date() | 641 | leave_expires = datetime.strptime(leave_expires, '%m-%d').date() |
| 642 | worktime = Worktime(**dict(**args, end_datetime = datetime.combine(leave_expires.replace(year = (year if year else def_year) + 1), time(), tzinfo=tzlocal()) + timedelta(days=1) if leave_expires else datetime(year = (year if year else def_year) + 1, month = 1, day = 1, tzinfo=tzlocal()) - timedelta(microseconds=1))) | ||
| 643 | date_format = config.get("WORKTIME", {}).get("DateFormat", '%Y-%m-%d') | ||
| 642 | 644 | ||
| 643 | days = [worktime.start_date.date() + timedelta(days = x) for x in range(0, (worktime.end_date.date() - worktime.start_date.date()).days + 1)] | 645 | days = [worktime.start_date.date() + timedelta(days = x) for x in range(0, (worktime.end_date.date() - worktime.start_date.date()).days + 1)] |
| 646 | leave_days_budget = {} | ||
| 644 | 647 | ||
| 645 | leave_budget = deepcopy(worktime.leave_budget) | 648 | leave_budget = deepcopy(worktime.leave_budget) |
| 646 | year_leave_budget = deepcopy(worktime.leave_budget) if year else None | 649 | year_leave_budget = deepcopy(worktime.leave_budget) if year else None |
| @@ -655,36 +658,28 @@ def leave(year, table, table_format, **args): | |||
| 655 | if leave_budget[iyear] <= 0: | 658 | if leave_budget[iyear] <= 0: |
| 656 | continue | 659 | continue |
| 657 | 660 | ||
| 661 | leave_days_budget[day] = iyear | ||
| 658 | leave_budget[iyear] -= 1 | 662 | leave_budget[iyear] -= 1 |
| 659 | if year_leave_budget and day.year < year: | ||
| 660 | year_leave_budget[iyear] -= 1 | ||
| 661 | break | 663 | break |
| 662 | else: | 664 | else: |
| 663 | print(f'Unaccounted leave: {day}', file=stderr) | 665 | print(f'Unaccounted leave: {day}', file=stderr) |
| 664 | 666 | ||
| 665 | if table and year: | 667 | if table and year: |
| 666 | table_data = [] | 668 | table_data = [] |
| 667 | leave_days = sorted([day for day in worktime.leave_days if day.year == year and worktime.would_be_workday(day)]) | 669 | leave_days = sorted([day for day in worktime.leave_days if leave_days_budget[day] == year and worktime.would_be_workday(day)]) |
| 668 | 670 | ||
| 669 | count = 0 | 671 | count = 0 |
| 670 | for _, group in groupby(enumerate(leave_days), lambda kv: kv[0] - worktime.ordinal_workday(kv[1])): | 672 | for _, group in groupby(enumerate(leave_days), lambda kv: kv[0] - worktime.ordinal_workday(kv[1])): |
| 671 | group = list(map(lambda kv: kv[1], group)) | 673 | group = list(map(lambda kv: kv[1], group)) |
| 672 | 674 | ||
| 673 | for day in group: | 675 | for day in group: |
| 674 | for iyear in years: | 676 | year_leave_budget[year] -= 1 |
| 675 | if day > leave_expires.replace(year = iyear + 1): | ||
| 676 | continue | ||
| 677 | if year_leave_budget[iyear] <= 0: | ||
| 678 | continue | ||
| 679 | |||
| 680 | year_leave_budget[iyear] -= 1 | ||
| 681 | break | ||
| 682 | 677 | ||
| 683 | next_count = count + len(group) | 678 | next_count = count + len(group) |
| 684 | if len(group) > 1: | 679 | if len(group) > 1: |
| 685 | table_data.append([count, group[0].strftime('%m–%d') + '…' + group[-1].strftime('%m–%d'), len(group), sum(year_leave_budget.values())]) | 680 | table_data.append([count, group[0].strftime('%m-%d' if group[0].year == year else '%Y-%m-%d') + '…' + group[-1].strftime('%m-%d' if group[-1].year == year else '%Y-%m-%d'), len(group), year_leave_budget[year]]) |
| 686 | else: | 681 | else: |
| 687 | table_data.append([count, group[0].strftime('%m–%d'), len(group), sum(year_leave_budget.values())]) | 682 | table_data.append([count, group[0].strftime('%m-%d' if group[0].year == year else '%Y-%m-%d'), len(group), year_leave_budget[year]]) |
| 688 | count = next_count | 683 | count = next_count |
| 689 | print(tabulate(table_data, tablefmt=table_format, headers=["Running Count", "Leave Days", "# of Leave Days", "# of Leave Days Left"] if table_format != 'plain' else None)) | 684 | print(tabulate(table_data, tablefmt=table_format, headers=["Running Count", "Leave Days", "# of Leave Days", "# of Leave Days Left"] if table_format != 'plain' else None)) |
| 690 | elif table: | 685 | elif table: |
| @@ -834,7 +829,13 @@ def main(): | |||
| 834 | classification_parser.set_defaults(cmd = partial(classification, classification_name=classification_name)) | 829 | classification_parser.set_defaults(cmd = partial(classification, classification_name=classification_name)) |
| 835 | args = parser.parse_args() | 830 | args = parser.parse_args() |
| 836 | 831 | ||
| 837 | args.cmd(**vars(args)) | 832 | args.cmd( |
| 833 | **{ | ||
| 834 | k: v | ||
| 835 | for k, v in vars(args).items() | ||
| 836 | if k in signature(args.cmd).parameters.keys() | ||
| 837 | } | ||
| 838 | ) | ||
| 838 | 839 | ||
| 839 | if __name__ == "__main__": | 840 | if __name__ == "__main__": |
| 840 | sys.exit(main()) | 841 | sys.exit(main()) |
