aula-connect 0.0.1__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.
- aula_connect-0.0.1/.git_archival.txt +3 -0
- aula_connect-0.0.1/.gitattributes +2 -0
- aula_connect-0.0.1/.github/dependabot.yml +24 -0
- aula_connect-0.0.1/.github/release.yml +25 -0
- aula_connect-0.0.1/.github/rulesets/branch-names.json +26 -0
- aula_connect-0.0.1/.github/rulesets/main.json +63 -0
- aula_connect-0.0.1/.github/workflows/close-inactive-issues.yml +30 -0
- aula_connect-0.0.1/.github/workflows/library-released.yml +32 -0
- aula_connect-0.0.1/.github/workflows/release-drafter.yml +28 -0
- aula_connect-0.0.1/.github/workflows/release.yml +91 -0
- aula_connect-0.0.1/.github/workflows/tests.yml +42 -0
- aula_connect-0.0.1/.gitignore +16 -0
- aula_connect-0.0.1/CLAUDE.md +152 -0
- aula_connect-0.0.1/LICENSE +674 -0
- aula_connect-0.0.1/PKG-INFO +64 -0
- aula_connect-0.0.1/README.md +32 -0
- aula_connect-0.0.1/pyproject.toml +82 -0
- aula_connect-0.0.1/requirements-test.txt +11 -0
- aula_connect-0.0.1/setup.cfg +4 -0
- aula_connect-0.0.1/src/aula_connect/__init__.py +14 -0
- aula_connect-0.0.1/src/aula_connect/api/aula_errors.py +15 -0
- aula_connect-0.0.1/src/aula_connect/api/aula_proxy_client.py +1368 -0
- aula_connect-0.0.1/src/aula_connect/api/const.py +6 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_birthday_models.py +11 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_birthday_parser.py +32 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_calendar_models.py +115 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_calendar_parser.py +141 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_easyiq_weekplan_models.py +38 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_easyiq_weekplan_parser.py +76 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_message_thread_models.py +61 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_message_thread_parser.py +114 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_newsletter_models.py +25 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_newsletter_parser.py +66 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_notification_models.py +104 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_notification_parser.py +195 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_parser.py +189 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_profile_models.py +106 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_profile_parser.py +205 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_weekly_plan_models.py +40 -0
- aula_connect-0.0.1/src/aula_connect/api/models/aula_weekly_plan_parser.py +66 -0
- aula_connect-0.0.1/src/aula_connect/api/models/constants.py +104 -0
- aula_connect-0.0.1/src/aula_connect/api/models/module.py +142 -0
- aula_connect-0.0.1/src/aula_connect/api/module.py +97 -0
- aula_connect-0.0.1/src/aula_connect/api/responses/common_data.py +13 -0
- aula_connect-0.0.1/src/aula_connect/api/responses/get_birthday_events_for_institutions.py +17 -0
- aula_connect-0.0.1/src/aula_connect/api/responses/get_daily_overview_response.py +43 -0
- aula_connect-0.0.1/src/aula_connect/api/responses/get_easyiq_weekplan_response.py +14 -0
- aula_connect-0.0.1/src/aula_connect/api/responses/get_events_by_profile_ids_and_resource_ids.py +67 -0
- aula_connect-0.0.1/src/aula_connect/api/responses/get_message_threads_response.py +48 -0
- aula_connect-0.0.1/src/aula_connect/api/responses/get_messages_for_thread_response.py +37 -0
- aula_connect-0.0.1/src/aula_connect/api/responses/get_notifications_response.py +34 -0
- aula_connect-0.0.1/src/aula_connect/api/responses/get_profile_context_response.py +92 -0
- aula_connect-0.0.1/src/aula_connect/api/responses/get_profile_master_data_response.py +23 -0
- aula_connect-0.0.1/src/aula_connect/api/responses/get_profiles_by_login_response.py +34 -0
- aula_connect-0.0.1/src/aula_connect/api/responses/get_weekly_newsletter_response.py +18 -0
- aula_connect-0.0.1/src/aula_connect/api/responses/get_weekly_plans_response.py +23 -0
- aula_connect-0.0.1/src/aula_connect/api/utils/list_utils.py +7 -0
- aula_connect-0.0.1/src/aula_connect/client.py +224 -0
- aula_connect-0.0.1/src/aula_connect/login/__init__.py +20 -0
- aula_connect-0.0.1/src/aula_connect/login/client.py +1732 -0
- aula_connect-0.0.1/src/aula_connect/login/exceptions.py +43 -0
- aula_connect-0.0.1/src/aula_connect/login/mitid/__init__.py +30 -0
- aula_connect-0.0.1/src/aula_connect/login/mitid/browser_client.py +813 -0
- aula_connect-0.0.1/src/aula_connect/login/mitid/helpers.py +106 -0
- aula_connect-0.0.1/src/aula_connect/login/mitid/login_flows/__init__.py +0 -0
- aula_connect-0.0.1/src/aula_connect/login/mitid/login_flows/aula.py +10 -0
- aula_connect-0.0.1/src/aula_connect/login/mitid/srp.py +158 -0
- aula_connect-0.0.1/src/aula_connect/py.typed +0 -0
- aula_connect-0.0.1/src/aula_connect.egg-info/PKG-INFO +64 -0
- aula_connect-0.0.1/src/aula_connect.egg-info/SOURCES.txt +80 -0
- aula_connect-0.0.1/src/aula_connect.egg-info/dependency_links.txt +1 -0
- aula_connect-0.0.1/src/aula_connect.egg-info/requires.txt +5 -0
- aula_connect-0.0.1/src/aula_connect.egg-info/scm_file_list.json +77 -0
- aula_connect-0.0.1/src/aula_connect.egg-info/scm_version.json +8 -0
- aula_connect-0.0.1/src/aula_connect.egg-info/top_level.txt +1 -0
- aula_connect-0.0.1/tests/api/fixtures/easyiq_weekplan_response.json +28 -0
- aula_connect-0.0.1/tests/api/test_easyiq_weekplan.py +89 -0
- aula_connect-0.0.1/tests/api/test_error_handling.py +1172 -0
- aula_connect-0.0.1/tests/api/test_messages.py +43 -0
- aula_connect-0.0.1/tests/api/test_newsletter.py +172 -0
- aula_connect-0.0.1/tests/api/test_notifications.py +98 -0
- aula_connect-0.0.1/tests/api/test_parser.py +111 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Proposes updates to the pinned actions and test tools as pull requests, which the tests then
|
|
2
|
+
# check before anything is merged.
|
|
3
|
+
#
|
|
4
|
+
# Shared by every library of the owner, from HairingX/workflows; this file is a copy of its
|
|
5
|
+
# template and is checked to stay so.
|
|
6
|
+
version: 2
|
|
7
|
+
updates:
|
|
8
|
+
- package-ecosystem: github-actions
|
|
9
|
+
directory: /
|
|
10
|
+
schedule:
|
|
11
|
+
interval: weekly
|
|
12
|
+
labels:
|
|
13
|
+
- dependencies
|
|
14
|
+
assignees:
|
|
15
|
+
- HairingX
|
|
16
|
+
|
|
17
|
+
- package-ecosystem: pip
|
|
18
|
+
directory: /
|
|
19
|
+
schedule:
|
|
20
|
+
interval: weekly
|
|
21
|
+
labels:
|
|
22
|
+
- dependencies
|
|
23
|
+
assignees:
|
|
24
|
+
- HairingX
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# How GitHub groups a release's notes: each pull request by its labels.
|
|
2
|
+
changelog:
|
|
3
|
+
# The notes are for users: what is changed for them, not work on the repository itself.
|
|
4
|
+
exclude:
|
|
5
|
+
labels:
|
|
6
|
+
- skip-changelog
|
|
7
|
+
- chore
|
|
8
|
+
- documentation
|
|
9
|
+
- dependencies
|
|
10
|
+
categories:
|
|
11
|
+
- title: 🛠 Breaking Changes
|
|
12
|
+
labels:
|
|
13
|
+
- breaking-change
|
|
14
|
+
- title: 🚀 Features
|
|
15
|
+
labels:
|
|
16
|
+
- feature request
|
|
17
|
+
- enhancement
|
|
18
|
+
- title: 🐛 Bug Fixes
|
|
19
|
+
labels:
|
|
20
|
+
- bug
|
|
21
|
+
- fix
|
|
22
|
+
- bugfix
|
|
23
|
+
- title: Other Changes
|
|
24
|
+
labels:
|
|
25
|
+
- "*"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Branch names",
|
|
3
|
+
"target": "branch",
|
|
4
|
+
"enforcement": "active",
|
|
5
|
+
"conditions": {
|
|
6
|
+
"ref_name": {
|
|
7
|
+
"include": [
|
|
8
|
+
"~ALL"
|
|
9
|
+
],
|
|
10
|
+
"exclude": [
|
|
11
|
+
"refs/heads/main",
|
|
12
|
+
"refs/heads/feature/**/*",
|
|
13
|
+
"refs/heads/fix/**/*",
|
|
14
|
+
"refs/heads/docs/**/*",
|
|
15
|
+
"refs/heads/chore/**/*",
|
|
16
|
+
"refs/heads/dependabot/**/*"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"bypass_actors": [],
|
|
21
|
+
"rules": [
|
|
22
|
+
{
|
|
23
|
+
"type": "creation"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "main: pull requests only",
|
|
3
|
+
"target": "branch",
|
|
4
|
+
"enforcement": "active",
|
|
5
|
+
"conditions": {
|
|
6
|
+
"ref_name": {
|
|
7
|
+
"include": [
|
|
8
|
+
"~DEFAULT_BRANCH"
|
|
9
|
+
],
|
|
10
|
+
"exclude": []
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"bypass_actors": [
|
|
14
|
+
{
|
|
15
|
+
"actor_id": 5,
|
|
16
|
+
"actor_type": "RepositoryRole",
|
|
17
|
+
"bypass_mode": "pull_request"
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"rules": [
|
|
21
|
+
{
|
|
22
|
+
"type": "deletion"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"type": "non_fast_forward"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"type": "pull_request",
|
|
29
|
+
"parameters": {
|
|
30
|
+
"required_approving_review_count": 0,
|
|
31
|
+
"dismiss_stale_reviews_on_push": false,
|
|
32
|
+
"require_code_owner_review": false,
|
|
33
|
+
"require_last_push_approval": false,
|
|
34
|
+
"required_review_thread_resolution": false
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"type": "required_status_checks",
|
|
39
|
+
"parameters": {
|
|
40
|
+
"strict_required_status_checks_policy": false,
|
|
41
|
+
"do_not_enforce_on_create": false,
|
|
42
|
+
"required_status_checks": [
|
|
43
|
+
{
|
|
44
|
+
"context": "Python 3.12",
|
|
45
|
+
"integration_id": 15368
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"context": "Python 3.13",
|
|
49
|
+
"integration_id": 15368
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"context": "Python 3.14",
|
|
53
|
+
"integration_id": 15368
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"context": "Libraries released and pinned",
|
|
57
|
+
"integration_id": 15368
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Close inactive issues
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
schedule:
|
|
6
|
+
- cron: "30 1 * * *"
|
|
7
|
+
|
|
8
|
+
permissions: {}
|
|
9
|
+
|
|
10
|
+
# The shell given explicitly, so GitHub runs every step with pipefail.
|
|
11
|
+
defaults:
|
|
12
|
+
run:
|
|
13
|
+
shell: bash
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
close-issues:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
permissions:
|
|
19
|
+
issues: write
|
|
20
|
+
pull-requests: write
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/stale@v11
|
|
23
|
+
with:
|
|
24
|
+
days-before-issue-stale: 30
|
|
25
|
+
days-before-issue-close: 14
|
|
26
|
+
stale-issue-label: "stale"
|
|
27
|
+
stale-issue-message: "This issue is stale because it has been open for 30 days with no activity."
|
|
28
|
+
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
|
|
29
|
+
days-before-pr-stale: -1
|
|
30
|
+
days-before-pr-close: -1
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Library released
|
|
2
|
+
|
|
3
|
+
# A pull request is merged only once every library developed alongside the package comes from
|
|
4
|
+
# its release, not from a branch of the pull request's name.
|
|
5
|
+
#
|
|
6
|
+
# The workflows and the tools are shared by every library of the owner, from
|
|
7
|
+
# HairingX/workflows; this file is a copy of its template and is checked to stay so.
|
|
8
|
+
on:
|
|
9
|
+
pull_request:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
# The shell given explicitly, so GitHub runs every step with pipefail.
|
|
15
|
+
defaults:
|
|
16
|
+
run:
|
|
17
|
+
shell: bash
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
released:
|
|
21
|
+
name: Libraries released and pinned
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- name: Check out repository
|
|
25
|
+
uses: actions/checkout@v7
|
|
26
|
+
with:
|
|
27
|
+
persist-credentials: false
|
|
28
|
+
|
|
29
|
+
- name: No library from a branch
|
|
30
|
+
uses: HairingX/workflows/python/actions/libraries-released@v2
|
|
31
|
+
with:
|
|
32
|
+
branch: ${{ github.head_ref }}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Release Drafter
|
|
2
|
+
|
|
3
|
+
# Keeps a draft release proposing the next version, and labels pull requests by their branch's
|
|
4
|
+
# name. The draft is never published by hand: the Release workflow publishes it.
|
|
5
|
+
#
|
|
6
|
+
# The workflows and the tools are shared by every repository of the owner, from
|
|
7
|
+
# HairingX/workflows; this file is a copy of its template and is checked to stay so.
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
branches:
|
|
11
|
+
- main
|
|
12
|
+
pull_request:
|
|
13
|
+
types: [opened, reopened, synchronize]
|
|
14
|
+
|
|
15
|
+
permissions: {}
|
|
16
|
+
|
|
17
|
+
# The shell given explicitly, so GitHub runs every step with pipefail.
|
|
18
|
+
defaults:
|
|
19
|
+
run:
|
|
20
|
+
shell: bash
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
drafter:
|
|
24
|
+
name: Release Drafter
|
|
25
|
+
permissions:
|
|
26
|
+
contents: write
|
|
27
|
+
pull-requests: write
|
|
28
|
+
uses: HairingX/workflows/.github/workflows/release-drafter.yml@v2
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Run this from the Actions tab, on main, once the maintainer has approved the draft release and
|
|
4
|
+
# its version. Never publish the draft release by hand: the package takes its version from the
|
|
5
|
+
# tag, and only this workflow tags a tested commit.
|
|
6
|
+
#
|
|
7
|
+
# The file name matters: PyPI trusted publishing is bound to this repository, this workflow file
|
|
8
|
+
# and the pypi environment, and takes no reusable workflow, so the upload runs here.
|
|
9
|
+
#
|
|
10
|
+
# The workflows and the tools are shared by every library of the owner, from
|
|
11
|
+
# HairingX/workflows; this file is a copy of its template and is checked to stay so.
|
|
12
|
+
on:
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
inputs:
|
|
15
|
+
release:
|
|
16
|
+
description: >-
|
|
17
|
+
What to release. The version is worked out from the tags, PyPI and the draft release:
|
|
18
|
+
the next release candidate, or the final release that ends the series.
|
|
19
|
+
required: true
|
|
20
|
+
type: choice
|
|
21
|
+
options:
|
|
22
|
+
- release candidate
|
|
23
|
+
- final release
|
|
24
|
+
default: release candidate
|
|
25
|
+
version:
|
|
26
|
+
description: >-
|
|
27
|
+
Override, only for a new major version, which is never worked out, or when the version
|
|
28
|
+
worked out is wrong: canonical PEP 440 without a v, such as 1.0.0 or 1.0.0rc1, of the
|
|
29
|
+
kind chosen above. It must still be higher than every version tagged or on PyPI.
|
|
30
|
+
required: false
|
|
31
|
+
type: string
|
|
32
|
+
|
|
33
|
+
permissions: {}
|
|
34
|
+
|
|
35
|
+
# GitHub keeps one waiting run per group: a third dispatch cancels the one waiting.
|
|
36
|
+
concurrency:
|
|
37
|
+
group: release
|
|
38
|
+
cancel-in-progress: false
|
|
39
|
+
|
|
40
|
+
# The shell given explicitly, so GitHub runs every step with pipefail.
|
|
41
|
+
defaults:
|
|
42
|
+
run:
|
|
43
|
+
shell: bash
|
|
44
|
+
|
|
45
|
+
jobs:
|
|
46
|
+
release:
|
|
47
|
+
name: Release
|
|
48
|
+
permissions:
|
|
49
|
+
contents: write
|
|
50
|
+
pull-requests: read
|
|
51
|
+
actions: read
|
|
52
|
+
uses: HairingX/workflows/.github/workflows/python-release.yml@v2
|
|
53
|
+
with:
|
|
54
|
+
release: ${{ inputs.release }}
|
|
55
|
+
version: ${{ inputs.version }}
|
|
56
|
+
|
|
57
|
+
pypi:
|
|
58
|
+
name: Publish to PyPI
|
|
59
|
+
needs: release
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
permissions:
|
|
62
|
+
# Mandatory for trusted publishing.
|
|
63
|
+
id-token: write
|
|
64
|
+
environment:
|
|
65
|
+
name: pypi
|
|
66
|
+
url: https://pypi.org/p/${{ needs.release.outputs.package }}
|
|
67
|
+
steps:
|
|
68
|
+
- name: Fetch the distributions
|
|
69
|
+
uses: actions/download-artifact@v8
|
|
70
|
+
with:
|
|
71
|
+
name: dist
|
|
72
|
+
path: dist/
|
|
73
|
+
|
|
74
|
+
# A re-run finds the version it uploaded before.
|
|
75
|
+
- name: Publish
|
|
76
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
77
|
+
with:
|
|
78
|
+
skip-existing: true
|
|
79
|
+
|
|
80
|
+
github-release:
|
|
81
|
+
name: GitHub release
|
|
82
|
+
needs: [release, pypi]
|
|
83
|
+
permissions:
|
|
84
|
+
contents: write
|
|
85
|
+
uses: HairingX/workflows/.github/workflows/python-github-release.yml@v2
|
|
86
|
+
with:
|
|
87
|
+
tag: ${{ needs.release.outputs.tag }}
|
|
88
|
+
prerelease: ${{ needs.release.outputs.prerelease }}
|
|
89
|
+
previous_tag: ${{ needs.release.outputs.previous_tag }}
|
|
90
|
+
draft_id: ${{ needs.release.outputs.draft_id }}
|
|
91
|
+
draft_body: ${{ needs.release.outputs.draft_body }}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
# The workflows and the tools are shared by every library of the owner, from
|
|
4
|
+
# HairingX/workflows; this file is a copy of its template and is checked to stay so.
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
pull_request:
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: tests-${{ github.event_name }}-${{ github.ref }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
# The shell given explicitly, so GitHub runs every step with pipefail.
|
|
18
|
+
defaults:
|
|
19
|
+
run:
|
|
20
|
+
shell: bash
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
test:
|
|
24
|
+
name: Python ${{ matrix.python-version }}
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
strategy:
|
|
27
|
+
fail-fast: false
|
|
28
|
+
matrix:
|
|
29
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
30
|
+
steps:
|
|
31
|
+
- name: Check out repository, with every tag
|
|
32
|
+
uses: actions/checkout@v7
|
|
33
|
+
with:
|
|
34
|
+
persist-credentials: false
|
|
35
|
+
# setuptools-scm works the package's version out from the tags.
|
|
36
|
+
fetch-depth: 0
|
|
37
|
+
|
|
38
|
+
- name: Tests and type check
|
|
39
|
+
uses: HairingX/workflows/python/actions/tests@v2
|
|
40
|
+
with:
|
|
41
|
+
python-version: ${{ matrix.python-version }}
|
|
42
|
+
branch: ${{ github.head_ref || github.ref_name }}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.egg-info/
|
|
3
|
+
build/
|
|
4
|
+
dist/
|
|
5
|
+
.venv/
|
|
6
|
+
.pytest_cache/
|
|
7
|
+
.coverage
|
|
8
|
+
.idea/
|
|
9
|
+
.DS_Store
|
|
10
|
+
.claude/worktrees/
|
|
11
|
+
mysecrets.py
|
|
12
|
+
|
|
13
|
+
# Responses captured from a real Aula account hold children's personal data: they stay on the
|
|
14
|
+
# machine they were captured on. Only fixtures made up for the tests are tracked.
|
|
15
|
+
tests/api/fixtures/*
|
|
16
|
+
!tests/api/fixtures/easyiq_weekplan_response.json
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Conventions for this repository
|
|
2
|
+
|
|
3
|
+
A Python library for the Danish school platform Aula: it logs in through MitID and reads the
|
|
4
|
+
children's profiles, daily overviews, calendars, messages, notifications, weekly plans and
|
|
5
|
+
newsletters into typed models. The Home Assistant integration `ha_aula_connect` is built on it.
|
|
6
|
+
|
|
7
|
+
## This library
|
|
8
|
+
|
|
9
|
+
- Responses captured from a real Aula account hold children's personal data. They stay on the
|
|
10
|
+
machine they were captured on: `.gitignore` keeps `tests/api/fixtures/` out of git but for
|
|
11
|
+
the fixtures made up for the tests, and tests that need a captured response skip without it.
|
|
12
|
+
- MitID and Aula credentials and tokens are never logged.
|
|
13
|
+
- It imports nothing from Home Assistant. Aula sends some times as UTC that are the
|
|
14
|
+
institution's local time; `set_time_zone` names that time zone, and the system's is taken
|
|
15
|
+
without it.
|
|
16
|
+
- `aula_connect.login` is the MitID login, `aula_connect.api` the Aula API client with its
|
|
17
|
+
models and parsers, and `aula_connect.AulaClient` the two together, with the tokens kept
|
|
18
|
+
fresh.
|
|
19
|
+
- The code is GPL-3.0-or-later, as the Aula integration it comes from; the MitID browser client
|
|
20
|
+
in `aula_connect.login.mitid` is MIT-licensed by its author.
|
|
21
|
+
|
|
22
|
+
<!-- BEGIN HairingX/workflows: shared; edit it there -->
|
|
23
|
+
## Shared by every library
|
|
24
|
+
|
|
25
|
+
This section, the workflows and the release tools are the same in every Python library of the
|
|
26
|
+
owner. They come from `HairingX/workflows`: the workflows in `.github/` are copies of its
|
|
27
|
+
template, which call its reusable workflows and actions at `@v2`, and this section is a copy of
|
|
28
|
+
its `python/template/CLAUDE.md`. The tests check that the copies agree; a change to any of them is
|
|
29
|
+
made there, released, and synced into every repository with its
|
|
30
|
+
`common/tools/template.py sync python`. What is this repository's own is above this section.
|
|
31
|
+
|
|
32
|
+
## Comments and docstrings
|
|
33
|
+
|
|
34
|
+
Based on PEP 8 (Comments), PEP 257 (Docstring Conventions) and the Google Python Style Guide
|
|
35
|
+
(3.8 Comments and Docstrings).
|
|
36
|
+
|
|
37
|
+
**Docstrings describe the unit's own contract, and nothing else.**
|
|
38
|
+
- Every public module, class, function and method has one.
|
|
39
|
+
- The first line is a one-sentence summary. Add more only when a caller needs it: arguments,
|
|
40
|
+
return value, exceptions raised, side effects, invariants.
|
|
41
|
+
- Use Google style sections (`Args:`, `Returns:`, `Raises:`) only when they say something the
|
|
42
|
+
signature and type hints do not. Never repeat types; the hints carry them.
|
|
43
|
+
- Describe what the unit does, not who calls it, how other classes use its data, or where its
|
|
44
|
+
result ends up. That knowledge belongs to those other units and goes stale here.
|
|
45
|
+
|
|
46
|
+
**Comments explain why, never what.**
|
|
47
|
+
- Write one only where the code cannot say it: a protocol quirk, a non-obvious constraint, the
|
|
48
|
+
reason for an order of operations.
|
|
49
|
+
- No history: no "used to", "previously", "the old code", "this was a bug". Version control
|
|
50
|
+
holds history; a regression test's name holds the reason it exists.
|
|
51
|
+
- No references to other files, classes, line numbers or design-document sections. They rot the
|
|
52
|
+
moment the other side changes.
|
|
53
|
+
- No commented-out code. No TODO without an issue reference.
|
|
54
|
+
|
|
55
|
+
**Keep them short.** A comment longer than a few lines is design rationale; it belongs in
|
|
56
|
+
`docs/`, where it can cover several modules at once.
|
|
57
|
+
|
|
58
|
+
**Tests.** The test name states the behaviour. Add a docstring only when the reason is not
|
|
59
|
+
obvious from the name - one or two lines, no narrative.
|
|
60
|
+
|
|
61
|
+
## Conventions
|
|
62
|
+
|
|
63
|
+
- All documentation, comments and commit messages are in English.
|
|
64
|
+
- The package lives in `src/<package>/`, ships its types (`py.typed`), and supports Python 3.12
|
|
65
|
+
and later (`requires-python = ">=3.12"`); the tests run on 3.12, 3.13 and 3.14.
|
|
66
|
+
- pyright strict must report 0 errors (`pyright`); the configuration is in `pyproject.toml`.
|
|
67
|
+
No `# type: ignore` and no rule turned off.
|
|
68
|
+
- The tests are pytest, in `tests/`, and cover every line of the package; the build fails below
|
|
69
|
+
100%. They import the installed package, as its users do, never `src.<package>`: a packaging
|
|
70
|
+
mistake then fails a test before a release. Tests that need a real device are marked `live`,
|
|
71
|
+
skip themselves without one, and never run in CI.
|
|
72
|
+
- A repository on its way to this standard says so under `[tool.hairingx-workflows]` in
|
|
73
|
+
`pyproject.toml`: `transition` says why, and `coverage` the percentage its tests must reach
|
|
74
|
+
meanwhile; pyright, still strict, may leave the files listed in `[tool.pyright] ignore`
|
|
75
|
+
unchecked. Every run warns while it lasts. Each pull request raises the coverage and takes
|
|
76
|
+
files off the list, never the reverse, until the transition is removed.
|
|
77
|
+
- Every problem found gets a test that fails without the fix.
|
|
78
|
+
- The test tools are pinned with `==` in `requirements-test.txt`, pyright, pytest and
|
|
79
|
+
pytest-cov among them: `pip install -e . -r requirements-test.txt`.
|
|
80
|
+
- No real IP addresses, hostnames, serial numbers, email addresses or credentials in tracked
|
|
81
|
+
files; real values live in a gitignored file or in environment variables. Examples use the
|
|
82
|
+
documentation ranges, such as 192.0.2.0/24. A credential is never logged.
|
|
83
|
+
|
|
84
|
+
## Releasing
|
|
85
|
+
|
|
86
|
+
**The version is the release's tag, and the draft release is never published by hand.** The
|
|
87
|
+
package has no version in a file: setuptools-scm works it out from the tags when it is built, so a
|
|
88
|
+
checkout between releases says a development version such as `0.2.1.dev3+g1a2b3c4`.
|
|
89
|
+
|
|
90
|
+
1. Merge pull requests into `main`. Release Drafter keeps a draft release proposing the next
|
|
91
|
+
version: a minor bump for the label `breaking-change` or `minor`, a patch otherwise.
|
|
92
|
+
**A new major version is never worked out**, as a label placed wrongly must not release one;
|
|
93
|
+
type it into Release as the override.
|
|
94
|
+
2. Wait until the Release Drafter run on `main` has finished. Release refuses a draft that is not
|
|
95
|
+
up to date with `main`.
|
|
96
|
+
3. Show the maintainer the draft's notes and its version, and get explicit approval before
|
|
97
|
+
running Release.
|
|
98
|
+
4. Run the **Release** workflow from the Actions tab, on `main`, and choose **release
|
|
99
|
+
candidate** or **final release**. It works out the version: the next release candidate of the
|
|
100
|
+
open series (`0.2.0rc1` -> `0.2.0rc2`), or the final release that ends it (`0.2.0`); a draft
|
|
101
|
+
naming a higher version starts a new series. Type a version only for a new major, or to
|
|
102
|
+
override one worked out wrongly: canonical PEP 440, of the kind chosen.
|
|
103
|
+
|
|
104
|
+
Release refuses any version not higher than every version tagged or on PyPI, yanked ones
|
|
105
|
+
included, and a version with no pull request merged since the release before it - for a final
|
|
106
|
+
release, the final release before it. It runs the tests on the exact commit it releases, tags
|
|
107
|
+
that commit, builds, checks that the built package says the version, and only then pushes the
|
|
108
|
+
tag - nothing is pushed to `main`. Then PyPI, then the GitHub release with the distributions,
|
|
109
|
+
marked as a pre-release where it is one.
|
|
110
|
+
|
|
111
|
+
A release candidate's notes are written by GitHub from the pull requests merged since the
|
|
112
|
+
previous release candidate or final release, grouped by label as `.github/release.yml` says, and
|
|
113
|
+
the draft is kept. A final release's notes are the draft's - the first final release says only
|
|
114
|
+
that it is the initial release - and the final release deletes the draft. To change what a
|
|
115
|
+
release says, change the pull requests: the title is the line, the labels decide the section.
|
|
116
|
+
|
|
117
|
+
If publishing fails part-way, **Re-run failed jobs** resumes it: the tag, PyPI and the GitHub
|
|
118
|
+
release each accept what an earlier attempt already did.
|
|
119
|
+
|
|
120
|
+
PyPI trusted publishing is bound to this repository, the workflow file `release.yml` and the
|
|
121
|
+
`pypi` environment: renaming either breaks the upload. Actions are referred to by their major
|
|
122
|
+
version; Dependabot proposes a new major, and updates to the test tools, as pull requests.
|
|
123
|
+
|
|
124
|
+
## Libraries developed together
|
|
125
|
+
|
|
126
|
+
A library this one depends on and develops alongside is listed, in install order, under
|
|
127
|
+
`[tool.hairingx-workflows] libraries` in `pyproject.toml`. A development branch is tested with
|
|
128
|
+
that library's branch of the same name, where it has one, over its release; the check
|
|
129
|
+
"Libraries released and pinned" then fails until the library is released, its version required
|
|
130
|
+
in `pyproject.toml`, and its branch deleted. **Release a library first**, then require its
|
|
131
|
+
version here.
|
|
132
|
+
|
|
133
|
+
## Branches and pull requests
|
|
134
|
+
|
|
135
|
+
- Every change goes through a branch and a pull request: `main` takes no push. The ruleset in
|
|
136
|
+
`.github/rulesets/main.json` enforces it, with the checks "Python 3.12", "Python 3.13",
|
|
137
|
+
"Python 3.14" and "Libraries released and pinned" required; its only bypass is the owner's,
|
|
138
|
+
and only for merging a pull request. A change to what a user gets - the library's code or
|
|
139
|
+
documentation - comes with its tests.
|
|
140
|
+
- Name every branch by the kind of change, as the release draft's labels follow the name;
|
|
141
|
+
`.github/rulesets/branch-names.json` refuses any other name. `feature/<what>` is labelled
|
|
142
|
+
`feature request`, `fix/<what>` is labelled `bug`, `docs/<what>` is labelled `documentation`,
|
|
143
|
+
and `chore/<what>` - CI, tooling, anything that stays in the repository - is labelled `chore`.
|
|
144
|
+
The release notes list features and fixes; documentation, chores and Dependabot's
|
|
145
|
+
`dependencies` are left out. A change to what a user installs, such as a new dependency, is a
|
|
146
|
+
`fix/` or a `feature/`, never a `chore/`.
|
|
147
|
+
- A pull request's text describes only its own change: what it does and how it was tested. Never
|
|
148
|
+
releases to come, merge order, or other repositories.
|
|
149
|
+
- Put `breaking-change` on a pull request that breaks the API - a `feature/` or `fix/` one, as a
|
|
150
|
+
chore is left out of the notes - and `minor` on one that needs a minor bump; both give a minor
|
|
151
|
+
bump, and a patch is the default. No label gives a major.
|
|
152
|
+
<!-- END HairingX/workflows -->
|