summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.sops.yaml3
-rw-r--r--flake.lock21
-rw-r--r--flake.nix2
-rwxr-xr-xoverlays/worktime/worktime/__main__.py33
4 files changed, 38 insertions, 21 deletions
diff --git a/.sops.yaml b/.sops.yaml
index 51823ad2..7b0507ee 100644
--- a/.sops.yaml
+++ b/.sops.yaml
@@ -5,6 +5,9 @@ keys:
5 - &machine_sif age1fj65apkhfkrwyv5tx6zcs9nkjg8267fy733qph30sc7zfn7vapjqkd5kne 5 - &machine_sif age1fj65apkhfkrwyv5tx6zcs9nkjg8267fy733qph30sc7zfn7vapjqkd5kne
6 6
7creation_rules: 7creation_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 ]
diff --git a/flake.lock b/flake.lock
index 8510955d..df28d666 100644
--- a/flake.lock
+++ b/flake.lock
@@ -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": [
diff --git a/flake.nix b/flake.nix
index 728a6322..fc60e599 100644
--- a/flake.nix
+++ b/flake.nix
@@ -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
6import toml 6import toml
7from uritools import (uricompose) 7from uritools import (uricompose)
8 8
9from inspect import signature
10
9from dateutil.easter import * 11from dateutil.easter import *
10from dateutil.tz import * 12from dateutil.tz import *
11from dateutil.parser import isoparse 13from dateutil.parser import isoparse
@@ -633,14 +635,15 @@ def holidays(year, table_format, **args):
633 635
634def leave(year, table, table_format, **args): 636def 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
839if __name__ == "__main__": 840if __name__ == "__main__":
840 sys.exit(main()) 841 sys.exit(main())