wilhelmina 0.1.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 {{cookiecutter.github_user}}
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,152 @@
1
+ Metadata-Version: 2.1
2
+ Name: wilhelmina
3
+ Version: 0.1.0
4
+ Summary: API client for Wilma school portal
5
+ Home-page: https://github.com/frwickst/wilma
6
+ License: MIT
7
+ Author: Frank Wickström
8
+ Author-email: frwickst@gmail.com
9
+ Requires-Python: >=3.13,<4.0
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Provides-Extra: playwright
13
+ Requires-Dist: aiohttp (>=3.11.16,<4.0.0)
14
+ Requires-Dist: beautifulsoup4 (>=4.13.4,<5.0.0)
15
+ Requires-Dist: html2text (>=2025.4.15,<2026.0.0)
16
+ Requires-Dist: mashumaro (>=3.15,<4.0)
17
+ Requires-Dist: playwright (>=1.51.0,<2.0.0) ; extra == "playwright"
18
+ Project-URL: Repository, https://github.com/frwickst/wilma
19
+ Description-Content-Type: text/markdown
20
+
21
+ # Wilhelmina - Wilma API Client
22
+
23
+ A Python API client for the Wilma school platform. This client allows you to authenticate, fetch messages, and view message contents from the Wilma platform.
24
+
25
+ Why is this not called Wilma? The reason is simple, PyPi sees "Wilma" as a prohibited packages name. It
26
+ is not taken on PyPi, it just is not allowed. Wilhelmina is the long/full version of the name Wilma which
27
+ is the reason for the name.
28
+
29
+ ## Wilma API Features
30
+
31
+ - [X] Messages
32
+ - [X] List (API)
33
+ - [X] Get single (API)
34
+ - [X] Get unread (Scraping w/ Playwright)\*
35
+
36
+
37
+ \* There _is_ an API that returns the `status` of a message (0=read, 1=unread) but this is not enabled on all instances, specifically not on the Turku instance that I was interested in.
38
+
39
+ ## Home Assistant compatibility
40
+
41
+ This library has support for passing in an existing `aiohttp` to allow for easier integration with
42
+ Home Assistant. The version of `aiohttp` has also been slightly restricted in order to be installable
43
+ in Home Assistant. `mashumaro` was chosen for type safe models instead of Pydantic to not need to
44
+ go through the v1 vs. v2 hassle.
45
+
46
+ ## Features
47
+
48
+ - Asynchronous API using `aiohttp`
49
+ - Type-safe models using `mashumaro`
50
+ - Optional unread message detection using Playwright for JavaScript rendering
51
+ - Graceful fallback when Playwright is not installed (messages won't be marked as unread)
52
+ - Comprehensive test suite
53
+
54
+ ## Note about AI
55
+
56
+ Sonnet 3.7 has written a lot code in this repository. Far from one-shotted however and a lot of
57
+ refactoring has been done in order to get things into this state. The main purpose for creating
58
+ this library was to get quick access to the Wilma API through Python.
59
+
60
+ ## Installation
61
+
62
+ ```bash
63
+ # Basic installation
64
+ pip install wilma
65
+
66
+ # (Optional) Installation with Playwright support (for unread message detection)
67
+ pip install wilma[playwright]
68
+
69
+ # Playwright browser will be installed automatically on import
70
+
71
+ # Using Poetry
72
+ poetry add wilma -E playwright
73
+ ```
74
+
75
+ ## API Client Usage
76
+
77
+ ```python
78
+ import asyncio
79
+ from wilma import WilmaClient
80
+
81
+ async def main():
82
+ # Initialize client with an optional existing aiohttp session
83
+ # Use headless=False to see the browser
84
+ session = aiohttp.ClientSession() # Optional - provide your own session
85
+
86
+ async with WilmaClient("https://turku.inschool.fi", session=session, headless=True) as client:
87
+ # Login
88
+ await client.login("username", "password")
89
+
90
+ # Get messages
91
+ messages = await client.get_messages()
92
+
93
+ # Print messages
94
+ for msg in messages:
95
+ # Show unread status
96
+ unread_status = "UNREAD" if msg.unread else "read"
97
+ print(f"{msg.id}: {msg.subject} - {msg.timestamp} - {msg.sender} - {unread_status}")
98
+
99
+ # Get message content
100
+ content = await client.get_message_content(msg.id)
101
+ print(f"Content: {content.content[:100]}...")
102
+
103
+ # Run the main function
104
+ asyncio.run(main())
105
+ ```
106
+
107
+ ## Development
108
+
109
+ ### Setup
110
+
111
+ ```bash
112
+ # Clone the repository
113
+ git clone https://github.com/yourusername/wilma.git
114
+ cd wilma
115
+
116
+ # Install development dependencies
117
+ poetry install
118
+
119
+ # Install Playwright browser
120
+ poetry run playwright install chromium
121
+ ```
122
+
123
+ ### Running Tests
124
+
125
+ ```bash
126
+ # Run all tests
127
+ poetry run pytest
128
+
129
+ # Run specific tests
130
+ poetry run pytest wilma/tests/test_client.py
131
+
132
+ # Run with coverage
133
+ poetry run pytest --cov=wilma
134
+ ```
135
+
136
+ ### Linting and Type Checking
137
+
138
+ ```bash
139
+ # Format with ruff
140
+ poetry run ruff format wilma
141
+
142
+ # Run ruff for linting
143
+ poetry run ruff check wilma --fix
144
+
145
+ # Run mypy for type checking
146
+ poetry run mypy wilma
147
+ ```
148
+
149
+ ## License
150
+
151
+ MIT
152
+
@@ -0,0 +1,131 @@
1
+ # Wilhelmina - Wilma API Client
2
+
3
+ A Python API client for the Wilma school platform. This client allows you to authenticate, fetch messages, and view message contents from the Wilma platform.
4
+
5
+ Why is this not called Wilma? The reason is simple, PyPi sees "Wilma" as a prohibited packages name. It
6
+ is not taken on PyPi, it just is not allowed. Wilhelmina is the long/full version of the name Wilma which
7
+ is the reason for the name.
8
+
9
+ ## Wilma API Features
10
+
11
+ - [X] Messages
12
+ - [X] List (API)
13
+ - [X] Get single (API)
14
+ - [X] Get unread (Scraping w/ Playwright)\*
15
+
16
+
17
+ \* There _is_ an API that returns the `status` of a message (0=read, 1=unread) but this is not enabled on all instances, specifically not on the Turku instance that I was interested in.
18
+
19
+ ## Home Assistant compatibility
20
+
21
+ This library has support for passing in an existing `aiohttp` to allow for easier integration with
22
+ Home Assistant. The version of `aiohttp` has also been slightly restricted in order to be installable
23
+ in Home Assistant. `mashumaro` was chosen for type safe models instead of Pydantic to not need to
24
+ go through the v1 vs. v2 hassle.
25
+
26
+ ## Features
27
+
28
+ - Asynchronous API using `aiohttp`
29
+ - Type-safe models using `mashumaro`
30
+ - Optional unread message detection using Playwright for JavaScript rendering
31
+ - Graceful fallback when Playwright is not installed (messages won't be marked as unread)
32
+ - Comprehensive test suite
33
+
34
+ ## Note about AI
35
+
36
+ Sonnet 3.7 has written a lot code in this repository. Far from one-shotted however and a lot of
37
+ refactoring has been done in order to get things into this state. The main purpose for creating
38
+ this library was to get quick access to the Wilma API through Python.
39
+
40
+ ## Installation
41
+
42
+ ```bash
43
+ # Basic installation
44
+ pip install wilma
45
+
46
+ # (Optional) Installation with Playwright support (for unread message detection)
47
+ pip install wilma[playwright]
48
+
49
+ # Playwright browser will be installed automatically on import
50
+
51
+ # Using Poetry
52
+ poetry add wilma -E playwright
53
+ ```
54
+
55
+ ## API Client Usage
56
+
57
+ ```python
58
+ import asyncio
59
+ from wilma import WilmaClient
60
+
61
+ async def main():
62
+ # Initialize client with an optional existing aiohttp session
63
+ # Use headless=False to see the browser
64
+ session = aiohttp.ClientSession() # Optional - provide your own session
65
+
66
+ async with WilmaClient("https://turku.inschool.fi", session=session, headless=True) as client:
67
+ # Login
68
+ await client.login("username", "password")
69
+
70
+ # Get messages
71
+ messages = await client.get_messages()
72
+
73
+ # Print messages
74
+ for msg in messages:
75
+ # Show unread status
76
+ unread_status = "UNREAD" if msg.unread else "read"
77
+ print(f"{msg.id}: {msg.subject} - {msg.timestamp} - {msg.sender} - {unread_status}")
78
+
79
+ # Get message content
80
+ content = await client.get_message_content(msg.id)
81
+ print(f"Content: {content.content[:100]}...")
82
+
83
+ # Run the main function
84
+ asyncio.run(main())
85
+ ```
86
+
87
+ ## Development
88
+
89
+ ### Setup
90
+
91
+ ```bash
92
+ # Clone the repository
93
+ git clone https://github.com/yourusername/wilma.git
94
+ cd wilma
95
+
96
+ # Install development dependencies
97
+ poetry install
98
+
99
+ # Install Playwright browser
100
+ poetry run playwright install chromium
101
+ ```
102
+
103
+ ### Running Tests
104
+
105
+ ```bash
106
+ # Run all tests
107
+ poetry run pytest
108
+
109
+ # Run specific tests
110
+ poetry run pytest wilma/tests/test_client.py
111
+
112
+ # Run with coverage
113
+ poetry run pytest --cov=wilma
114
+ ```
115
+
116
+ ### Linting and Type Checking
117
+
118
+ ```bash
119
+ # Format with ruff
120
+ poetry run ruff format wilma
121
+
122
+ # Run ruff for linting
123
+ poetry run ruff check wilma --fix
124
+
125
+ # Run mypy for type checking
126
+ poetry run mypy wilma
127
+ ```
128
+
129
+ ## License
130
+
131
+ MIT
@@ -0,0 +1,61 @@
1
+ [tool.poetry]
2
+ name = "wilhelmina"
3
+ version = "0.1.0"
4
+ description = "API client for Wilma school portal"
5
+ authors = ["Frank Wickström <frwickst@gmail.com>"]
6
+ repository = "https://github.com/frwickst/wilma"
7
+ readme = "README.md"
8
+ license = "MIT"
9
+
10
+ [tool.poetry.dependencies]
11
+ python = "^3.13"
12
+ aiohttp = "^3.11.16"
13
+ mashumaro = "^3.15"
14
+ html2text = "^2025.4.15"
15
+ beautifulsoup4 = "^4.13.4"
16
+ playwright = {version = "^1.51.0", optional = true}
17
+
18
+ [tool.poetry.extras]
19
+ playwright = ["playwright"]
20
+
21
+ [tool.poetry.scripts]
22
+ wilma-install-deps = "wilma:install_playwright_deps"
23
+
24
+ [tool.poetry.group.dev.dependencies]
25
+ pytest = "^8.3.5"
26
+ pytest-asyncio = "^0.26.0"
27
+ pytest-cov = "^6.1.1"
28
+ mypy = "^1.15.0"
29
+ ruff = "^0.11.6"
30
+ types-beautifulsoup4 = "^4.12.0.20250204"
31
+
32
+ [build-system]
33
+ requires = ["poetry-core"]
34
+ build-backend = "poetry.core.masonry.api"
35
+
36
+ [tool.ruff]
37
+ line-length = 100
38
+ target-version = "py313"
39
+ src = ["wilma"]
40
+ lint.select = ["E", "F", "I"]
41
+
42
+ [tool.mypy]
43
+ python_version = "3.13"
44
+ strict = true
45
+ warn_unused_ignores = true
46
+ warn_return_any = true
47
+ warn_unreachable = true
48
+ disallow_any_generics = true
49
+ disallow_untyped_defs = true
50
+ check_untyped_defs = true
51
+
52
+ [[tool.mypy.overrides]]
53
+ module = "wilma.tests.*"
54
+ ignore_errors = true
55
+
56
+ [[tool.mypy.overrides]]
57
+ module = "playwright.*"
58
+ ignore_missing_imports = true
59
+
60
+ [tool.pytest.ini_options]
61
+ asyncio_default_fixture_loop_scope = "function"
@@ -0,0 +1,65 @@
1
+ """Wilma API client."""
2
+
3
+ import importlib.util
4
+ import logging
5
+ import subprocess
6
+ import sys
7
+
8
+ from wilma.client import AuthenticationError, WilmaClient, WilmaError
9
+ from wilma.models import Message, MessagesList, Sender
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ __all__ = [
14
+ "WilmaClient",
15
+ "WilmaError",
16
+ "AuthenticationError",
17
+ "Message",
18
+ "MessagesList",
19
+ "Sender",
20
+ "install_playwright_deps",
21
+ ]
22
+
23
+
24
+ def install_playwright_deps(force: bool = False, quiet: bool = False) -> bool:
25
+ """Install Playwright dependencies.
26
+
27
+ Args:
28
+ force: Force installation even if playwright is not installed
29
+ quiet: Don't log anything
30
+
31
+ Returns:
32
+ True if installed, False if skipped or failed
33
+ """
34
+ if not force:
35
+ # Check if playwright is installed
36
+ if importlib.util.find_spec("playwright") is None:
37
+ if not quiet:
38
+ logger.warning(
39
+ "Playwright is not installed. Install with 'pip install wilma[playwright]'"
40
+ )
41
+ return False
42
+
43
+ log_level = logging.ERROR if quiet else logging.INFO
44
+ logger.setLevel(log_level)
45
+
46
+ try:
47
+ logger.info("Installing Playwright dependencies...")
48
+ subprocess.run(
49
+ [sys.executable, "-m", "playwright", "install", "chromium"],
50
+ check=True,
51
+ capture_output=quiet,
52
+ )
53
+ logger.info("Playwright dependencies installed successfully.")
54
+ return True
55
+ except (subprocess.SubprocessError, FileNotFoundError) as e:
56
+ logger.error(f"Failed to install Playwright dependencies: {e}")
57
+ return False
58
+
59
+
60
+ # Auto-install Playwright browser when package is installed with the extra
61
+ if importlib.util.find_spec("playwright") is not None:
62
+ # Only attempt installation during import if playwright is available
63
+ # This ensures the browser is installed automatically when the package
64
+ # is installed with the playwright extra
65
+ install_playwright_deps(quiet=True)