A comprehensive Python client for the EcoleDirecte API with MFA support.
Project description
ecoledirecte-py-client
A comprehensive Python client library for the EcoleDirecte API, providing easy access to student data, grades, homework, schedules, and more. Built with async/await support and robust Multi-Factor Authentication (MFA) handling.
Features
- ๐ Dual Account Support: Seamlessly handles both Student and Family (Parent) accounts
- ๐ก๏ธ MFA/CNED Support: Integrated handling of Multi-Factor Authentication challenges
- ๐ค Smart MFA: Automatically caches and reuses known MFA answers for frictionless future logins
- โก Async/Await: Built on modern async Python with
httpxfor efficient API calls - ๐ Secure by Default: Credential management via environment variables
- ๐ฆ Zero Configuration: Works out of the box with minimal setup
- ๐ฏ Type Hints: Full type annotations for better IDE support and code quality
- โ Well Tested: Comprehensive test suite with pytest
Installation
Install from PyPI using pip:
pip install ecoledirecte-py-client
Or using uv (recommended):
uv add ecoledirecte-py-client
Quick Start
Basic Usage (Student Account)
import asyncio
from ecoledirecte_py_client import Client
async def main():
# Create client and login
client = Client()
session = await client.login("username", "password")
# Fetch student data
grades = await session.get_grades()
homework = await session.get_homework()
messages = await session.get_messages()
print(f"Retrieved {len(grades)} grades")
# Always close the client
await client.close()
if __name__ == "__main__":
asyncio.run(main())
Family Account with Multiple Students
from ecoledirecte_py_client import Client, Family
async def main():
client = Client()
session = await client.login("parent_username", "parent_password")
# Check if it's a family account
if isinstance(session, Family):
print(f"Found {len(session.students)} students")
# Access each student
for student in session.students:
print(f"\n--- Data for {student.name} ---")
grades = await student.get_grades()
homework = await student.get_homework()
print(f"Grades: {len(grades)}")
await client.close()
asyncio.run(main())
Handling MFA Challenges
The recommended way to handle MFA is using the mfa_callback parameter:
import asyncio
from ecoledirecte_py_client import Client
def mfa_callback(question: str, choices: list[str]) -> str:
"""Interactive MFA callback."""
print(f"MFA Required: {question}")
for idx, choice in enumerate(choices):
print(f" {idx}: {choice}")
selection = int(input("Select option: "))
return choices[selection]
async def main():
# Pass the callback to handle MFA automatically
client = Client(mfa_callback=mfa_callback)
session = await client.login("username", "password")
print("Login successful!")
await client.close()
asyncio.run(main())
Alternatively, you can use the built-in console callback:
from ecoledirecte_py_client import Client, default_console_callback
client = Client(mfa_callback=default_console_callback)
Or handle MFA manually with try/except:
from ecoledirecte_py_client import Client, MFARequiredError
async def main():
client = Client()
try:
session = await client.login("username", "password")
except MFARequiredError as e:
print(f"MFA Required: {e.question}")
for idx, option in enumerate(e.propositions):
print(f" {idx}: {option}")
choice = int(input("Select option: "))
answer = e.propositions[choice]
session = await client.submit_mfa(answer)
await client.close()
asyncio.run(main())
Documentation
- API Reference - Complete API documentation for all classes and methods
- Usage Guide - Advanced usage patterns and best practices
- MFA Handling - Detailed guide on handling Multi-Factor Authentication
- Troubleshooting - Common issues and solutions
- Contributing - Guide for contributors
Configuration
Client Options
The Client constructor accepts the following optional parameters:
from ecoledirecte_py_client import Client
client = Client(
device_file="device.json", # Path to device token cache (None to disable)
qcm_file="qcm.json", # Path to MFA answer cache (None to disable)
mfa_callback=my_callback, # Callback for interactive MFA (see below)
)
Environment Variables
Create a .env file in your project root:
ECOLEDIRECTE_USERNAME=your_username
ECOLEDIRECTE_PASSWORD=your_password
Then load it in your application:
from dotenv import load_dotenv
import os
load_dotenv()
username = os.getenv("ECOLEDIRECTE_USERNAME")
password = os.getenv("ECOLEDIRECTE_PASSWORD")
MFA Configuration
The library automatically manages MFA answers in a qcm.json file. When you successfully answer an MFA challenge, it's cached for future logins:
{
"Quelle est votre ville de rรฉsidence ?": ["PARIS"],
"Quel est le niveau scolaire de <prรฉnom> ?": ["QUATRIEMES"]
}
Device tokens are cached in device.json to avoid repeated MFA challenges on trusted devices.
See docs/mfa.md for detailed MFA handling strategies.
Available Methods
Student Class
# Retrieve grades (all or by quarter)
grades = await student.get_grades()
grades_q1 = await student.get_grades(quarter=1)
# Get homework assignments
homework = await student.get_homework()
homework_sorted = await student.get_homework(sort_by_due_date=True)
# Fetch schedule for date range
schedule = await student.get_schedule("2024-01-01", "2024-01-31")
schedule = await student.get_schedule("2024-01-01", "2024-01-31", sort_by_date=False)
# Access messages
messages = await student.get_messages() # received by default
messages = await student.get_messages(message_type="sent")
messages = await student.get_messages(message_type="all")
Family Class
# Access list of students
for student in family.students:
print(student.name, student.id)
# Each student has the same methods as Student class
grades = await family.students[0].get_grades()
Examples
Check the examples/ directory for complete, runnable examples:
# Run the demo with your credentials
uv run --env-file .env examples/demo.py
Project Structure
ecoledirecte-py-client/
โโโ src/ecoledirecte_py_client/ # Core library code
โ โโโ client.py # Main Client class
โ โโโ student.py # Student account methods
โ โโโ family.py # Family account methods
โ โโโ mfa.py # MFA handling utilities
โ โโโ exceptions.py # Custom exceptions
โ โโโ models/ # Pydantic models
โ โ โโโ auth.py
โ โ โโโ grades.py
โ โ โโโ homework.py
โ โ โโโ messages.py
โ โ โโโ schedule.py
โ โโโ managers/ # API managers
โ โโโ grades_manager.py
โ โโโ homework_manager.py
โ โโโ messages_manager.py
โ โโโ schedule_manager.py
โโโ examples/ # Usage examples
โ โโโ demo.py # Complete demo script
โโโ tests/ # Test suite
โโโ docs/ # Documentation
โโโ qcm.json.example # Example MFA cache file
Development
Setting Up Development Environment
# Clone the repository
git clone https://github.com/ngombert/ecoledirecte-py-client.git
cd ecoledirecte-py-client
# Install dependencies with uv
uv sync
# Run tests
uv run pytest
# Run tests with coverage
uv run pytest --cov=src/ecoledirecte_py_client
See docs/contributing.md for detailed contribution guidelines.
Important Notes
- Rate Limiting: Be respectful of the EcoleDirecte API. Avoid excessive requests.
- Credentials Security: Never commit
.envfiles orqcm.jsonwith real data to version control. - MFA Answers: The
qcm.jsonfile contains answers specific to your account. Keep it private. - Unofficial API: This library uses an unofficial API that may change without notice.
License
This project is licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later). See the LICENSE file for details.
Contributing
Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Acknowledgments
This library is inspired by and references other EcoleDirecte API implementations. Special thanks to the EcoleDirecte community for reverse-engineering efforts.
Disclaimer: This is an unofficial client library and is not affiliated with or endorsed by EcoleDirecte. Use at your own risk.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ecoledirecte_py_client-0.2.1.tar.gz.
File metadata
- Download URL: ecoledirecte_py_client-0.2.1.tar.gz
- Upload date:
- Size: 104.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2eab44279c9eaea2c7be85e52561cd91906c2de6aabd49638f786b673c1d6eeb
|
|
| MD5 |
785318dbed3615252fb28a524c37f566
|
|
| BLAKE2b-256 |
6e91d2cf54d0e135bcef7d7d343fb5f18e7349eb8ea9d3b528b168bcf01cdad8
|
File details
Details for the file ecoledirecte_py_client-0.2.1-py3-none-any.whl.
File metadata
- Download URL: ecoledirecte_py_client-0.2.1-py3-none-any.whl
- Upload date:
- Size: 41.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
984695996b9597696fc83f0a91accc100ad0d2d9675386a1e7cc634596ef69d2
|
|
| MD5 |
4c57f25c61026c8ff9dc268ba922fbc8
|
|
| BLAKE2b-256 |
99c41c885d8a736075b17177684017fb653f773ee1aca79c0604eed9c135ede6
|