librus-python-api 1.0.0__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.
- librus_python_api/__init__.py +243 -0
- librus_python_api/_notification_bootstrap.py +124 -0
- librus_python_api/_notification_codec.py +396 -0
- librus_python_api/_storage.py +403 -0
- librus_python_api/_windows_filesystem.py +390 -0
- librus_python_api/announcements.py +159 -0
- librus_python_api/attachment_routes.py +114 -0
- librus_python_api/attachments.py +297 -0
- librus_python_api/attendance.py +182 -0
- librus_python_api/attendance_frequency.py +112 -0
- librus_python_api/budget.py +79 -0
- librus_python_api/checkpoint.py +61 -0
- librus_python_api/completed_lessons.py +216 -0
- librus_python_api/config.py +1410 -0
- librus_python_api/detail_fields.py +50 -0
- librus_python_api/diagnostics.py +25 -0
- librus_python_api/exceptions.py +172 -0
- librus_python_api/files.py +242 -0
- librus_python_api/grade_parsers.py +169 -0
- librus_python_api/grade_records.py +454 -0
- librus_python_api/homework_range.py +41 -0
- librus_python_api/lifecycle.py +24 -0
- librus_python_api/markup.py +147 -0
- librus_python_api/message_content.py +230 -0
- librus_python_api/messages.py +288 -0
- librus_python_api/models.py +1160 -0
- librus_python_api/modern_body.py +75 -0
- librus_python_api/modern_mailbox.py +459 -0
- librus_python_api/modern_messages.py +276 -0
- librus_python_api/notification_models.py +145 -0
- librus_python_api/notification_persistence.py +1243 -0
- librus_python_api/notification_workflow.py +337 -0
- librus_python_api/notifications.py +216 -0
- librus_python_api/parsers.py +232 -0
- librus_python_api/parsing.py +49 -0
- librus_python_api/persistence.py +419 -0
- librus_python_api/py.typed +0 -0
- librus_python_api/recipients.py +271 -0
- librus_python_api/scheduler.py +287 -0
- librus_python_api/school_reads.py +400 -0
- librus_python_api/sending.py +125 -0
- librus_python_api/service.py +2285 -0
- librus_python_api/timetable.py +261 -0
- librus_python_api/transport.py +956 -0
- librus_python_api-1.0.0.dist-info/METADATA +262 -0
- librus_python_api-1.0.0.dist-info/RECORD +48 -0
- librus_python_api-1.0.0.dist-info/WHEEL +4 -0
- librus_python_api-1.0.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: librus-python-api
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Independent bounded async Librus Synergia client
|
|
5
|
+
Project-URL: Repository, https://github.com/krzysztofbury/librus-python-api
|
|
6
|
+
Project-URL: Issues, https://github.com/krzysztofbury/librus-python-api/issues
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
10
|
+
Classifier: Framework :: AsyncIO
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Classifier: Operating System :: POSIX
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Requires-Python: >=3.13
|
|
19
|
+
Requires-Dist: aiohttp<4,>=3.14.2
|
|
20
|
+
Requires-Dist: lxml<7,>=6.1
|
|
21
|
+
Requires-Dist: pydantic<3,>=2.12
|
|
22
|
+
Requires-Dist: pywin32<400,>=312; sys_platform == 'win32'
|
|
23
|
+
Requires-Dist: tzdata>=2026.5; sys_platform == 'win32'
|
|
24
|
+
Requires-Dist: yarl<2,>=1.20
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# librus-python-api
|
|
28
|
+
|
|
29
|
+
Read grades, attendance, homework, timetables and messages from **Librus Synergia**
|
|
30
|
+
in Python. This independent, asynchronous client handles login, session recovery,
|
|
31
|
+
pagination and request limits, returning typed Python objects rather than HTML.
|
|
32
|
+
|
|
33
|
+
Use it in personal scripts, notification services or application backends. One
|
|
34
|
+
service can manage multiple logins while keeping their sessions and data separate.
|
|
35
|
+
It is not an official Librus product.
|
|
36
|
+
|
|
37
|
+
**Requirements:** Python 3.13 or newer. Disk workflows require a trusted local
|
|
38
|
+
POSIX filesystem on Linux/macOS, or a fixed local NTFS volume on Windows with
|
|
39
|
+
private ACLs. Windows installations include `pywin32` and `tzdata` automatically.
|
|
40
|
+
Network paths, reparse-point paths and unsafe storage permissions fail closed.
|
|
41
|
+
See [platform requirements](contracts/persistence.md#windows-disk-boundary-25).
|
|
42
|
+
|
|
43
|
+
**Status:** `1.0.0` freezes the documented native library API. It does not claim
|
|
44
|
+
completed MCP cutover, production-state migration or universal live-school
|
|
45
|
+
compatibility. Those consumer/live gates remain separate. School features depend
|
|
46
|
+
on what each account can access. See the [compatibility policy](API.md#compatibility-policy).
|
|
47
|
+
See [limitations](#supported-features-and-limitations) below.
|
|
48
|
+
|
|
49
|
+
## Install
|
|
50
|
+
|
|
51
|
+
Install the exact release from PyPI after its gated publication completes:
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
python -m pip install librus-python-api==1.0.0
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Pin the exact version qualified by your application. Before publication, use a
|
|
58
|
+
checkout or locally built wheel instead.
|
|
59
|
+
From a checkout, install into a virtual environment:
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
python3 -m venv .venv
|
|
63
|
+
. .venv/bin/activate
|
|
64
|
+
python -m pip install .
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
To install a locally built wheel instead:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
python -m pip install ./dist/librus_python_api-1.0.0-py3-none-any.whl
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
No CLI or background process is installed: import the library in your own program.
|
|
74
|
+
|
|
75
|
+
## First request
|
|
76
|
+
|
|
77
|
+
Provide your login and password through your application's secret management.
|
|
78
|
+
The example reads environment variables; the library itself does not discover
|
|
79
|
+
environment variables or credential files.
|
|
80
|
+
|
|
81
|
+
You also need an application context key. Generate it **once**, store it alongside
|
|
82
|
+
your other application secrets, and reuse it across runs:
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
python -c 'import secrets; print(secrets.token_hex(32))'
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Set `LIBRUS_LOGIN`, `LIBRUS_PASSWORD` and `LIBRUS_CONTEXT_KEY` in your environment.
|
|
89
|
+
The last variable is the 64-character hex output from that command. Do not use
|
|
90
|
+
your password as this key. Then run:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
import asyncio
|
|
94
|
+
import os
|
|
95
|
+
from datetime import date
|
|
96
|
+
|
|
97
|
+
from librus_python_api import AccountCredentials, HomeworkRangeRequest, LibrusService
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
async def main() -> None:
|
|
101
|
+
accounts = {
|
|
102
|
+
"school": AccountCredentials(
|
|
103
|
+
login=os.environ["LIBRUS_LOGIN"],
|
|
104
|
+
password=os.environ["LIBRUS_PASSWORD"],
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
context_key = bytes.fromhex(os.environ["LIBRUS_CONTEXT_KEY"])
|
|
108
|
+
async with LibrusService(accounts, context_key=context_key) as service:
|
|
109
|
+
client = service.account("school")
|
|
110
|
+
profile = await client.student_information()
|
|
111
|
+
print(profile)
|
|
112
|
+
|
|
113
|
+
today = date.today()
|
|
114
|
+
homework = await client.homework_range(
|
|
115
|
+
HomeworkRangeRequest(today.replace(day=1), today)
|
|
116
|
+
)
|
|
117
|
+
for item in homework.items:
|
|
118
|
+
print(item.subject, item.topic, item.due_on)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
asyncio.run(main())
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`"school"` is your local account alias, not a student ID. Login occurs on the first
|
|
125
|
+
request. The async context manager closes sessions and outstanding work when it
|
|
126
|
+
exits. Results are immutable dataclasses; personal fields are omitted from their
|
|
127
|
+
`repr`, so access named attributes when displaying data intentionally.
|
|
128
|
+
|
|
129
|
+
## Common tasks
|
|
130
|
+
|
|
131
|
+
Inside the service context above:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from datetime import timedelta
|
|
135
|
+
|
|
136
|
+
# School-provided final grades, grouped into typed subject records.
|
|
137
|
+
grades = await client.final_grades()
|
|
138
|
+
for subject in grades.items:
|
|
139
|
+
print(subject.subject, subject.annual.raw)
|
|
140
|
+
|
|
141
|
+
# A week always starts on Monday.
|
|
142
|
+
today = date.today()
|
|
143
|
+
monday = today - timedelta(days=today.weekday())
|
|
144
|
+
timetable = await client.timetable(monday)
|
|
145
|
+
|
|
146
|
+
# Inclusive date window. Neither attendance nor grades computes a GPA.
|
|
147
|
+
attendance = await client.attendance_window(today.replace(day=1), today)
|
|
148
|
+
|
|
149
|
+
# Permit reuse of this account's cached result for up to 60 seconds.
|
|
150
|
+
announcements = await client.announcements(max_age_seconds=60)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Collections expose named record tuples, for example `homework.items`, rather than
|
|
154
|
+
name-keyed dictionaries. Dates are Python `date` values where established by the
|
|
155
|
+
upstream contract. Displayed detail values remain strings; missing or unknown
|
|
156
|
+
values are not replaced with guessed zeros. Full signatures, result fields and
|
|
157
|
+
examples are in the [API reference][api].
|
|
158
|
+
|
|
159
|
+
### Multiple accounts
|
|
160
|
+
|
|
161
|
+
Add more aliases to `accounts`, then use `service.account(alias)` for each login.
|
|
162
|
+
Reuse **one service** so concurrent calls share its request budget and connection
|
|
163
|
+
limits. A parent login and a student login are separate contexts even when they
|
|
164
|
+
refer to the same student. Separate processes need application-level coordination
|
|
165
|
+
if they share an upstream traffic allowance.
|
|
166
|
+
|
|
167
|
+
### Bounded pagination and errors
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
from librus_python_api import RequestBudget
|
|
171
|
+
from librus_python_api.exceptions import LibrusError, ViewDisabledError
|
|
172
|
+
|
|
173
|
+
budget = RequestBudget(max_requests=20, timeout_seconds=60)
|
|
174
|
+
try:
|
|
175
|
+
batch = await client.messages(limit=25, max_pages=2, budget=budget)
|
|
176
|
+
for message in batch.items:
|
|
177
|
+
print(message.subject)
|
|
178
|
+
# Request another batch with cursor=batch.next_cursor when it is not None.
|
|
179
|
+
except ViewDisabledError:
|
|
180
|
+
print("This school has disabled the requested view.")
|
|
181
|
+
except LibrusError as error:
|
|
182
|
+
print(f"Request failed: {error.kind.value}")
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
A budget covers login, queueing and all pages of an operation. Defaults allow
|
|
186
|
+
5 requests/second, a burst of 10 and two simultaneous requests across the service.
|
|
187
|
+
Fresh reads are the default. Unsupported layouts raise typed errors rather than
|
|
188
|
+
silently returning incomplete data. Cursors detect changes; they are not snapshots.
|
|
189
|
+
|
|
190
|
+
## Messages, files and notifications
|
|
191
|
+
|
|
192
|
+
- **Message content:** opening received content can mark it read. Pass
|
|
193
|
+
`allow_mark_read=True` only when your application permits that effect.
|
|
194
|
+
- **Sending:** prepare a single-use send attempt and obtain approval in your
|
|
195
|
+
application. An `UNKNOWN` result must not trigger an automatic resend.
|
|
196
|
+
- **Attachments:** stream bytes with explicit limits, or use the optional
|
|
197
|
+
`files.publish_attachment()` helper to save atomically into an existing directory.
|
|
198
|
+
- **Notifications:** optional `NotificationStore` and `NotificationWorkflow`
|
|
199
|
+
provide durable checkpoints, pending delivery and explicit acknowledgement.
|
|
200
|
+
- **Persistent sends:** optional `PersistenceStore` records confirmations, claims
|
|
201
|
+
and uncertain outcomes across restarts. Stores create or validate private
|
|
202
|
+
caller-selected directories; core reads do not create files. Use explicit
|
|
203
|
+
`files.prepare_attachment_directory(path)` to provision a private download
|
|
204
|
+
directory without writing platform-specific ACL code.
|
|
205
|
+
|
|
206
|
+
The legacy and modern messaging backends have distinct references and permissions;
|
|
207
|
+
select one explicitly. See the [API reference][api] for complete workflows.
|
|
208
|
+
|
|
209
|
+
## Context keys and upgrading from 0.6
|
|
210
|
+
|
|
211
|
+
`LibrusService` now requires `context_key`, exactly 32 secret random bytes.
|
|
212
|
+
`client.context.identifier` is an HMAC-SHA256 pseudonym bound to that key, the
|
|
213
|
+
alias, login and configured origins. Password changes preserve it. Different
|
|
214
|
+
application keys produce different identifiers; the identifier is not a login
|
|
215
|
+
credential or permission token. The separate `context.alias` is still plain text.
|
|
216
|
+
|
|
217
|
+
**Back up and reuse the key with persistent state.** Losing or rotating it changes
|
|
218
|
+
all context identifiers. Do not treat an empty history under a different key as
|
|
219
|
+
permission to resend a message. Version 0.7 uses storage and notification archive
|
|
220
|
+
format 3 and refuses older formats without modifying them. Keep 0.6 stores and
|
|
221
|
+
their pending/UNKNOWN records for reconciliation; there is no automatic migration.
|
|
222
|
+
See the [upgrade guide][upgrade] before reusing a persistent application.
|
|
223
|
+
|
|
224
|
+
Loguru is no longer a dependency. For optional diagnostics, pass
|
|
225
|
+
`diagnostic_sink=librus_python_api.diagnostics.logging_sink` after importing that
|
|
226
|
+
function. Configure handlers with Python's standard `logging` module. You can
|
|
227
|
+
also pass your own callable; events contain allowlisted timing/outcome fields,
|
|
228
|
+
not credentials, account aliases or response bodies. The old `loguru_sink` was
|
|
229
|
+
removed in 0.7.
|
|
230
|
+
|
|
231
|
+
## Supported features and limitations
|
|
232
|
+
|
|
233
|
+
| Area | Available |
|
|
234
|
+
| --- | --- |
|
|
235
|
+
| School data | Profile, grades, attendance, timetable, announcements, agenda, homework and completed lessons |
|
|
236
|
+
| Communication | Legacy/modern message lists and content, recipient discovery, bounded attachment streams and explicit sending |
|
|
237
|
+
| Application workflows | Shared multi-account limits, caching, notification checkpoints, optional durable send/notification stores |
|
|
238
|
+
|
|
239
|
+
Completed lessons may be disabled by the school. Behaviour notes and observation
|
|
240
|
+
cards are not implemented. Some recipient, archive and receipt layouts remain
|
|
241
|
+
unqualified; backend acceptance is not proof of delivery. Tests cover supported
|
|
242
|
+
contracts, not every school or role. Detailed coverage is in the
|
|
243
|
+
[verification log][verification] and [roadmap][roadmap].
|
|
244
|
+
|
|
245
|
+
## Development and support
|
|
246
|
+
|
|
247
|
+
Use a repository checkout for tests and development tools; they are deliberately
|
|
248
|
+
excluded from published source archives. See [CONTRIBUTING.md][contributing] for
|
|
249
|
+
setup and offline checks. Report bugs through [GitHub Issues][issues] and security
|
|
250
|
+
concerns according to [SECURITY.md][security]. Do not attach credentials or raw
|
|
251
|
+
school data to public reports.
|
|
252
|
+
|
|
253
|
+
MIT licensed. See [LICENSE][license].
|
|
254
|
+
|
|
255
|
+
[api]: https://github.com/krzysztofbury/librus-python-api/blob/main/API.md
|
|
256
|
+
[upgrade]: https://github.com/krzysztofbury/librus-python-api/blob/main/contracts/account-context.md
|
|
257
|
+
[verification]: https://github.com/krzysztofbury/librus-python-api/blob/main/VERIFICATION.md
|
|
258
|
+
[roadmap]: https://github.com/krzysztofbury/librus-python-api/blob/main/TODO.md
|
|
259
|
+
[contributing]: https://github.com/krzysztofbury/librus-python-api/blob/main/CONTRIBUTING.md
|
|
260
|
+
[issues]: https://github.com/krzysztofbury/librus-python-api/issues
|
|
261
|
+
[security]: https://github.com/krzysztofbury/librus-python-api/blob/main/SECURITY.md
|
|
262
|
+
[license]: https://github.com/krzysztofbury/librus-python-api/blob/main/LICENSE
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
librus_python_api/__init__.py,sha256=ErEyS0CIPgmEIHzURu8MnaZ-rwFiRexLujZnv5cyY_8,5657
|
|
2
|
+
librus_python_api/_notification_bootstrap.py,sha256=18nzH0doXBNaZXCz-_ckIvRrlHTWV5Mm1t5m2-5eYGI,4669
|
|
3
|
+
librus_python_api/_notification_codec.py,sha256=hU6G3zGJ5fR8wfPC6fV2OqBKs-7XpT9eRnKO3FGsTzY,13451
|
|
4
|
+
librus_python_api/_storage.py,sha256=vh6O3X7e5ZNJf2GKU3Cz5PxhHn4D_nv7U7YvcoQV57s,15661
|
|
5
|
+
librus_python_api/_windows_filesystem.py,sha256=pQANIGkYrb4Q75gz5mdr5mqYhM_PFblWwTxPGM0bQ78,14063
|
|
6
|
+
librus_python_api/announcements.py,sha256=13FoOR1sq7tt9w6aLf0vclcFKDqLUiIYaO5iYD2QVLA,5928
|
|
7
|
+
librus_python_api/attachment_routes.py,sha256=uSg5wCQqHJiphF0KdI0GatQxZr5SLUx6xWQRsl_U4_U,4123
|
|
8
|
+
librus_python_api/attachments.py,sha256=kyIBpFxeK34Al5_jCkxYKpZnsSLa5DYaGS6vHADpy_g,10921
|
|
9
|
+
librus_python_api/attendance.py,sha256=HeFAfnIUn4N__yp1zr635Dve55S2jmwtkeIy_6mV5B4,6924
|
|
10
|
+
librus_python_api/attendance_frequency.py,sha256=VAXZksSbE_o3fhP9vnN3_y0CCFQATFf6EOYhLQn-Fk8,3426
|
|
11
|
+
librus_python_api/budget.py,sha256=8fvqT7eIxyVX2P2OBG27XsYHk_HbtSS4lzuecYpHtgs,2878
|
|
12
|
+
librus_python_api/checkpoint.py,sha256=QBmG9GtpyaGRaFq-FXuGA3yR1BjuMFN9V3RTvvi_FNQ,1930
|
|
13
|
+
librus_python_api/completed_lessons.py,sha256=sR2oLSGb2q1580l-2upCBv9sQfIcHi7CQfWr1K0EFXI,7635
|
|
14
|
+
librus_python_api/config.py,sha256=uXadjaj_CONEt3RJkk6a8ErZAohGVoZRsR9lfMaUtrU,48422
|
|
15
|
+
librus_python_api/detail_fields.py,sha256=K10Stx_ehDTttkUI7-G7a2Ko9exYEu5NJpR-3sBnQ60,1789
|
|
16
|
+
librus_python_api/diagnostics.py,sha256=2l7wq6RA3it-Gwj-JRLcw5qbI37fl3xII6GZA2mZj0o,856
|
|
17
|
+
librus_python_api/exceptions.py,sha256=yWWoo0xyrQAk1d13HOJZnQBsq4ulh_P0hRSI6ZiNQOE,4622
|
|
18
|
+
librus_python_api/files.py,sha256=yVa1wvw2PwAWPix_ZDLokZ-_NTMuG8nStW7I3K6jAo4,8895
|
|
19
|
+
librus_python_api/grade_parsers.py,sha256=91Kr1-TArzqO-b94ipeIR0a98OV7tRCZQdBWsd9QLZ0,6141
|
|
20
|
+
librus_python_api/grade_records.py,sha256=HvGHQ8Fyx_1Ne5k6N8cBeTqrDCzM5P6saj8eijDbRA4,16793
|
|
21
|
+
librus_python_api/homework_range.py,sha256=erYfvS6PhHU5XhnR6LkiLNy677hGVflY3UAuHOs-YUw,1663
|
|
22
|
+
librus_python_api/lifecycle.py,sha256=XzA5CEdZFo7iL5IMUrawnRvf2m9BFe0OseP-fpQFaAE,856
|
|
23
|
+
librus_python_api/markup.py,sha256=GZk7MmBBGB5SIVY_VngmQxQErI3eGHOpJs3mFVlMR3M,5298
|
|
24
|
+
librus_python_api/message_content.py,sha256=sUPuqpjuavqDyn6QGM5aPH4mpoQV62bDLepSSQ2AsUE,8686
|
|
25
|
+
librus_python_api/messages.py,sha256=K9F8XVs1SojfFpdxxLV8gx9E0g81YxEHjigDzLHmDCg,10230
|
|
26
|
+
librus_python_api/models.py,sha256=DGbxwDymPjJsqRMtqIe2W9KCBXzNiVPhzeXVjPSC9iQ,33106
|
|
27
|
+
librus_python_api/modern_body.py,sha256=3L4P_cIrHdIxZqiinFSQrDMhG6iklT1GoA-VEWMJUiI,2682
|
|
28
|
+
librus_python_api/modern_mailbox.py,sha256=nRrmIHb7RfV49xjUTBlDcgtxOdmXEpp4F1L0IvcGQxw,16118
|
|
29
|
+
librus_python_api/modern_messages.py,sha256=9gysqjUkQGtMKmnCL7boRzNDnAhtL5ibAJ2rkNZWCec,9694
|
|
30
|
+
librus_python_api/notification_models.py,sha256=4eLTAE9JzHhveoaWtZQwGBolmb87QUP5kOSW7Jjt7J0,4199
|
|
31
|
+
librus_python_api/notification_persistence.py,sha256=hXKmzAh0yNYG_n5CLlZOcoYOZdQnlrSeNtjjXiDmLm4,49532
|
|
32
|
+
librus_python_api/notification_workflow.py,sha256=MsBJdwn6J1UUGlz3Ldzi7WEBz5Qsama7eGmZvUQj25g,12924
|
|
33
|
+
librus_python_api/notifications.py,sha256=VbA8pqNG_19yYo9y7IqpGRmfEb4qDcvA5gBb1syGJKs,7806
|
|
34
|
+
librus_python_api/parsers.py,sha256=OFztbUMDzCywq17BgfFT485bVjyOqLksFHQJthZCx5Q,8120
|
|
35
|
+
librus_python_api/parsing.py,sha256=H71srw5yx-RFrAKZFgj-QFX-DIXZmhnGrDTmJhazCB8,1838
|
|
36
|
+
librus_python_api/persistence.py,sha256=C5oDHQg1Xzy9Jb9obVsRNndCiXps-QQQtQ_M7_l5BBI,15546
|
|
37
|
+
librus_python_api/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
+
librus_python_api/recipients.py,sha256=6GQCKo-Zjg3VFSg1J8YXcDsy_U3r6-MUS4VCvz0xdaQ,10033
|
|
39
|
+
librus_python_api/scheduler.py,sha256=3JplYxqvQdFz3aKXcoQUJHE9s3FPw_xRhQ2CPNLuQmA,10729
|
|
40
|
+
librus_python_api/school_reads.py,sha256=PCnZ4lv44j-68FgJpQiMteaPSyfhbX8_3CUyE6zhFcQ,14760
|
|
41
|
+
librus_python_api/sending.py,sha256=Nvvk2r-6D6Us53a2fH5GW9PcA6bWEfuOvy6c3M5QVcE,4549
|
|
42
|
+
librus_python_api/service.py,sha256=a8EYBZBihVFe8moY_5SYjCtQSbcDrPwLA7vtcIopsqk,84209
|
|
43
|
+
librus_python_api/timetable.py,sha256=tX1QK9fQABxzfLaHHqTe8e6rAgdOkCoTOfAHdPwNmLE,9836
|
|
44
|
+
librus_python_api/transport.py,sha256=6S5wwBiRkUfKmi6w2t8msxlTSzCo-IbIBE13FeBc7Jw,35357
|
|
45
|
+
librus_python_api-1.0.0.dist-info/METADATA,sha256=_7MctXX2lgQROYs4N-In7q7ZT5vAbKNU3BfQchDQ8Rg,11514
|
|
46
|
+
librus_python_api-1.0.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
47
|
+
librus_python_api-1.0.0.dist-info/licenses/LICENSE,sha256=IuerLb3cnZCsaB23znydjjvKqP-LmSJd3syKa9NGUts,1071
|
|
48
|
+
librus_python_api-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Krzysztof Bury
|
|
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.
|