Unofficial async Python API wrapper for Mashov
Project description
pymashov
Unofficial async Python API wrapper for Mashov - the Israeli education system's student and parent portal.
Features
- ✨ Async/await support - Built with modern Python async patterns using
httpx - 🔐 Secure authentication - Handles CSRF tokens and session management
- 📚 Comprehensive API coverage - Access grades, timetables, homework, behavior records, and more
- 🎯 Type hints - Full type annotation support for better IDE experience
- 🚀 Easy to use - Simple, intuitive interface with context manager support
Installation
From PyPI (Recommended)
pip install pymashov
From Source
git clone https://github.com/t0mer/pymashov.git
cd pymashov
pip install -e .
Requirements
- Python 3.8 or higher
- httpx >= 0.25
Quick Start
import asyncio
from mashov import MashovClient
async def main():
# Create a client instance
async with MashovClient(
username="YOUR_ID",
password="YOUR_PASSWORD",
semel="SCHOOL_CODE",
year="2026" # Optional, defaults to current year
) as client:
# Login is handled automatically
# Get student grades
student_id = "YOUR_STUDENT_ID"
grades = await client.get_grades(student_id)
print(f"Grades: {grades}")
asyncio.run(main())
Usage Examples
Manual Login
If you prefer to control when login happens:
import asyncio
from mashov import MashovClient
async def main():
client = MashovClient(
username="YOUR_ID",
password="YOUR_PASSWORD",
semel="SCHOOL_CODE",
auto_login=False # Disable automatic login
)
try:
# Manually login
session = await client.login()
print(f"Logged in successfully!")
print(f"CSRF Token: {session.csrf_header_token}")
# Now you can make API calls
student_id = "YOUR_STUDENT_ID"
grades = await client.get_grades(student_id)
print(grades)
finally:
await client.close()
asyncio.run(main())
Get Student Grades
async def get_student_grades(client, student_id):
"""Fetch and display student grades."""
grades = await client.get_grades(student_id)
for grade in grades:
print(f"Subject: {grade['subject']}")
print(f"Grade: {grade['grade']}")
print(f"Date: {grade['date']}")
print("---")
return grades
Get Weekly Timetable
async def get_weekly_schedule(client, student_id):
"""Fetch student's weekly timetable."""
timetable = await client.get_timetable(student_id)
for day in timetable:
print(f"Day: {day['day']}")
for lesson in day['lessons']:
print(f" {lesson['time']}: {lesson['subject']} - {lesson['teacher']}")
return timetable
Get Homework Assignments
async def get_pending_homework(client, student_id):
"""Fetch all homework assignments."""
homework = await client.get_homework(student_id)
for assignment in homework:
print(f"Subject: {assignment['subject']}")
print(f"Description: {assignment['description']}")
print(f"Due Date: {assignment['dueDate']}")
print("---")
return homework
Get Behavior Records
async def check_behavior(client, student_id):
"""Fetch behavior/discipline records."""
behavior = await client.get_behavior(student_id)
for record in behavior:
print(f"Date: {record['date']}")
print(f"Type: {record['type']}")
print(f"Description: {record['description']}")
print("---")
return behavior
Get Mail Conversations
async def get_recent_messages(client, count=10):
"""Fetch recent mail conversations."""
conversations = await client.get_conversations(skip=0, take=count)
for conv in conversations:
print(f"From: {conv['sender']}")
print(f"Subject: {conv['subject']}")
print(f"Date: {conv['date']}")
print("---")
return conversations
Get Available Schools
async def list_schools(client):
"""Fetch list of available schools (public endpoint)."""
schools = await client.get_schools()
for school in schools:
print(f"Name: {school['name']}")
print(f"Code (Semel): {school['semel']}")
print(f"City: {school['city']}")
print("---")
return schools
Complete Example - Daily Student Report
import asyncio
from mashov import MashovClient
async def generate_daily_report(username, password, semel, student_id):
"""Generate a comprehensive daily report for a student."""
async with MashovClient(username, password, semel) as client:
print("=" * 50)
print("DAILY STUDENT REPORT")
print("=" * 50)
# Get grades
print("\n📊 GRADES:")
grades = await client.get_grades(student_id)
for grade in grades[:5]: # Show last 5 grades
print(f" • {grade.get('subject', 'N/A')}: {grade.get('grade', 'N/A')}")
# Get today's timetable
print("\n📅 TODAY'S SCHEDULE:")
timetable = await client.get_timetable(student_id)
# Process and display timetable...
# Get pending homework
print("\n📝 PENDING HOMEWORK:")
homework = await client.get_homework(student_id)
for hw in homework[:5]: # Show next 5 assignments
print(f" • {hw.get('subject', 'N/A')}: {hw.get('description', 'N/A')}")
print(f" Due: {hw.get('dueDate', 'N/A')}")
# Get recent behavior records
print("\n⭐ RECENT BEHAVIOR:")
behavior = await client.get_behavior(student_id)
for record in behavior[:3]: # Show last 3 records
print(f" • {record.get('date', 'N/A')}: {record.get('description', 'N/A')}")
# Get recent messages
print("\n📧 RECENT MESSAGES:")
messages = await client.get_conversations(skip=0, take=3)
for msg in messages:
print(f" • From {msg.get('sender', 'N/A')}: {msg.get('subject', 'N/A')}")
print("\n" + "=" * 50)
# Run the report
asyncio.run(generate_daily_report(
username="YOUR_ID",
password="YOUR_PASSWORD",
semel="SCHOOL_CODE",
student_id="YOUR_STUDENT_ID"
))
Advanced: Custom API Requests
For endpoints not yet wrapped, use the low-level request() method:
async def custom_api_call(client):
"""Make custom API calls to any Mashov endpoint."""
# Authenticated request
response = await client.request(
"GET",
"/api/custom/endpoint",
params={"param1": "value1"}
)
data = response.json()
# Public request (no authentication)
response = await client.public_request(
"GET",
"/api/public/endpoint"
)
data = response.json()
return data
API Reference
MashovClient
Constructor Parameters:
username(str): User ID numberpassword(str): User passwordsemel(str): School codeyear(str, optional): Academic year (default: "2026")base_url(str, optional): API base URL (default: "https://web.mashov.info")timeout(float, optional): Request timeout in seconds (default: 20.0)auto_login(bool, optional): Auto-login on first request (default: True)
Methods:
async login() -> MashovSession
Manually login and obtain session credentials.
async close() -> None
Close the HTTP client session.
async get_grades(student_id: str) -> Any
Get student grades.
async get_timetable(student_id: str) -> Any
Get student's weekly timetable.
async get_homework(student_id: str) -> Any
Get homework assignments.
async get_behavior(student_id: str) -> Any
Get behavior/discipline records.
async get_conversations(skip: int = 0, take: int = 20) -> Any
Get mail conversations from inbox.
async get_schools() -> Any
Get list of available schools (public endpoint, no authentication required).
async request(method: str, path: str, **kwargs) -> httpx.Response
Low-level authenticated request method for custom API calls.
async public_request(method: str, path: str, **kwargs) -> httpx.Response
Low-level public request method (no authentication).
Error Handling
from mashov import MashovClient, MashovLoginError, MashovRequestError, MashovError
async def safe_api_call():
try:
async with MashovClient(username, password, semel) as client:
grades = await client.get_grades(student_id)
return grades
except MashovLoginError as e:
print(f"Login failed: {e}")
# Handle authentication errors
except MashovRequestError as e:
print(f"API request failed: {e}")
# Handle request errors
except MashovError as e:
print(f"Mashov error: {e}")
# Handle other Mashov-related errors
except Exception as e:
print(f"Unexpected error: {e}")
# Handle unexpected errors
Exception Classes
MashovError- Base exception for all pymashov errorsMashovLoginError- Raised when login fails or authentication is missingMashovRequestError- Raised when an API request fails
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Disclaimer
This is an unofficial API wrapper and is not affiliated with, endorsed by, or connected to Mashov or the Israeli Ministry of Education. Use at your own risk.
Author
Tomer Klein
- Email: tomer.klein@gmail.com
- GitHub: @t0mer
Acknowledgments
- Built with httpx for async HTTP requests
- Inspired by the need for programmatic access to student information
Changelog
0.0.1 (Initial Release)
- Basic authentication and session management
- Support for grades, timetable, homework, and behavior endpoints
- Mail conversations support
- Public schools endpoint
- Async/await support with httpx
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 pymashov-0.0.2.tar.gz.
File metadata
- Download URL: pymashov-0.0.2.tar.gz
- Upload date:
- Size: 15.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aaa2957edf7a7b455bb7e96167193483d403987db2507ad67ded7ecbbf773700
|
|
| MD5 |
fafe8438bbfdac77b3754e0974b003a3
|
|
| BLAKE2b-256 |
8b553055f9aa4a9fbd243875281e4065e3251dd494f1fe484af61717f1782831
|
File details
Details for the file pymashov-0.0.2-py3-none-any.whl.
File metadata
- Download URL: pymashov-0.0.2-py3-none-any.whl
- Upload date:
- Size: 12.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab7a2c07980920cc153284752fc8cede83276b69e48e8cc6747d4b706ce94668
|
|
| MD5 |
376c5631aa2643bda76a68ca48f26939
|
|
| BLAKE2b-256 |
75b4e158d92ef2d47c5bffad06be8fd152136fbc8f412882e01c1598d6c59690
|