Skip to content

Commit c91ba56

Browse files
authored
Feat: notebooks for hours conversion (#17)
2 parents e62e971 + 27c23ba commit c91ba56

32 files changed

+1044
-40
lines changed

.devcontainer/devcontainer.json

+2
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919
"extensions": [
2020
"eamodio.gitlens",
2121
"esbenp.prettier-vscode",
22+
"mechatroner.rainbow-csv",
2223
"mhutchie.git-graph",
2324
"ms-python.python",
2425
"ms-python.black-formatter",
2526
"ms-python.flake8",
27+
"ms-toolsai.jupyter",
2628
"tamasfe.even-better-toml"
2729
]
2830
}

.env.sample

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
HARVEST_CLIENT_NAME=Client1
2+
HARVEST_DATA=data/harvest-sample.csv
3+
TOGGL_DATA=data/toggl-sample.csv
4+
TOGGL_PROJECT_INFO=data/toggl-project-info-sample.json
5+
TOGGL_USER_INFO=data/toggl-user-info-sample.json

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ __pycache__
44
!.config/README.md
55
.coverage
66
.downloads
7+
.env
78
.pytest_cache
89
*.csv
910
*.egg-info
11+
notebooks/data/*
12+
!notebooks/data/harvest-sample.csv
13+
!notebooks/data/toggl-project-info-sample.json
14+
!notebooks/data/toggl-sample.csv
15+
!notebooks/data/toggl-user-info-sample.json

compiler_admin/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from importlib.metadata import version, PackageNotFoundError
22

3+
RESULT_SUCCESS = 0
4+
RESULT_FAILURE = 1
5+
36
try:
47
__version__ = version("compiler_admin")
58
except PackageNotFoundError:

compiler_admin/commands/__init__.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +0,0 @@
1-
RESULT_SUCCESS = 0
2-
RESULT_FAILURE = 1

compiler_admin/commands/convert.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from argparse import Namespace
22

3-
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
3+
from compiler_admin import RESULT_SUCCESS, RESULT_FAILURE
44
from compiler_admin.services.google import (
55
GROUP_PARTNERS,
66
GROUP_STAFF,

compiler_admin/commands/create.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from argparse import Namespace
22
from typing import Sequence
33

4-
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
4+
from compiler_admin import RESULT_SUCCESS, RESULT_FAILURE
55
from compiler_admin.services.google import GROUP_TEAM, add_user_to_group, CallGAMCommand, user_account_name, user_exists
66

77

compiler_admin/commands/delete.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from argparse import Namespace
22

3-
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
3+
from compiler_admin import RESULT_SUCCESS, RESULT_FAILURE
44
from compiler_admin.services.google import CallGAMCommand, user_account_name, user_exists
55

66

compiler_admin/commands/info.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from compiler_admin import __version__ as version
2-
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
1+
from compiler_admin import __version__ as version, RESULT_SUCCESS, RESULT_FAILURE
32
from compiler_admin.services.google import CallGAMCommand, CallGYBCommand
43

54

compiler_admin/commands/init.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from shutil import rmtree
55
import subprocess
66

7-
from compiler_admin.commands import RESULT_FAILURE, RESULT_SUCCESS
7+
from compiler_admin import RESULT_FAILURE, RESULT_SUCCESS
88
from compiler_admin.services.google import USER_ARCHIVE, CallGAMCommand
99

1010

compiler_admin/commands/offboard.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from argparse import Namespace
22
from tempfile import NamedTemporaryFile
33

4-
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
4+
from compiler_admin import RESULT_SUCCESS, RESULT_FAILURE
55
from compiler_admin.commands.delete import delete
66
from compiler_admin.commands.signout import signout
77
from compiler_admin.services.google import (

compiler_admin/commands/reset_password.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from argparse import Namespace
22

3-
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
3+
from compiler_admin import RESULT_SUCCESS, RESULT_FAILURE
44
from compiler_admin.commands.signout import signout
55
from compiler_admin.services.google import USER_HELLO, CallGAMCommand, user_account_name, user_exists
66

compiler_admin/commands/restore.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from argparse import Namespace
22
import pathlib
33

4-
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
4+
from compiler_admin import RESULT_SUCCESS, RESULT_FAILURE
55
from compiler_admin.services.google import USER_ARCHIVE, CallGYBCommand, user_account_name
66

77

compiler_admin/commands/signout.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from argparse import Namespace
22

3-
from compiler_admin.commands import RESULT_SUCCESS, RESULT_FAILURE
3+
from compiler_admin import RESULT_SUCCESS, RESULT_FAILURE
44
from compiler_admin.services.google import CallGAMCommand, user_account_name, user_exists
55

66

compiler_admin/services/google.py

+33-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from tempfile import NamedTemporaryFile
44
from typing import Any, Sequence, IO
55

6+
from compiler_admin import RESULT_SUCCESS
7+
68
# import and alias CallGAMCommand so we can simplify usage in this app
79
from gam import CallGAMCommand as __CallGAMCommand, initializeLogging
810

@@ -96,9 +98,38 @@ def user_exists(username: str) -> bool:
9698
print(f"User not in domain: {username}")
9799
return False
98100

99-
res = CallGAMCommand(("info", "user", username, "quick"))
101+
info = user_info(username)
102+
103+
return info != {}
104+
100105

101-
return res == 0
106+
def user_info(username: str) -> dict:
107+
"""Get a dict of basic user information.
108+
109+
Args:
110+
username (str): The [email protected] to get.
111+
Returns:
112+
A dict of user information
113+
"""
114+
if not str(username).endswith(DOMAIN):
115+
print(f"User not in domain: {username}")
116+
return {}
117+
118+
with NamedTemporaryFile("w+") as stdout:
119+
res = CallGAMCommand(("info", "user", username, "quick"), stdout=stdout.name)
120+
if res != RESULT_SUCCESS:
121+
# user doesn't exist
122+
return {}
123+
# user exists, read data
124+
lines = stdout.readlines()
125+
# split on newline and filter out lines that aren't line "Key:Value" and empty value lines like "Key:<empty>"
126+
lines = [L.strip() for L in lines if len(L.split(":")) == 2 and L.split(":")[1].strip()]
127+
# make a map by splitting the lines, trimming key and value
128+
info = {}
129+
for line in lines:
130+
k, v = line.split(":")
131+
info[k.strip()] = v.strip()
132+
return info
102133

103134

104135
def user_in_group(username: str, group: str) -> bool:

0 commit comments

Comments
 (0)