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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: odysseeapi
3
- Version: 0.0.1
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
+ [![PyPI Version](https://img.shields.io/pypi/v/odysseeapi)](https://pypi.org/project/odysseeapi/)
12
+ [![Downloads](https://static.pepy.tech/badge/odysseeapi)](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
- - get reports from committee members
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("rapportsOdyssee")
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
+ [![PyPI Version](https://img.shields.io/pypi/v/odysseeapi)](https://pypi.org/project/odysseeapi/)
2
+ [![Downloads](https://static.pepy.tech/badge/odysseeapi)](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
- - get reports from committee members
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("rapportsOdyssee")
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.1
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
+ [![PyPI Version](https://img.shields.io/pypi/v/odysseeapi)](https://pypi.org/project/odysseeapi/)
12
+ [![Downloads](https://static.pepy.tech/badge/odysseeapi)](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
- - get reports from committee members
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("rapportsOdyssee")
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)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "odysseeapi"
7
- version = "0.0.1"
7
+ version = "0.2.0"
8
8
  authors = [
9
9
  {name = "Géry Casiez", email = "gery.casiez@univ-lille.fr"},
10
10
  ]
File without changes