diff options
-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()) |