ladok3 4.10__py3-none-any.whl → 4.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ladok3 might be problematic. Click here for more details.
- doc/ltxobj/ladok3.pdf +0 -0
- ladok3/__init__.py +41 -34
- ladok3/cli.nw +23 -9
- ladok3/cli.py +261 -241
- {ladok3-4.10.dist-info → ladok3-4.11.dist-info}/METADATA +1 -1
- {ladok3-4.10.dist-info → ladok3-4.11.dist-info}/RECORD +9 -9
- {ladok3-4.10.dist-info → ladok3-4.11.dist-info}/LICENSE +0 -0
- {ladok3-4.10.dist-info → ladok3-4.11.dist-info}/WHEEL +0 -0
- {ladok3-4.10.dist-info → ladok3-4.11.dist-info}/entry_points.txt +0 -0
doc/ltxobj/ladok3.pdf
CHANGED
|
Binary file
|
ladok3/__init__.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""A Python wrapper for the LADOK3 API"""
|
|
2
|
+
|
|
2
3
|
# -*- coding: utf-8 -*-
|
|
3
4
|
import cachetools
|
|
4
5
|
import datetime
|
|
@@ -4125,40 +4126,46 @@ class LadokSession:
|
|
|
4125
4126
|
"results": [
|
|
4126
4127
|
{
|
|
4127
4128
|
"education_id": result["UtbildningUID"],
|
|
4128
|
-
"pending":
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
"
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
result["SenastAttesteradeResultat"]["
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4129
|
+
"pending": (
|
|
4130
|
+
{
|
|
4131
|
+
"id": result["Arbetsunderlag"]["Uid"],
|
|
4132
|
+
"moment_id": result["Arbetsunderlag"][
|
|
4133
|
+
"UtbildningsinstansUID"
|
|
4134
|
+
],
|
|
4135
|
+
"grade": self.__get_grade_by_id(
|
|
4136
|
+
result["Arbetsunderlag"]["Betygsgrad"]
|
|
4137
|
+
),
|
|
4138
|
+
"date": result["Arbetsunderlag"]["Examinationsdatum"],
|
|
4139
|
+
"grade_scale": self.__get_grade_scale_by_id(
|
|
4140
|
+
result["Arbetsunderlag"]["BetygsskalaID"]
|
|
4141
|
+
),
|
|
4142
|
+
# behövs vid uppdatering av betygsutkast
|
|
4143
|
+
"last_modified": result["Arbetsunderlag"][
|
|
4144
|
+
"SenasteResultatandring"
|
|
4145
|
+
],
|
|
4146
|
+
}
|
|
4147
|
+
if "Arbetsunderlag" in result
|
|
4148
|
+
else None
|
|
4149
|
+
),
|
|
4150
|
+
"attested": (
|
|
4151
|
+
{
|
|
4152
|
+
"id": result["SenastAttesteradeResultat"]["Uid"],
|
|
4153
|
+
"moment_id": result["SenastAttesteradeResultat"][
|
|
4154
|
+
"UtbildningsinstansUID"
|
|
4155
|
+
],
|
|
4156
|
+
"grade": self.__get_grade_by_id(
|
|
4157
|
+
result["SenastAttesteradeResultat"]["Betygsgrad"]
|
|
4158
|
+
),
|
|
4159
|
+
"date": result["SenastAttesteradeResultat"][
|
|
4160
|
+
"Examinationsdatum"
|
|
4161
|
+
],
|
|
4162
|
+
"grade_scale": self.__get_grade_scale_by_id(
|
|
4163
|
+
result["SenastAttesteradeResultat"]["BetygsskalaID"]
|
|
4164
|
+
),
|
|
4165
|
+
}
|
|
4166
|
+
if "SenastAttesteradeResultat" in result
|
|
4167
|
+
else None
|
|
4168
|
+
),
|
|
4162
4169
|
}
|
|
4163
4170
|
for result in r["ResultatPaUtbildningar"]
|
|
4164
4171
|
],
|
ladok3/cli.nw
CHANGED
|
@@ -522,6 +522,9 @@ def load_credentials(filename="config.json"):
|
|
|
522
522
|
|
|
523
523
|
First we try the newest format.
|
|
524
524
|
We try to fetch the institution and vars from the keyring.
|
|
525
|
+
|
|
526
|
+
Note that [[keyring]] returns [[None]] if the key doesn't exist, it doesn't
|
|
527
|
+
raise an exception.
|
|
525
528
|
<<fetch vars from keyring>>=
|
|
526
529
|
try:
|
|
527
530
|
institution = keyring.get_password("ladok3", "institution")
|
|
@@ -529,7 +532,9 @@ try:
|
|
|
529
532
|
|
|
530
533
|
vars = {}
|
|
531
534
|
for key in vars_keys.split(";"):
|
|
532
|
-
|
|
535
|
+
value = keyring.get_password("ladok3", key)
|
|
536
|
+
if value:
|
|
537
|
+
vars[key] = value
|
|
533
538
|
|
|
534
539
|
if institution and vars:
|
|
535
540
|
return institution, vars
|
|
@@ -542,12 +547,10 @@ supported KTH.
|
|
|
542
547
|
<<fetch username and password from keyring>>=
|
|
543
548
|
try:
|
|
544
549
|
institution = "KTH Royal Institute of Technology"
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
if vars:
|
|
550
|
-
return institution, vars
|
|
550
|
+
username = keyring.get_password("ladok3", "username")
|
|
551
|
+
password = keyring.get_password("ladok3", "password")
|
|
552
|
+
if username and password:
|
|
553
|
+
return institution, {"username": username, "password": password}
|
|
551
554
|
except:
|
|
552
555
|
pass
|
|
553
556
|
@
|
|
@@ -581,7 +584,10 @@ try:
|
|
|
581
584
|
|
|
582
585
|
vars = {}
|
|
583
586
|
for key in vars_keys.split(":"):
|
|
584
|
-
|
|
587
|
+
try:
|
|
588
|
+
vars[key] = os.environ[key]
|
|
589
|
+
except KeyError:
|
|
590
|
+
<<print warning about missing variable in [[LADOK_VARS]]>>
|
|
585
591
|
|
|
586
592
|
if institution and vars:
|
|
587
593
|
return institution, vars
|
|
@@ -589,6 +595,14 @@ except:
|
|
|
589
595
|
pass
|
|
590
596
|
@
|
|
591
597
|
|
|
598
|
+
Unlike in the other cases, we don't just ignore the exception of the key not
|
|
599
|
+
existing.
|
|
600
|
+
Since the user has explicitly specified the variable, we should warn them that
|
|
601
|
+
it doesn't exist.
|
|
602
|
+
<<print warning about missing variable in [[LADOK_VARS]]>>=
|
|
603
|
+
warn(f"Variable {key} not set, ignoring.")
|
|
604
|
+
@
|
|
605
|
+
|
|
592
606
|
If none of the above worked, the last resort is to try to read the
|
|
593
607
|
configuration file.
|
|
594
608
|
We pop the institution from the configuration file (a dictionary), because then
|
|
@@ -599,7 +613,7 @@ try:
|
|
|
599
613
|
config = json.load(conf_file)
|
|
600
614
|
|
|
601
615
|
institution = config.pop("institution",
|
|
602
|
-
|
|
616
|
+
"KTH Royal Institute of Technology")
|
|
603
617
|
return institution, config
|
|
604
618
|
except:
|
|
605
619
|
pass
|
ladok3/cli.py
CHANGED
|
@@ -26,92 +26,97 @@ import ladok3.student
|
|
|
26
26
|
|
|
27
27
|
dirs = appdirs.AppDirs("ladok", "dbosk@kth.se")
|
|
28
28
|
|
|
29
|
+
|
|
29
30
|
def err(rc, msg):
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
print(f"{sys.argv[0]}: error: {msg}", file=sys.stderr)
|
|
32
|
+
sys.exit(rc)
|
|
33
|
+
|
|
32
34
|
|
|
33
35
|
def warn(msg):
|
|
34
|
-
|
|
35
|
-
def store_ladok_session(ls, credentials):
|
|
36
|
-
if not os.path.isdir(dirs.user_cache_dir):
|
|
37
|
-
os.makedirs(dirs.user_cache_dir)
|
|
36
|
+
print(f"{sys.argv[0]}: {msg}", file=sys.stderr)
|
|
38
37
|
|
|
39
|
-
file_path = dirs.user_cache_dir + "/LadokSession"
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
def store_ladok_session(ls, credentials):
|
|
40
|
+
if not os.path.isdir(dirs.user_cache_dir):
|
|
41
|
+
os.makedirs(dirs.user_cache_dir)
|
|
44
42
|
|
|
45
|
-
|
|
46
|
-
try:
|
|
47
|
-
salt = credentials["username"]
|
|
48
|
-
passwd = credentials["password"]
|
|
49
|
-
except KeyError:
|
|
50
|
-
credentials = list(credentials.values())
|
|
51
|
-
salt = credentials[0]
|
|
52
|
-
passwd = credentials[1]
|
|
53
|
-
else:
|
|
54
|
-
salt = credentials[0]
|
|
55
|
-
passwd = credentials[1]
|
|
56
|
-
|
|
57
|
-
kdf = PBKDF2HMAC(
|
|
58
|
-
algorithm=hashes.SHA256(),
|
|
59
|
-
length=32,
|
|
60
|
-
salt=salt.encode("utf-8"),
|
|
61
|
-
iterations=100000
|
|
62
|
-
)
|
|
63
|
-
key = base64.urlsafe_b64encode(kdf.derive(passwd.encode("utf-8")))
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
fernet_protocol = Fernet(key)
|
|
67
|
-
encrypted_ls = fernet_protocol.encrypt(pickled_ls)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
with open(file_path, "wb") as file:
|
|
71
|
-
file.write(encrypted_ls)
|
|
72
|
-
|
|
73
|
-
def restore_ladok_session(credentials):
|
|
74
|
-
file_path = dirs.user_cache_dir + "/LadokSession"
|
|
43
|
+
file_path = dirs.user_cache_dir + "/LadokSession"
|
|
75
44
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
encrypted_ls = file.read()
|
|
79
|
-
if not credentials or len(credentials) < 2:
|
|
45
|
+
pickled_ls = pickle.dumps(ls)
|
|
46
|
+
if not credentials or len(credentials) < 2:
|
|
80
47
|
raise ValueError(f"Missing credentials, see `ladok login -h`.")
|
|
81
48
|
|
|
82
|
-
|
|
49
|
+
if isinstance(credentials, dict):
|
|
83
50
|
try:
|
|
84
|
-
|
|
85
|
-
|
|
51
|
+
salt = credentials["username"]
|
|
52
|
+
passwd = credentials["password"]
|
|
86
53
|
except KeyError:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
54
|
+
credentials = list(credentials.values())
|
|
55
|
+
salt = credentials[0]
|
|
56
|
+
passwd = credentials[1]
|
|
57
|
+
else:
|
|
91
58
|
salt = credentials[0]
|
|
92
59
|
passwd = credentials[1]
|
|
93
60
|
|
|
94
|
-
|
|
61
|
+
kdf = PBKDF2HMAC(
|
|
95
62
|
algorithm=hashes.SHA256(),
|
|
96
63
|
length=32,
|
|
97
64
|
salt=salt.encode("utf-8"),
|
|
98
|
-
iterations=100000
|
|
99
|
-
|
|
100
|
-
|
|
65
|
+
iterations=100000,
|
|
66
|
+
)
|
|
67
|
+
key = base64.urlsafe_b64encode(kdf.derive(passwd.encode("utf-8")))
|
|
68
|
+
|
|
69
|
+
fernet_protocol = Fernet(key)
|
|
70
|
+
encrypted_ls = fernet_protocol.encrypt(pickled_ls)
|
|
71
|
+
|
|
72
|
+
with open(file_path, "wb") as file:
|
|
73
|
+
file.write(encrypted_ls)
|
|
101
74
|
|
|
102
75
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
76
|
+
def restore_ladok_session(credentials):
|
|
77
|
+
file_path = dirs.user_cache_dir + "/LadokSession"
|
|
78
|
+
|
|
79
|
+
if os.path.isfile(file_path):
|
|
80
|
+
with open(file_path, "rb") as file:
|
|
81
|
+
encrypted_ls = file.read()
|
|
82
|
+
if not credentials or len(credentials) < 2:
|
|
83
|
+
raise ValueError(f"Missing credentials, see `ladok login -h`.")
|
|
84
|
+
|
|
85
|
+
if isinstance(credentials, dict):
|
|
86
|
+
try:
|
|
87
|
+
salt = credentials["username"]
|
|
88
|
+
passwd = credentials["password"]
|
|
89
|
+
except KeyError:
|
|
90
|
+
credentials = list(credentials.values())
|
|
91
|
+
salt = credentials[0]
|
|
92
|
+
passwd = credentials[1]
|
|
93
|
+
else:
|
|
94
|
+
salt = credentials[0]
|
|
95
|
+
passwd = credentials[1]
|
|
96
|
+
|
|
97
|
+
kdf = PBKDF2HMAC(
|
|
98
|
+
algorithm=hashes.SHA256(),
|
|
99
|
+
length=32,
|
|
100
|
+
salt=salt.encode("utf-8"),
|
|
101
|
+
iterations=100000,
|
|
102
|
+
)
|
|
103
|
+
key = base64.urlsafe_b64encode(kdf.derive(passwd.encode("utf-8")))
|
|
104
|
+
|
|
105
|
+
fernet_protocol = Fernet(key)
|
|
106
|
+
try:
|
|
107
|
+
pickled_ls = fernet_protocol.decrypt(encrypted_ls)
|
|
108
|
+
except Exception as err:
|
|
109
|
+
warn(f"cache was corrupted, cannot decrypt: {err}")
|
|
110
|
+
pickled_ls = None
|
|
111
|
+
if pickled_ls:
|
|
112
|
+
return pickle.loads(pickled_ls)
|
|
113
|
+
|
|
114
|
+
return None
|
|
115
|
+
|
|
111
116
|
|
|
112
|
-
return None
|
|
113
117
|
def update_credentials_in_keyring(ls, args):
|
|
114
|
-
|
|
118
|
+
print(
|
|
119
|
+
"""
|
|
115
120
|
This login process is exactly the same as when you log in using
|
|
116
121
|
the web browser. You need three things:
|
|
117
122
|
|
|
@@ -126,57 +131,66 @@ the web browser. You need three things:
|
|
|
126
131
|
|
|
127
132
|
3) Your password at your institution.
|
|
128
133
|
|
|
129
|
-
"""
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
134
|
+
"""
|
|
135
|
+
)
|
|
136
|
+
while True:
|
|
137
|
+
institution = input("Institution: ")
|
|
138
|
+
matches = sa.find_entity_data_by_name(institution)
|
|
133
139
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
140
|
+
if not matches:
|
|
141
|
+
print("No match, try again.")
|
|
142
|
+
continue
|
|
137
143
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
144
|
+
if len(matches) > 1:
|
|
145
|
+
print("More than one match. Which one?")
|
|
146
|
+
for match in matches:
|
|
147
|
+
print(f"- {match['title']}")
|
|
148
|
+
continue
|
|
143
149
|
|
|
144
|
-
|
|
150
|
+
match = matches[0]
|
|
145
151
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
152
|
+
print(
|
|
153
|
+
f"Matched uniquely, using {match['title']}\n"
|
|
154
|
+
f" with domain {match['domain']} and\n"
|
|
155
|
+
f" unique identifier {match['id']}."
|
|
156
|
+
)
|
|
149
157
|
|
|
150
|
-
|
|
151
|
-
|
|
158
|
+
institution = match["id"]
|
|
159
|
+
break
|
|
152
160
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
161
|
+
vars = {
|
|
162
|
+
"username": input("Institution username: "),
|
|
163
|
+
"password": getpass.getpass("Institution password: [input is hidden] "),
|
|
164
|
+
}
|
|
165
|
+
while True:
|
|
166
|
+
temp_ls = ladok3.LadokSession(institution, vars=vars)
|
|
167
|
+
|
|
168
|
+
try:
|
|
169
|
+
temp_ls.user_info_JSON()
|
|
170
|
+
except weblogin.AuthenticationError as err:
|
|
171
|
+
adjust_vars(vars, err.variables)
|
|
172
|
+
else:
|
|
173
|
+
break
|
|
159
174
|
|
|
160
175
|
try:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
clear_cache(ls, args)
|
|
176
|
+
keyring.set_password("ladok3", "institution", institution)
|
|
177
|
+
keyring.set_password("ladok3", "vars", ";".join(vars.keys()))
|
|
178
|
+
for key, value in vars.items():
|
|
179
|
+
keyring.set_password("ladok3", key, value)
|
|
180
|
+
except Exception as err:
|
|
181
|
+
globals()["err"](
|
|
182
|
+
-1,
|
|
183
|
+
f"You don't seem to have a working keyring. "
|
|
184
|
+
f"Use one of the other methods, see "
|
|
185
|
+
f"`ladok login -h`: {err}.",
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
clear_cache(ls, args)
|
|
189
|
+
|
|
190
|
+
|
|
178
191
|
def adjust_vars(vars, form_variables):
|
|
179
|
-
|
|
192
|
+
print(
|
|
193
|
+
"""
|
|
180
194
|
Some part of the authentication went wrong. Either you typed your username or
|
|
181
195
|
password incorrectly, or your institution requires some adjustments. We'll
|
|
182
196
|
guide you through it.
|
|
@@ -191,107 +205,115 @@ when it should be 'dbosk@ug.kth.se' --- or something similar. Use your
|
|
|
191
205
|
institution's login page to figure this out.
|
|
192
206
|
|
|
193
207
|
Note: Your password will be visible on screen during this process.
|
|
194
|
-
"""
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
key
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
208
|
+
"""
|
|
209
|
+
)
|
|
210
|
+
input("\nPress return to continue.\n")
|
|
211
|
+
|
|
212
|
+
for key, value in form_variables.items():
|
|
213
|
+
key = key.casefold()
|
|
214
|
+
new_val = input(f"{key} = '{value}' " f"[enter new value, blank to keep] ")
|
|
215
|
+
if new_val:
|
|
216
|
+
vars[key] = new_val
|
|
217
|
+
|
|
218
|
+
|
|
203
219
|
def load_credentials(filename="config.json"):
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
220
|
+
"""
|
|
221
|
+
Loads credentials from environment or file named filename.
|
|
222
|
+
Returns the tuple (instituation, credential dictionary) that
|
|
223
|
+
can be passed to `LadokSession(instiution, credential dictionary)`.
|
|
224
|
+
"""
|
|
225
|
+
|
|
226
|
+
try:
|
|
227
|
+
institution = keyring.get_password("ladok3", "institution")
|
|
228
|
+
vars_keys = keyring.get_password("ladok3", "vars")
|
|
229
|
+
|
|
230
|
+
vars = {}
|
|
231
|
+
for key in vars_keys.split(";"):
|
|
232
|
+
value = keyring.get_password("ladok3", key)
|
|
233
|
+
if value:
|
|
234
|
+
vars[key] = value
|
|
235
|
+
|
|
236
|
+
if institution and vars:
|
|
237
|
+
return institution, vars
|
|
238
|
+
except:
|
|
239
|
+
pass
|
|
240
|
+
try:
|
|
241
|
+
institution = "KTH Royal Institute of Technology"
|
|
242
|
+
username = keyring.get_password("ladok3", "username")
|
|
243
|
+
password = keyring.get_password("ladok3", "password")
|
|
244
|
+
if username and password:
|
|
245
|
+
return institution, {"username": username, "password": password}
|
|
246
|
+
except:
|
|
247
|
+
pass
|
|
248
|
+
try:
|
|
249
|
+
institution = os.environ["LADOK_INST"]
|
|
250
|
+
except:
|
|
251
|
+
institution = "KTH Royal Institute of Technology"
|
|
252
|
+
|
|
253
|
+
try:
|
|
254
|
+
vars = {
|
|
255
|
+
"username": os.environ["LADOK_USER"],
|
|
256
|
+
"password": os.environ["LADOK_PASS"],
|
|
257
|
+
}
|
|
258
|
+
if institution and vars:
|
|
259
|
+
return institution, vars
|
|
260
|
+
except:
|
|
261
|
+
pass
|
|
262
|
+
try:
|
|
263
|
+
vars_keys = os.environ["LADOK_VARS"]
|
|
264
|
+
|
|
265
|
+
vars = {}
|
|
266
|
+
for key in vars_keys.split(":"):
|
|
267
|
+
try:
|
|
268
|
+
vars[key] = os.environ[key]
|
|
269
|
+
except KeyError:
|
|
270
|
+
warn(f"Variable {key} not set, ignoring.")
|
|
271
|
+
|
|
272
|
+
if institution and vars:
|
|
273
|
+
return institution, vars
|
|
274
|
+
except:
|
|
275
|
+
pass
|
|
276
|
+
try:
|
|
277
|
+
with open(filename) as conf_file:
|
|
278
|
+
config = json.load(conf_file)
|
|
279
|
+
|
|
280
|
+
institution = config.pop("institution", "KTH Royal Institute of Technology")
|
|
281
|
+
return institution, config
|
|
282
|
+
except:
|
|
283
|
+
pass
|
|
284
|
+
|
|
285
|
+
return None, None
|
|
286
|
+
|
|
287
|
+
|
|
268
288
|
def clear_cache(ls, args):
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
289
|
+
try:
|
|
290
|
+
os.remove(dirs.user_cache_dir + "/LadokSession")
|
|
291
|
+
except FileNotFoundError as err:
|
|
292
|
+
pass
|
|
293
|
+
|
|
294
|
+
sys.exit(0)
|
|
295
|
+
|
|
273
296
|
|
|
274
|
-
sys.exit(0)
|
|
275
297
|
def main():
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
required=True
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
298
|
+
"""Run the command-line interface for the ladok command"""
|
|
299
|
+
argp = argparse.ArgumentParser(
|
|
300
|
+
description="This is a CLI-ification of LADOK3's web GUI.",
|
|
301
|
+
epilog="Web: https://github.com/dbosk/ladok3",
|
|
302
|
+
)
|
|
303
|
+
argp.add_argument(
|
|
304
|
+
"-f",
|
|
305
|
+
"--config-file",
|
|
306
|
+
default=f"{dirs.user_config_dir}/config.json",
|
|
307
|
+
help="Path to configuration file "
|
|
308
|
+
f"(default: {dirs.user_config_dir}/config.json) "
|
|
309
|
+
"or set LADOK_USER and LADOK_PASS environment variables.",
|
|
310
|
+
)
|
|
311
|
+
subp = argp.add_subparsers(title="commands", dest="command", required=True)
|
|
312
|
+
login_parser = subp.add_parser(
|
|
313
|
+
"login",
|
|
314
|
+
help="Manage login credentials",
|
|
315
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
316
|
+
description=f"""
|
|
295
317
|
Manages the user's LADOK login credentials. There are three ways to supply the
|
|
296
318
|
login credentials, in order of priority:
|
|
297
319
|
|
|
@@ -321,42 +343,40 @@ def main():
|
|
|
321
343
|
option). (The keys 'username' and 'password' can be renamed to correspond to
|
|
322
344
|
the necessary values if the university login system uses other names.)
|
|
323
345
|
|
|
324
|
-
"""
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
ls
|
|
353
|
-
|
|
354
|
-
args.func(ls, args)
|
|
355
|
-
store_ladok_session(ls, LADOK_VARS)
|
|
346
|
+
""",
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
login_parser.set_defaults(func=update_credentials_in_keyring)
|
|
350
|
+
cache_parser = subp.add_parser(
|
|
351
|
+
"cache", help="Manage cache", description="Manages the cache of LADOK data"
|
|
352
|
+
)
|
|
353
|
+
cache_subp = cache_parser.add_subparsers(
|
|
354
|
+
title="subcommands", dest="subcommand", required=True
|
|
355
|
+
)
|
|
356
|
+
cache_clear = cache_subp.add_parser(
|
|
357
|
+
"clear", help="Clear the cache", description="Clears everything from the cache"
|
|
358
|
+
)
|
|
359
|
+
cache_clear.set_defaults(func=clear_cache)
|
|
360
|
+
ladok3.data.add_command_options(subp)
|
|
361
|
+
ladok3.report.add_command_options(subp)
|
|
362
|
+
ladok3.student.add_command_options(subp)
|
|
363
|
+
argcomplete.autocomplete(argp)
|
|
364
|
+
args = argp.parse_args()
|
|
365
|
+
LADOK_INST, LADOK_VARS = load_credentials(args.config_file)
|
|
366
|
+
try:
|
|
367
|
+
ls = restore_ladok_session(LADOK_VARS)
|
|
368
|
+
except ValueError as error:
|
|
369
|
+
err(-1, f"Couldn't restore LADOK session: {error}")
|
|
370
|
+
if not ls:
|
|
371
|
+
ls = ladok3.LadokSession(LADOK_INST, vars=LADOK_VARS)
|
|
372
|
+
if "func" in args:
|
|
373
|
+
args.func(ls, args)
|
|
374
|
+
store_ladok_session(ls, LADOK_VARS)
|
|
375
|
+
|
|
356
376
|
|
|
357
377
|
if __name__ == "__main__":
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
378
|
+
try:
|
|
379
|
+
main()
|
|
380
|
+
sys.exit(0)
|
|
381
|
+
except Exception as e:
|
|
382
|
+
err(-1, e)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
doc/ltxobj/ladok3.pdf,sha256=
|
|
1
|
+
doc/ltxobj/ladok3.pdf,sha256=WZ3PoQ8-IPNLUNiOwv9P0pxsFHaRx2vTTgbQjtfGajo,1407824
|
|
2
2
|
ladok3/.gitignore,sha256=QOcCshtjIsFasi4vaqFcooBWPJkxVWaoYEWOBBtdY_w,81
|
|
3
3
|
ladok3/Makefile,sha256=Jy6OFjoVLU9YivnVxctxI_zrUOK9ysEOiistJ3ST6Nw,557
|
|
4
|
-
ladok3/__init__.py,sha256=
|
|
4
|
+
ladok3/__init__.py,sha256=3z1Lys2ygnuDyYFvm4O4Um6vgYud470W3xX4gYJ4bMc,245725
|
|
5
5
|
ladok3/api.nw,sha256=pHFU8T2tr2N4kJfyo7uKzNd1lpkd7KICK8lHzV6b1-Y,43304
|
|
6
|
-
ladok3/cli.nw,sha256=
|
|
7
|
-
ladok3/cli.py,sha256=
|
|
6
|
+
ladok3/cli.nw,sha256=cwooD_hc9ZpgnRhQ9TebbeWp_ZjKDTWjcV9Qqiqxu28,22378
|
|
7
|
+
ladok3/cli.py,sha256=pLAVt2XhaGJ50knOlRNX_lcS3NFExu5ChHPgItRRGvI,12093
|
|
8
8
|
ladok3/data.nw,sha256=3o6-kmeMtCGoSJ5yL8qFCuIINQeym_WtW_2mhItuR-s,11785
|
|
9
9
|
ladok3/data.py,sha256=kPRO9l5DTQb9lGnN2kU-YYPSyg31t0bq5HCw986hbPk,6747
|
|
10
10
|
ladok3/ladok.bash,sha256=zGfTFdtos2zLjV13pzfK-1uCy2b_lF2qUKMoL2ExW7c,1441
|
|
@@ -14,8 +14,8 @@ ladok3/report.py,sha256=1K7cRaedemiOGDDAMI9wqnctLeic5ZlMYHw5hzhnvQw,5627
|
|
|
14
14
|
ladok3/student.nw,sha256=zayn9_b9jCKeMnZxSGS_EuSmF3ojOBHQDMUMMkpRssI,3747
|
|
15
15
|
ladok3/student.py,sha256=TaYn2rpbQnzummB-8xz-sUEV31Gh0CUmU0QkF6VgEic,1703
|
|
16
16
|
ladok3/undoc.nw,sha256=NyHuVIzrRqJPM39MyAlZNEE7PbXdUDJFQ2kJ0NfdwQI,180333
|
|
17
|
-
ladok3-4.
|
|
18
|
-
ladok3-4.
|
|
19
|
-
ladok3-4.
|
|
20
|
-
ladok3-4.
|
|
21
|
-
ladok3-4.
|
|
17
|
+
ladok3-4.11.dist-info/LICENSE,sha256=s_C5qznXAvDRrzU7vRd4eqzshyIkAfPwGyVBihGeOdM,1155
|
|
18
|
+
ladok3-4.11.dist-info/METADATA,sha256=b_1jNYsFOsiXR11udNkWFRzBZepydHwWfRAu9PTRlFo,8822
|
|
19
|
+
ladok3-4.11.dist-info/WHEEL,sha256=kLuE8m1WYU0Ig0_YEGrXyTtiJvKPpLpDEiChiNyei5Y,88
|
|
20
|
+
ladok3-4.11.dist-info/entry_points.txt,sha256=pi-KKP5Obo0AyuDjXQUpadS9kIvAY2_5ORhPgEYlJv8,41
|
|
21
|
+
ladok3-4.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|