odysseeapi 0.0.1__tar.gz → 0.2.0__tar.gz
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.
- {odysseeapi-0.0.1 → odysseeapi-0.2.0}/PKG-INFO +15 -3
- {odysseeapi-0.0.1 → odysseeapi-0.2.0}/Readme.md +14 -2
- {odysseeapi-0.0.1 → odysseeapi-0.2.0}/odysseeapi/Odyssee.py +80 -2
- {odysseeapi-0.0.1 → odysseeapi-0.2.0}/odysseeapi.egg-info/PKG-INFO +15 -3
- {odysseeapi-0.0.1 → odysseeapi-0.2.0}/pyproject.toml +1 -1
- {odysseeapi-0.0.1 → odysseeapi-0.2.0}/odysseeapi/__init__.py +0 -0
- {odysseeapi-0.0.1 → odysseeapi-0.2.0}/odysseeapi.egg-info/SOURCES.txt +0 -0
- {odysseeapi-0.0.1 → odysseeapi-0.2.0}/odysseeapi.egg-info/dependency_links.txt +0 -0
- {odysseeapi-0.0.1 → odysseeapi-0.2.0}/odysseeapi.egg-info/top_level.txt +0 -0
- {odysseeapi-0.0.1 → odysseeapi-0.2.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: odysseeapi
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Unofficial Python API for Odyssee
|
|
5
5
|
Author-email: Géry Casiez <gery.casiez@univ-lille.fr>
|
|
6
6
|
Project-URL: Repository, https://github.com/casiez/OdysseeAPI
|
|
@@ -8,18 +8,22 @@ Classifier: Programming Language :: Python :: 3
|
|
|
8
8
|
Classifier: License :: OSI Approved :: BSD License
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
|
|
11
|
+
[](https://pypi.org/project/odysseeapi/)
|
|
12
|
+
[](https://pepy.tech/project/odysseeapi)
|
|
13
|
+
|
|
11
14
|
# Odyssee API
|
|
12
15
|
|
|
13
16
|
Provides an unofficial API for the [Odyssee platform](https://odyssee.enseignementsup-recherche.gouv.fr/), allowing users to access and interact with their data programmatically.
|
|
14
17
|
|
|
15
18
|
## Features
|
|
16
19
|
|
|
20
|
+
- download applications of candidates
|
|
17
21
|
- get information about candidates
|
|
18
22
|
- get information about committee members
|
|
19
23
|
- get information about institutions
|
|
20
24
|
- get keywords
|
|
21
25
|
- assign applications to committee members
|
|
22
|
-
-
|
|
26
|
+
- download reports from committee members
|
|
23
27
|
- provide decision on each candidate after the first round of evaluation
|
|
24
28
|
|
|
25
29
|
## Installation
|
|
@@ -52,6 +56,14 @@ from odysseeapi.Odyssee import Odyssee
|
|
|
52
56
|
|
|
53
57
|
numposte = "123456"
|
|
54
58
|
token = """eyJhbGciOiJSUzI1N... (token value) ..."""
|
|
59
|
+
|
|
60
|
+
# Initialize the API client with the numposte, token and use_cache set to True
|
|
61
|
+
# setting use_cache to False forces the API client to fetch fresh data from the server for each request, while setting it to True allows the client to use cached data if available
|
|
62
|
+
odyssee = Odyssee(numposte, token, True)
|
|
63
|
+
|
|
64
|
+
# Download the applications of the candidates in the specified directory
|
|
65
|
+
odyssee.download_applications('dossiers_candidats')
|
|
66
|
+
|
|
55
67
|
candidates = odyssee.get_candidates()
|
|
56
68
|
print(candidates)
|
|
57
69
|
|
|
@@ -70,7 +82,7 @@ print(candidates_with_details)
|
|
|
70
82
|
# odyssee.assign_jury_members_to_candidate("f1e2d3c4-b5a6-4789-9876-543210fedcba", "98765432-10fe-dcba-9876-543210fedcba", "abcd1234-5678-90ef-ghij-klmnopqrstuv")
|
|
71
83
|
|
|
72
84
|
# Download the reports of the committee members for the candidates in the specified directory
|
|
73
|
-
odyssee.downloadReports("
|
|
85
|
+
odyssee.downloadReports("rapports_odyssee")
|
|
74
86
|
|
|
75
87
|
# A l'issue de la première réunion du jury, enregistrer l'avis pour chaque candidat et les résultats du vote
|
|
76
88
|
# odyssee.opinion_for_interview("f1e2d3c4-b5a6-4789-9876-543210fedcba", "A", "Motif audition", 16, 16, 0, 0, 16, 0)
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
+
[](https://pypi.org/project/odysseeapi/)
|
|
2
|
+
[](https://pepy.tech/project/odysseeapi)
|
|
3
|
+
|
|
1
4
|
# Odyssee API
|
|
2
5
|
|
|
3
6
|
Provides an unofficial API for the [Odyssee platform](https://odyssee.enseignementsup-recherche.gouv.fr/), allowing users to access and interact with their data programmatically.
|
|
4
7
|
|
|
5
8
|
## Features
|
|
6
9
|
|
|
10
|
+
- download applications of candidates
|
|
7
11
|
- get information about candidates
|
|
8
12
|
- get information about committee members
|
|
9
13
|
- get information about institutions
|
|
10
14
|
- get keywords
|
|
11
15
|
- assign applications to committee members
|
|
12
|
-
-
|
|
16
|
+
- download reports from committee members
|
|
13
17
|
- provide decision on each candidate after the first round of evaluation
|
|
14
18
|
|
|
15
19
|
## Installation
|
|
@@ -42,6 +46,14 @@ from odysseeapi.Odyssee import Odyssee
|
|
|
42
46
|
|
|
43
47
|
numposte = "123456"
|
|
44
48
|
token = """eyJhbGciOiJSUzI1N... (token value) ..."""
|
|
49
|
+
|
|
50
|
+
# Initialize the API client with the numposte, token and use_cache set to True
|
|
51
|
+
# setting use_cache to False forces the API client to fetch fresh data from the server for each request, while setting it to True allows the client to use cached data if available
|
|
52
|
+
odyssee = Odyssee(numposte, token, True)
|
|
53
|
+
|
|
54
|
+
# Download the applications of the candidates in the specified directory
|
|
55
|
+
odyssee.download_applications('dossiers_candidats')
|
|
56
|
+
|
|
45
57
|
candidates = odyssee.get_candidates()
|
|
46
58
|
print(candidates)
|
|
47
59
|
|
|
@@ -60,7 +72,7 @@ print(candidates_with_details)
|
|
|
60
72
|
# odyssee.assign_jury_members_to_candidate("f1e2d3c4-b5a6-4789-9876-543210fedcba", "98765432-10fe-dcba-9876-543210fedcba", "abcd1234-5678-90ef-ghij-klmnopqrstuv")
|
|
61
73
|
|
|
62
74
|
# Download the reports of the committee members for the candidates in the specified directory
|
|
63
|
-
odyssee.downloadReports("
|
|
75
|
+
odyssee.downloadReports("rapports_odyssee")
|
|
64
76
|
|
|
65
77
|
# A l'issue de la première réunion du jury, enregistrer l'avis pour chaque candidat et les résultats du vote
|
|
66
78
|
# odyssee.opinion_for_interview("f1e2d3c4-b5a6-4789-9876-543210fedcba", "A", "Motif audition", 16, 16, 0, 0, 16, 0)
|
|
@@ -37,10 +37,11 @@ import tqdm
|
|
|
37
37
|
import os
|
|
38
38
|
|
|
39
39
|
class Odyssee(object):
|
|
40
|
-
def __init__(self, numposte, bearer_token):
|
|
40
|
+
def __init__(self, numposte, bearer_token, use_cache=True):
|
|
41
41
|
"""Initialize the Odyssee class.
|
|
42
42
|
numposte: the numposte to use for the API calls
|
|
43
|
-
bearer_token: the bearer token to use for the API calls
|
|
43
|
+
bearer_token: the bearer token to use for the API calls
|
|
44
|
+
use_cache: whether to use caching for API responses (default: True)"""
|
|
44
45
|
|
|
45
46
|
self.numposte = numposte
|
|
46
47
|
self.base_url = "https://odyssee.enseignementsup-recherche.gouv.fr/gateway/"
|
|
@@ -52,6 +53,26 @@ class Odyssee(object):
|
|
|
52
53
|
self.etablissements = None
|
|
53
54
|
self.keywords = None
|
|
54
55
|
self.reportsPath = "rapportsOdyssee"
|
|
56
|
+
self.use_cache = use_cache
|
|
57
|
+
self.__loadCache()
|
|
58
|
+
|
|
59
|
+
def __loadCache(self):
|
|
60
|
+
if os.path.exists("cache.json"):
|
|
61
|
+
with open("cache.json", "r") as f:
|
|
62
|
+
self.cache = json.load(f)
|
|
63
|
+
else:
|
|
64
|
+
self.cache = {
|
|
65
|
+
"candidatures": None,
|
|
66
|
+
"rapporteurs": None,
|
|
67
|
+
"etablissements": None,
|
|
68
|
+
"keywords": None,
|
|
69
|
+
"detailCandidatures": None
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
def __saveToCache(self, key, value):
|
|
73
|
+
self.cache[key] = value
|
|
74
|
+
with open("cache.json", "w") as f:
|
|
75
|
+
json.dump(self.cache, f)
|
|
55
76
|
|
|
56
77
|
def get_candidates(self):
|
|
57
78
|
"""
|
|
@@ -82,12 +103,17 @@ class Odyssee(object):
|
|
|
82
103
|
}
|
|
83
104
|
"""
|
|
84
105
|
|
|
106
|
+
if self.use_cache and self.cache.get("candidatures", None) is not None:
|
|
107
|
+
self.candidatures = self.cache["candidatures"]
|
|
108
|
+
return self.candidatures
|
|
109
|
+
|
|
85
110
|
candidatures = self.s.get(f"{self.base_url}recrutements/offre-poste/candidature/candidatures/examen/{self.numposte}", params={"page": "0", "limite": "200", "filtres": "()"}, headers=self.headers, cookies=self.cookies)
|
|
86
111
|
if candidatures.status_code != 200:
|
|
87
112
|
msg = f"Failed to get candidatures: {candidatures.status_code} - {candidatures.text}"
|
|
88
113
|
raise Exception(msg)
|
|
89
114
|
json_data = json.loads(candidatures.content)
|
|
90
115
|
self.candidatures = json_data["content"]
|
|
116
|
+
self.__saveToCache("candidatures", self.candidatures)
|
|
91
117
|
return self.candidatures
|
|
92
118
|
|
|
93
119
|
def get_committee_members(self):
|
|
@@ -107,12 +133,18 @@ class Odyssee(object):
|
|
|
107
133
|
"numeroRapporteur":
|
|
108
134
|
}
|
|
109
135
|
"""
|
|
136
|
+
|
|
137
|
+
if self.use_cache and self.cache.get("rapporteurs", None) is not None:
|
|
138
|
+
self.rapporteurs = self.cache["rapporteurs"]
|
|
139
|
+
return self.rapporteurs
|
|
140
|
+
|
|
110
141
|
rapporteurs = self.s.get(f"{self.base_url}recrutements/offre-jury/chercher-rapporteurs/{self.numposte}", params={"page": "0", "limite": "50"}, headers=self.headers, cookies=self.cookies)
|
|
111
142
|
if rapporteurs.status_code != 200:
|
|
112
143
|
msg = f"Failed to get rapporteurs: {rapporteurs.status_code} - {rapporteurs.text}"
|
|
113
144
|
raise Exception(msg)
|
|
114
145
|
json_data = json.loads(rapporteurs.content)
|
|
115
146
|
self.rapporteurs = json_data["content"]
|
|
147
|
+
self.__saveToCache("rapporteurs", self.rapporteurs)
|
|
116
148
|
return self.rapporteurs
|
|
117
149
|
|
|
118
150
|
def get_institutions(self):
|
|
@@ -161,11 +193,17 @@ class Odyssee(object):
|
|
|
161
193
|
"description":
|
|
162
194
|
}
|
|
163
195
|
"""
|
|
196
|
+
|
|
197
|
+
if self.use_cache and self.cache.get("etablissements", None) is not None:
|
|
198
|
+
self.etablissements = self.cache["etablissements"]
|
|
199
|
+
return self.etablissements
|
|
200
|
+
|
|
164
201
|
etablissements = self.s.get(f"{self.base_url}referentiels/etablissements", headers=self.headers, cookies=self.cookies)
|
|
165
202
|
if etablissements.status_code != 200:
|
|
166
203
|
msg = f"Failed to get etablissements: {etablissements.status_code} - {etablissements.text}"
|
|
167
204
|
raise Exception(msg)
|
|
168
205
|
self.etablissements = json.loads(etablissements.content)
|
|
206
|
+
self.__saveToCache("etablissements", self.etablissements)
|
|
169
207
|
return self.etablissements
|
|
170
208
|
|
|
171
209
|
def get_keywords(self):
|
|
@@ -178,13 +216,47 @@ class Odyssee(object):
|
|
|
178
216
|
"supprimable":
|
|
179
217
|
}
|
|
180
218
|
"""
|
|
219
|
+
|
|
220
|
+
if self.use_cache and self.cache.get("keywords", None) is not None:
|
|
221
|
+
self.keywords = self.cache["keywords"]
|
|
222
|
+
return self.keywords
|
|
223
|
+
|
|
181
224
|
keywords = self.s.get(f"{self.base_url}referentiels/mots-cles", headers=self.headers, cookies=self.cookies)
|
|
182
225
|
if keywords.status_code != 200:
|
|
183
226
|
msg = f"Failed to get mots clés: {keywords.status_code} - {keywords.text}"
|
|
184
227
|
raise Exception(msg)
|
|
185
228
|
self.keywords = json.loads(keywords.content)
|
|
229
|
+
self.__saveToCache("keywords", self.keywords)
|
|
186
230
|
return self.keywords
|
|
187
231
|
|
|
232
|
+
def download_applications(self, path):
|
|
233
|
+
"""Download applications for a given numposte and save them in the specified path."""
|
|
234
|
+
self.__createDir(path)
|
|
235
|
+
|
|
236
|
+
if self.candidatures is None:
|
|
237
|
+
self.get_candidates()
|
|
238
|
+
|
|
239
|
+
for c in tqdm.tqdm(self.candidatures, desc="Téléchargement des dossiers des candidatures"):
|
|
240
|
+
id_candidat = c["candidat"]["idKeycloakActuel"]
|
|
241
|
+
|
|
242
|
+
response = self.s.get(f"{self.base_url}recrutements/offre-poste/candidature/telecharger-dossier-candidature/{self.numposte}/{id_candidat}", headers=self.headers, cookies=self.cookies)
|
|
243
|
+
|
|
244
|
+
if response.status_code == 200:
|
|
245
|
+
chemin = response.content
|
|
246
|
+
fileName = f"{path}/{c['candidat']['nomUsage'].upper()}_{c['candidat']['prenom'].capitalize()}_{id_candidat}.zip"
|
|
247
|
+
|
|
248
|
+
response2 = self.s.get(f"{self.base_url}s3/fichier", params={"chemin": chemin}, headers=self.headers, cookies=self.cookies)
|
|
249
|
+
|
|
250
|
+
if response2.status_code == 200:
|
|
251
|
+
with open(fileName, "wb") as f:
|
|
252
|
+
f.write(response2.content)
|
|
253
|
+
else:
|
|
254
|
+
msg = f"Failed to download application for candidate {id_candidat}: {response2.status_code} - {response2.text}"
|
|
255
|
+
raise Exception(msg)
|
|
256
|
+
else:
|
|
257
|
+
msg = f"Failed to download application information for candidate {id_candidat}: {response.status_code} - {response.text}"
|
|
258
|
+
raise Exception(msg)
|
|
259
|
+
|
|
188
260
|
def __detailCandidature(self, id_candidat):
|
|
189
261
|
candidature = self.s.get(f"{self.base_url}recrutements/offre-poste/candidature/detail-candidature/{self.numposte}/{id_candidat}", headers=self.headers, cookies=self.cookies)
|
|
190
262
|
if candidature.status_code != 200:
|
|
@@ -252,6 +324,11 @@ class Odyssee(object):
|
|
|
252
324
|
]
|
|
253
325
|
},
|
|
254
326
|
"""
|
|
327
|
+
|
|
328
|
+
if self.use_cache and self.cache.get("detailCandidatures", None) is not None:
|
|
329
|
+
self.detailCandidatures = self.cache["detailCandidatures"]
|
|
330
|
+
return self.detailCandidatures
|
|
331
|
+
|
|
255
332
|
if self.candidatures is None:
|
|
256
333
|
self.get_candidates()
|
|
257
334
|
|
|
@@ -259,6 +336,7 @@ class Odyssee(object):
|
|
|
259
336
|
for c in tqdm.tqdm(self.candidatures, desc="Récupération des détails des candidatures"):
|
|
260
337
|
id_candidat = c["candidat"]["idKeycloakActuel"]
|
|
261
338
|
self.detailCandidatures.append(self.__detailCandidature(id_candidat))
|
|
339
|
+
self.__saveToCache("detailCandidatures", self.detailCandidatures)
|
|
262
340
|
return self.detailCandidatures
|
|
263
341
|
|
|
264
342
|
def assign_jury_members_to_candidate(self, id_candidat, id_rapporteur1, id_rapporteur2):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: odysseeapi
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Unofficial Python API for Odyssee
|
|
5
5
|
Author-email: Géry Casiez <gery.casiez@univ-lille.fr>
|
|
6
6
|
Project-URL: Repository, https://github.com/casiez/OdysseeAPI
|
|
@@ -8,18 +8,22 @@ Classifier: Programming Language :: Python :: 3
|
|
|
8
8
|
Classifier: License :: OSI Approved :: BSD License
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
|
|
11
|
+
[](https://pypi.org/project/odysseeapi/)
|
|
12
|
+
[](https://pepy.tech/project/odysseeapi)
|
|
13
|
+
|
|
11
14
|
# Odyssee API
|
|
12
15
|
|
|
13
16
|
Provides an unofficial API for the [Odyssee platform](https://odyssee.enseignementsup-recherche.gouv.fr/), allowing users to access and interact with their data programmatically.
|
|
14
17
|
|
|
15
18
|
## Features
|
|
16
19
|
|
|
20
|
+
- download applications of candidates
|
|
17
21
|
- get information about candidates
|
|
18
22
|
- get information about committee members
|
|
19
23
|
- get information about institutions
|
|
20
24
|
- get keywords
|
|
21
25
|
- assign applications to committee members
|
|
22
|
-
-
|
|
26
|
+
- download reports from committee members
|
|
23
27
|
- provide decision on each candidate after the first round of evaluation
|
|
24
28
|
|
|
25
29
|
## Installation
|
|
@@ -52,6 +56,14 @@ from odysseeapi.Odyssee import Odyssee
|
|
|
52
56
|
|
|
53
57
|
numposte = "123456"
|
|
54
58
|
token = """eyJhbGciOiJSUzI1N... (token value) ..."""
|
|
59
|
+
|
|
60
|
+
# Initialize the API client with the numposte, token and use_cache set to True
|
|
61
|
+
# setting use_cache to False forces the API client to fetch fresh data from the server for each request, while setting it to True allows the client to use cached data if available
|
|
62
|
+
odyssee = Odyssee(numposte, token, True)
|
|
63
|
+
|
|
64
|
+
# Download the applications of the candidates in the specified directory
|
|
65
|
+
odyssee.download_applications('dossiers_candidats')
|
|
66
|
+
|
|
55
67
|
candidates = odyssee.get_candidates()
|
|
56
68
|
print(candidates)
|
|
57
69
|
|
|
@@ -70,7 +82,7 @@ print(candidates_with_details)
|
|
|
70
82
|
# odyssee.assign_jury_members_to_candidate("f1e2d3c4-b5a6-4789-9876-543210fedcba", "98765432-10fe-dcba-9876-543210fedcba", "abcd1234-5678-90ef-ghij-klmnopqrstuv")
|
|
71
83
|
|
|
72
84
|
# Download the reports of the committee members for the candidates in the specified directory
|
|
73
|
-
odyssee.downloadReports("
|
|
85
|
+
odyssee.downloadReports("rapports_odyssee")
|
|
74
86
|
|
|
75
87
|
# A l'issue de la première réunion du jury, enregistrer l'avis pour chaque candidat et les résultats du vote
|
|
76
88
|
# odyssee.opinion_for_interview("f1e2d3c4-b5a6-4789-9876-543210fedcba", "A", "Motif audition", 16, 16, 0, 0, 16, 0)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|