esprit-py 0.3.1__py3-none-any.whl → 0.3.3__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 esprit-py might be problematic. Click here for more details.
- esprit/auth.py +51 -0
- esprit/esprit.py +7 -4
- esprit/grade.py +38 -0
- {esprit_py-0.3.1.dist-info → esprit_py-0.3.3.dist-info}/METADATA +6 -43
- esprit_py-0.3.3.dist-info/RECORD +12 -0
- esprit_py-0.3.1.dist-info/RECORD +0 -12
- {esprit_py-0.3.1.dist-info → esprit_py-0.3.3.dist-info}/LICENSE +0 -0
- {esprit_py-0.3.1.dist-info → esprit_py-0.3.3.dist-info}/WHEEL +0 -0
- {esprit_py-0.3.1.dist-info → esprit_py-0.3.3.dist-info}/top_level.txt +0 -0
esprit/auth.py
CHANGED
|
@@ -6,7 +6,42 @@ from selenium.webdriver.chrome.options import Options
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class Auth:
|
|
9
|
+
"""
|
|
10
|
+
A class used to represent an Authentication process
|
|
11
|
+
|
|
12
|
+
...
|
|
13
|
+
|
|
14
|
+
Attributes
|
|
15
|
+
----------
|
|
16
|
+
login_url : str
|
|
17
|
+
a string representing the login URL
|
|
18
|
+
debug : bool
|
|
19
|
+
a boolean indicating if debug mode is on
|
|
20
|
+
driver : WebDriver
|
|
21
|
+
a WebDriver object to interact with the browser
|
|
22
|
+
|
|
23
|
+
Methods
|
|
24
|
+
-------
|
|
25
|
+
login(id, password)
|
|
26
|
+
Logs in to the website using the provided id and password
|
|
27
|
+
"""
|
|
28
|
+
|
|
9
29
|
def __init__(self, driver_path=None, driver=None, debug=False, headless=True):
|
|
30
|
+
"""
|
|
31
|
+
Constructs all the necessary attributes for the Auth object.
|
|
32
|
+
|
|
33
|
+
Parameters
|
|
34
|
+
----------
|
|
35
|
+
driver_path : str, optional
|
|
36
|
+
Path to the WebDriver executable (default is None)
|
|
37
|
+
driver : WebDriver, optional
|
|
38
|
+
Existing WebDriver instance (default is None)
|
|
39
|
+
debug : bool, optional
|
|
40
|
+
Debug mode flag (default is False)
|
|
41
|
+
headless : bool, optional
|
|
42
|
+
Headless mode flag for the browser (default is True)
|
|
43
|
+
"""
|
|
44
|
+
|
|
10
45
|
self.login_url = "https://esprit-tn.com/esponline/online/default.aspx"
|
|
11
46
|
self.debug = debug
|
|
12
47
|
|
|
@@ -19,6 +54,22 @@ class Auth:
|
|
|
19
54
|
executable_path=driver_path, options=chrome_options)
|
|
20
55
|
|
|
21
56
|
def login(self, id, password):
|
|
57
|
+
"""
|
|
58
|
+
Logs in to the website using the provided id and password.
|
|
59
|
+
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
id : str
|
|
63
|
+
User's id
|
|
64
|
+
password : str
|
|
65
|
+
User's password
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
list
|
|
70
|
+
List of cookies if login is successful, None otherwise
|
|
71
|
+
"""
|
|
72
|
+
|
|
22
73
|
self.driver.get(self.login_url)
|
|
23
74
|
|
|
24
75
|
# Fill in the ID
|
esprit/esprit.py
CHANGED
|
@@ -7,10 +7,9 @@ from .credit import Credit
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class Esprit:
|
|
10
|
-
def __init__(self):
|
|
10
|
+
def __init__(self, driver_path=None, driver=None, debug=False, headless=True):
|
|
11
11
|
self.session = requests.Session()
|
|
12
|
-
self.auth = Auth()
|
|
13
|
-
self.grade_scrape = Grade(self.session)
|
|
12
|
+
self.auth = Auth(driver_path, driver, debug, headless)
|
|
14
13
|
self.grade_scrape = Grade(self.session)
|
|
15
14
|
self.absence_scrape = Absence(self.session)
|
|
16
15
|
self.time_schedule_scrape = TimeSchedule(self.session)
|
|
@@ -18,11 +17,15 @@ class Esprit:
|
|
|
18
17
|
|
|
19
18
|
def login(self, username, password):
|
|
20
19
|
cookies = self.auth.login(username, password)
|
|
21
|
-
|
|
20
|
+
cookies_dict = {cookie['name']: cookie['value'] for cookie in cookies}
|
|
21
|
+
self.session.cookies.update(cookies_dict)
|
|
22
22
|
|
|
23
23
|
def get_grades(self):
|
|
24
24
|
return self.grade_scrape.get_grades()
|
|
25
25
|
|
|
26
|
+
def calculate_average(self, grades):
|
|
27
|
+
return self.grade_scrape.calculate_average(grades)
|
|
28
|
+
|
|
26
29
|
def get_absences(self):
|
|
27
30
|
return self.absence_scrape.get_absences()
|
|
28
31
|
|
esprit/grade.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import requests
|
|
2
2
|
from bs4 import BeautifulSoup
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import numpy as np
|
|
3
5
|
|
|
4
6
|
|
|
5
7
|
class Grade:
|
|
@@ -50,3 +52,39 @@ class Grade:
|
|
|
50
52
|
grades = [headers] + [[cell.text.strip() for cell in row.find_all('td')]
|
|
51
53
|
for row in rows[1:]] # Skip header row
|
|
52
54
|
return grades
|
|
55
|
+
|
|
56
|
+
def calculate_average(self, grades):
|
|
57
|
+
# Convert the list of lists to a DataFrame
|
|
58
|
+
df = pd.DataFrame(grades[1:], columns=grades[0])
|
|
59
|
+
|
|
60
|
+
# Replace empty strings with NaN
|
|
61
|
+
df.replace('', np.nan, inplace=True)
|
|
62
|
+
|
|
63
|
+
# Replace comma with dot and convert to float
|
|
64
|
+
for col in ['COEF', 'NOTE_CC', 'NOTE_TP', 'NOTE_EXAM']:
|
|
65
|
+
df[col] = df[col].str.replace(',', '.').astype(float)
|
|
66
|
+
|
|
67
|
+
# Calculate the average based on available grades
|
|
68
|
+
|
|
69
|
+
def calculate_average(row):
|
|
70
|
+
if pd.isna(row['NOTE_TP']):
|
|
71
|
+
if pd.isna(row['NOTE_CC']):
|
|
72
|
+
return row['NOTE_EXAM']
|
|
73
|
+
else:
|
|
74
|
+
return row['NOTE_EXAM'] * 0.6 + row['NOTE_CC'] * 0.4
|
|
75
|
+
elif pd.isna(row['NOTE_CC']):
|
|
76
|
+
return row['NOTE_EXAM'] * 0.8 + row['NOTE_TP'] * 0.2
|
|
77
|
+
else:
|
|
78
|
+
return row['NOTE_EXAM'] * 0.5 + row['NOTE_CC'] * 0.3 + row['NOTE_TP'] * 0.2
|
|
79
|
+
|
|
80
|
+
df['MOYENNE'] = df.apply(calculate_average, axis=1)
|
|
81
|
+
|
|
82
|
+
# Calculate the total average
|
|
83
|
+
total_average = (df['MOYENNE'] * df['COEF']).sum() / df['COEF'].sum()
|
|
84
|
+
|
|
85
|
+
# Append the total average to the DataFrame
|
|
86
|
+
df = df._append({'DESIGNATION': 'Moyenne', 'COEF': df['COEF'].sum(
|
|
87
|
+
), 'MOYENNE': total_average}, ignore_index=True)
|
|
88
|
+
|
|
89
|
+
print(df)
|
|
90
|
+
return total_average
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: esprit-py
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: A Python library for interacting with data from esprit-tn.com
|
|
5
5
|
Home-page: https://github.com/TheLime1/esprit.py
|
|
6
6
|
Author: Lime1 (Aymen Hmani)
|
|
@@ -17,92 +17,55 @@ Requires-Dist: requests
|
|
|
17
17
|
Requires-Dist: beautifulsoup4
|
|
18
18
|
Requires-Dist: PyPDF2
|
|
19
19
|
Requires-Dist: selenium
|
|
20
|
+
Requires-Dist: numpy
|
|
21
|
+
Requires-Dist: pandas
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
# <img src="https://esprit.tn/favicon.ico" width="28px" /> esprit-py
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
26
|
> [!NOTE]
|
|
27
|
-
|
|
28
27
|
> Please note that this library is not an official API provided by Esprit and is intended for educational and personal use only.
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
29
|
## Features
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
|
|
36
31
|
- Get your exact timetable pdf *not 300 pages pdf*
|
|
37
|
-
|
|
38
32
|
- Get your grades
|
|
39
|
-
|
|
40
33
|
- Get your absences
|
|
41
|
-
|
|
42
34
|
- Get your credits
|
|
43
35
|
|
|
44
|
-
|
|
45
|
-
|
|
46
36
|
## Installation
|
|
47
37
|
|
|
48
|
-
|
|
49
|
-
|
|
50
38
|
```bash
|
|
51
|
-
|
|
52
39
|
pip install esprit-py
|
|
53
|
-
|
|
54
40
|
```
|
|
55
41
|
|
|
56
|
-
|
|
42
|
+
download `chromedriver` from [here](https://googlechromelabs.github.io/chrome-for-testing/#stable)
|
|
57
43
|
|
|
58
44
|
## Example
|
|
59
45
|
|
|
60
|
-
|
|
61
|
-
|
|
62
46
|
```python
|
|
63
|
-
|
|
64
47
|
from esprit import Esprit
|
|
65
48
|
|
|
66
|
-
|
|
67
|
-
|
|
68
49
|
# Create an Esprit object
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
50
|
+
esprit = Esprit(
|
|
51
|
+
driver_path="C:/path/to/chromedriver.exe",)
|
|
73
52
|
|
|
74
53
|
# Replace with your actual ID and password
|
|
75
|
-
|
|
76
54
|
id = 'ID'
|
|
77
|
-
|
|
78
55
|
password = 'PASSWORD'
|
|
79
56
|
|
|
80
|
-
|
|
81
|
-
|
|
82
57
|
# Attempt to log in
|
|
83
|
-
|
|
84
58
|
if esprit.login(id, password):
|
|
85
|
-
|
|
86
59
|
print("Login successful.")
|
|
87
|
-
|
|
88
60
|
else:
|
|
89
|
-
|
|
90
61
|
print("Login failed.")
|
|
91
62
|
|
|
92
|
-
|
|
93
|
-
|
|
94
63
|
# Get absences
|
|
95
|
-
|
|
96
64
|
absences = esprit.get_absences()
|
|
97
|
-
|
|
98
65
|
if absences is not None:
|
|
99
|
-
|
|
100
66
|
for absence in absences:
|
|
101
|
-
|
|
102
67
|
print(absence)
|
|
103
|
-
|
|
104
68
|
else:
|
|
105
|
-
|
|
106
69
|
print("Failed to get absences.")
|
|
107
70
|
|
|
108
71
|
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
esprit/__init__.py,sha256=PnahGRQ5xmA26XMFaj9ImLty9OEmYwnBqLanvGXZwwU,28
|
|
2
|
+
esprit/absence.py,sha256=qOFyK0QmSaWYrz_2RlDFcCom-m6QZLJAzG1dBj3YkbI,1666
|
|
3
|
+
esprit/auth.py,sha256=-jkquqEGZ8I7K61T4QsXHLfDTIwdhbirOrtEmGysbqQ,4034
|
|
4
|
+
esprit/credit.py,sha256=iKy_lTR_iLAkpRkP92l2gAUi4Dh6JvLidxGhuM9YJ68,1747
|
|
5
|
+
esprit/esprit.py,sha256=xjXqkXIGgV5J0DGSwBIM-ihj7123SH7DASzHPL0Fzpg,1680
|
|
6
|
+
esprit/grade.py,sha256=ip30Aavx9mCdwIpziXLENLMaEmaIM6mkC3EXnT0041g,3098
|
|
7
|
+
esprit/time_schedule.py,sha256=sU2gwV9dmIyFhSe0qlxTGg05L7lhLbD0YN0qhMXdNc0,6490
|
|
8
|
+
esprit_py-0.3.3.dist-info/LICENSE,sha256=DOcn7qpE6TsUEcakIsDDKm757jx5YlQ8fXDiED21P_w,1089
|
|
9
|
+
esprit_py-0.3.3.dist-info/METADATA,sha256=TfDmCND5Di6lTJHWIf8-MaalKcTQ0veV3g1gbEaJPnM,1833
|
|
10
|
+
esprit_py-0.3.3.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
11
|
+
esprit_py-0.3.3.dist-info/top_level.txt,sha256=aS9besFTZ4EYTsoBJVf3GaMjQtJLgLaK7WqAxSvGVdQ,7
|
|
12
|
+
esprit_py-0.3.3.dist-info/RECORD,,
|
esprit_py-0.3.1.dist-info/RECORD
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
esprit/__init__.py,sha256=PnahGRQ5xmA26XMFaj9ImLty9OEmYwnBqLanvGXZwwU,28
|
|
2
|
-
esprit/absence.py,sha256=qOFyK0QmSaWYrz_2RlDFcCom-m6QZLJAzG1dBj3YkbI,1666
|
|
3
|
-
esprit/auth.py,sha256=Yyu0W4-vGafb9mwWknpYN_nzSbbRZhlly6ZyliZCErQ,2660
|
|
4
|
-
esprit/credit.py,sha256=iKy_lTR_iLAkpRkP92l2gAUi4Dh6JvLidxGhuM9YJ68,1747
|
|
5
|
-
esprit/esprit.py,sha256=mCnFVZUIDKlK2v4nv7I9tFM84-MHBsyyv51aXyc5T7w,1445
|
|
6
|
-
esprit/grade.py,sha256=EAgYvA-490Jj9TeUCIlSQeW4aVu2gcmfujNxDG-91Fw,1648
|
|
7
|
-
esprit/time_schedule.py,sha256=sU2gwV9dmIyFhSe0qlxTGg05L7lhLbD0YN0qhMXdNc0,6490
|
|
8
|
-
esprit_py-0.3.1.dist-info/LICENSE,sha256=DOcn7qpE6TsUEcakIsDDKm757jx5YlQ8fXDiED21P_w,1089
|
|
9
|
-
esprit_py-0.3.1.dist-info/METADATA,sha256=ayAQO4PiuQ-i2i5046vt74JqX5m9HrrH_2DALC3DhAM,1722
|
|
10
|
-
esprit_py-0.3.1.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
11
|
-
esprit_py-0.3.1.dist-info/top_level.txt,sha256=aS9besFTZ4EYTsoBJVf3GaMjQtJLgLaK7WqAxSvGVdQ,7
|
|
12
|
-
esprit_py-0.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|