oehrpy 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.
Files changed (83) hide show
  1. oehrpy-0.1.0/.github/workflows/ci.yml +192 -0
  2. oehrpy-0.1.0/.github/workflows/publish.yml +87 -0
  3. oehrpy-0.1.0/.github/workflows/release.yml +44 -0
  4. oehrpy-0.1.0/.github/workflows-temp/fetch-webtemplate.yml +68 -0
  5. oehrpy-0.1.0/.gitignore +95 -0
  6. oehrpy-0.1.0/CHANGELOG.md +52 -0
  7. oehrpy-0.1.0/CLAUDE.md +219 -0
  8. oehrpy-0.1.0/CONTRIBUTING.md +227 -0
  9. oehrpy-0.1.0/INTEGRATION_TEST_ANALYSIS.md +235 -0
  10. oehrpy-0.1.0/INTEGRATION_TEST_STATUS.md +321 -0
  11. oehrpy-0.1.0/LICENSE +21 -0
  12. oehrpy-0.1.0/PKG-INFO +362 -0
  13. oehrpy-0.1.0/README.md +324 -0
  14. oehrpy-0.1.0/docker-compose.local.yml +48 -0
  15. oehrpy-0.1.0/docker-compose.yml +44 -0
  16. oehrpy-0.1.0/docs/FLAT_FORMAT_VERSIONS.md +310 -0
  17. oehrpy-0.1.0/docs/RESEARCH_FLAT_FORMAT_DISCOURSE.md +284 -0
  18. oehrpy-0.1.0/docs/adr/0000-record-architecture-decisions.md +19 -0
  19. oehrpy-0.1.0/docs/adr/0001-odin-parsing-and-rm-1.1.0-support.md +267 -0
  20. oehrpy-0.1.0/docs/adr/0002-integration-testing-with-ehrbase.md +369 -0
  21. oehrpy-0.1.0/docs/adr/0003-pre-commit-hooks-for-code-quality.md +153 -0
  22. oehrpy-0.1.0/docs/adr/0004-python-semantic-release-for-release-automation.md +104 -0
  23. oehrpy-0.1.0/docs/brand-kit.html +994 -0
  24. oehrpy-0.1.0/docs/docs.html +969 -0
  25. oehrpy-0.1.0/docs/ehrbase-issues/001-flat-format-documentation-gap.md +320 -0
  26. oehrpy-0.1.0/docs/ehrbase-issues/README.md +154 -0
  27. oehrpy-0.1.0/docs/flat-format-learnings.md +378 -0
  28. oehrpy-0.1.0/docs/index.html +548 -0
  29. oehrpy-0.1.0/docs/integration-testing-journey.md +437 -0
  30. oehrpy-0.1.0/docs/prd/PRD-0000-python-openehr-sdk.md +733 -0
  31. oehrpy-0.1.0/docs/prd/PRD-0001-odin-parser.md +557 -0
  32. oehrpy-0.1.0/examples/generate_builder_from_opt.py +83 -0
  33. oehrpy-0.1.0/fetch_webtemplate_from_ci.sh +99 -0
  34. oehrpy-0.1.0/generator/__init__.py +6 -0
  35. oehrpy-0.1.0/generator/bmm_parser.py +302 -0
  36. oehrpy-0.1.0/generator/generate_rm_1_1_0.py +212 -0
  37. oehrpy-0.1.0/generator/json_schema_parser.py +196 -0
  38. oehrpy-0.1.0/generator/pydantic_generator.py +471 -0
  39. oehrpy-0.1.0/init-db.sql +4 -0
  40. oehrpy-0.1.0/init-postgres.sql +7 -0
  41. oehrpy-0.1.0/pyproject.toml +104 -0
  42. oehrpy-0.1.0/src/openehr_sdk/__init__.py +49 -0
  43. oehrpy-0.1.0/src/openehr_sdk/aql/__init__.py +40 -0
  44. oehrpy-0.1.0/src/openehr_sdk/aql/builder.py +589 -0
  45. oehrpy-0.1.0/src/openehr_sdk/client/__init__.py +32 -0
  46. oehrpy-0.1.0/src/openehr_sdk/client/ehrbase.py +675 -0
  47. oehrpy-0.1.0/src/openehr_sdk/rm/__init__.py +17 -0
  48. oehrpy-0.1.0/src/openehr_sdk/rm/rm_types.py +1864 -0
  49. oehrpy-0.1.0/src/openehr_sdk/serialization/__init__.py +37 -0
  50. oehrpy-0.1.0/src/openehr_sdk/serialization/canonical.py +203 -0
  51. oehrpy-0.1.0/src/openehr_sdk/serialization/flat.py +372 -0
  52. oehrpy-0.1.0/src/openehr_sdk/templates/__init__.py +40 -0
  53. oehrpy-0.1.0/src/openehr_sdk/templates/builder_generator.py +421 -0
  54. oehrpy-0.1.0/src/openehr_sdk/templates/builders.py +432 -0
  55. oehrpy-0.1.0/src/openehr_sdk/templates/opt_parser.py +352 -0
  56. oehrpy-0.1.0/templates/.components/changelog_header.md.j2 +9 -0
  57. oehrpy-0.1.0/templates/.components/changelog_init.md.j2 +29 -0
  58. oehrpy-0.1.0/templates/.components/changelog_update.md.j2 +71 -0
  59. oehrpy-0.1.0/templates/.components/changes.md.j2 +129 -0
  60. oehrpy-0.1.0/templates/.components/first_release.md.j2 +18 -0
  61. oehrpy-0.1.0/templates/.components/macros.md.j2 +203 -0
  62. oehrpy-0.1.0/templates/.components/unreleased_changes.md.j2 +7 -0
  63. oehrpy-0.1.0/templates/.components/versioned_changes.md.j2 +20 -0
  64. oehrpy-0.1.0/templates/.release_notes.md.j2 +62 -0
  65. oehrpy-0.1.0/templates/CHANGELOG.md.j2 +21 -0
  66. oehrpy-0.1.0/test_flat_submission.sh +59 -0
  67. oehrpy-0.1.0/test_web_template.sh +62 -0
  68. oehrpy-0.1.0/tests/__init__.py +1 -0
  69. oehrpy-0.1.0/tests/fixtures/vital_signs.opt +4576 -0
  70. oehrpy-0.1.0/tests/integration/__init__.py +1 -0
  71. oehrpy-0.1.0/tests/integration/conftest.py +118 -0
  72. oehrpy-0.1.0/tests/integration/test_aql_queries.py +309 -0
  73. oehrpy-0.1.0/tests/integration/test_canonical_format.py +355 -0
  74. oehrpy-0.1.0/tests/integration/test_compositions.py +269 -0
  75. oehrpy-0.1.0/tests/integration/test_ehr_operations.py +87 -0
  76. oehrpy-0.1.0/tests/integration/test_round_trip.py +328 -0
  77. oehrpy-0.1.0/tests/test_aql.py +221 -0
  78. oehrpy-0.1.0/tests/test_flat.py +157 -0
  79. oehrpy-0.1.0/tests/test_rm_types.py +167 -0
  80. oehrpy-0.1.0/tests/test_serialization.py +180 -0
  81. oehrpy-0.1.0/tests/test_templates.py +292 -0
  82. oehrpy-0.1.0/web_template.json +1406 -0
  83. oehrpy-0.1.0/web_template_formatted.json +1406 -0
@@ -0,0 +1,192 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, develop ]
6
+ pull_request:
7
+ branches: [ main, develop ]
8
+
9
+ jobs:
10
+ lint:
11
+ name: Lint
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Set up Python
17
+ uses: actions/setup-python@v5
18
+ with:
19
+ python-version: "3.12"
20
+
21
+ - name: Install dependencies
22
+ run: |
23
+ python -m pip install --upgrade pip
24
+ pip install ruff
25
+
26
+ - name: Run ruff lint
27
+ run: ruff check .
28
+
29
+ - name: Run ruff format check
30
+ run: ruff format --check .
31
+
32
+ type-check:
33
+ name: Type Check
34
+ runs-on: ubuntu-latest
35
+ steps:
36
+ - uses: actions/checkout@v4
37
+
38
+ - name: Set up Python
39
+ uses: actions/setup-python@v5
40
+ with:
41
+ python-version: "3.12"
42
+
43
+ - name: Install dependencies
44
+ run: |
45
+ python -m pip install --upgrade pip
46
+ pip install -e ".[dev]"
47
+
48
+ - name: Run mypy
49
+ run: mypy src/openehr_sdk
50
+
51
+ test:
52
+ name: Unit Tests
53
+ runs-on: ubuntu-latest
54
+ steps:
55
+ - uses: actions/checkout@v4
56
+
57
+ - name: Set up Python
58
+ uses: actions/setup-python@v5
59
+ with:
60
+ python-version: "3.12"
61
+
62
+ - name: Install dependencies
63
+ run: |
64
+ python -m pip install --upgrade pip
65
+ pip install -e ".[dev]"
66
+ pip install pytest-cov
67
+
68
+ - name: Run unit tests with coverage
69
+ run: pytest tests/ -m "not integration" -v --tb=short --cov=src/openehr_sdk --cov-report=term-missing --cov-report=xml
70
+
71
+ - name: Upload coverage reports
72
+ if: env.CODECOV_TOKEN != ''
73
+ uses: codecov/codecov-action@v4
74
+ with:
75
+ file: ./coverage.xml
76
+ fail_ci_if_error: false
77
+ env:
78
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
79
+ continue-on-error: true
80
+
81
+ integration-test:
82
+ name: Integration Tests
83
+ runs-on: ubuntu-latest
84
+ # Only run on main/develop or PRs with 'integration' label
85
+ if: |
86
+ github.ref == 'refs/heads/main' ||
87
+ github.ref == 'refs/heads/develop' ||
88
+ contains(github.event.pull_request.labels.*.name, 'integration')
89
+
90
+ services:
91
+ postgres:
92
+ image: ehrbase/ehrbase-v2-postgres:16.2
93
+ env:
94
+ POSTGRES_USER: postgres
95
+ POSTGRES_PASSWORD: postgres
96
+ EHRBASE_USER: ehrbase
97
+ EHRBASE_PASSWORD: ehrbase
98
+ EHRBASE_USER_ADMIN: ehrbase_admin
99
+ EHRBASE_PASSWORD_ADMIN: ehrbase_admin
100
+ options: >-
101
+ --health-cmd "pg_isready -U postgres"
102
+ --health-interval 10s
103
+ --health-timeout 5s
104
+ --health-retries 5
105
+ ports:
106
+ - 5432:5432
107
+
108
+ steps:
109
+ - uses: actions/checkout@v4
110
+
111
+ - name: Set up Python
112
+ uses: actions/setup-python@v5
113
+ with:
114
+ python-version: "3.12"
115
+
116
+ - name: Install dependencies
117
+ run: |
118
+ python -m pip install --upgrade pip
119
+ pip install -e ".[dev]"
120
+
121
+ - name: Start EHRBase
122
+ run: |
123
+ docker run -d \
124
+ --name ehrbase \
125
+ --network host \
126
+ -e DB_URL=jdbc:postgresql://localhost:5432/ehrbase \
127
+ -e DB_USER=ehrbase \
128
+ -e DB_PASS=ehrbase \
129
+ -e DB_USER_ADMIN=ehrbase_admin \
130
+ -e DB_PASS_ADMIN=ehrbase_admin \
131
+ -e SECURITY_AUTHTYPE=BASIC \
132
+ -e SECURITY_AUTHUSER=ehrbase-user \
133
+ -e SECURITY_AUTHPASSWORD=SuperSecretPassword \
134
+ -e SECURITY_AUTHADMINUSER=ehrbase-admin \
135
+ -e SECURITY_AUTHADMINPASSWORD=EvenMoreSecretPassword \
136
+ ehrbase/ehrbase:2.26.0
137
+
138
+ - name: Wait for EHRBase
139
+ run: |
140
+ timeout 120 bash -c 'until curl -f -u ehrbase-user:SuperSecretPassword http://localhost:8080/ehrbase/rest/status; do echo "Waiting for EHRBase..."; sleep 5; done'
141
+ echo "EHRBase is ready!"
142
+
143
+ - name: Fetch Web Template for debugging
144
+ if: always()
145
+ continue-on-error: true
146
+ run: |
147
+ # Upload the template first (conftest.py does this in tests, but let's ensure it's there)
148
+ echo "Uploading template..."
149
+ curl -v -X POST -u ehrbase-user:SuperSecretPassword \
150
+ -H "Content-Type: application/xml" \
151
+ -H "Accept: */*" \
152
+ --data @tests/fixtures/vital_signs.opt \
153
+ http://localhost:8080/ehrbase/rest/openehr/v1/definition/template/adl1.4 || echo "Template upload may have failed or template already exists"
154
+
155
+ echo "Fetching Web Template (JSON format)..."
156
+ # Fetch the Web Template using the /webtemplate endpoint
157
+ curl -v -u ehrbase-user:SuperSecretPassword \
158
+ "http://localhost:8080/ehrbase/rest/definition/template/adl1.4/IDCR%20-%20Vital%20Signs%20Encounter.v1/webtemplate" \
159
+ -o web_template.json
160
+
161
+ # Check if file has content
162
+ if [ -s web_template.json ]; then
163
+ echo "Web Template file size: $(wc -c < web_template.json) bytes"
164
+ echo "First 100 chars:"
165
+ head -c 100 web_template.json
166
+ echo ""
167
+
168
+ # Try to pretty print (may fail if not JSON)
169
+ python3 -m json.tool web_template.json > web_template_formatted.json 2>&1 || \
170
+ cp web_template.json web_template_formatted.json
171
+ else
172
+ echo "Error: web_template.json is empty"
173
+ echo "ERROR: Failed to fetch web template" > web_template_formatted.json
174
+ fi
175
+
176
+ - name: Upload Web Template artifact
177
+ if: always()
178
+ uses: actions/upload-artifact@v4
179
+ with:
180
+ name: web-template
181
+ path: web_template*.json
182
+
183
+ - name: Run integration tests
184
+ run: pytest tests/ -m integration -v --tb=short
185
+ env:
186
+ EHRBASE_URL: http://localhost:8080/ehrbase
187
+ EHRBASE_USER: ehrbase-user
188
+ EHRBASE_PASSWORD: SuperSecretPassword
189
+
190
+ - name: Show EHRBase logs on failure
191
+ if: failure()
192
+ run: docker logs ehrbase
@@ -0,0 +1,87 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ # Allow manual trigger for testing
7
+ workflow_dispatch:
8
+ inputs:
9
+ target:
10
+ description: 'Target repository'
11
+ required: true
12
+ default: 'testpypi'
13
+ type: choice
14
+ options:
15
+ - testpypi
16
+ - pypi
17
+
18
+ jobs:
19
+ build:
20
+ name: Build distribution
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+
25
+ - name: Set up Python
26
+ uses: actions/setup-python@v5
27
+ with:
28
+ python-version: "3.12"
29
+
30
+ - name: Install build tools
31
+ run: |
32
+ python -m pip install --upgrade pip
33
+ pip install build twine
34
+
35
+ - name: Build package
36
+ run: python -m build
37
+
38
+ - name: Check package
39
+ run: python -m twine check dist/*
40
+
41
+ - name: Upload artifacts
42
+ uses: actions/upload-artifact@v4
43
+ with:
44
+ name: dist
45
+ path: dist/
46
+
47
+ publish-testpypi:
48
+ name: Publish to TestPyPI
49
+ needs: build
50
+ runs-on: ubuntu-latest
51
+ if: github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'testpypi'
52
+ environment:
53
+ name: testpypi
54
+ url: https://test.pypi.org/project/oehrpy/
55
+ permissions:
56
+ id-token: write
57
+ steps:
58
+ - name: Download artifacts
59
+ uses: actions/download-artifact@v4
60
+ with:
61
+ name: dist
62
+ path: dist/
63
+
64
+ - name: Publish to TestPyPI
65
+ uses: pypa/gh-action-pypi-publish@release/v1
66
+ with:
67
+ repository-url: https://test.pypi.org/legacy/
68
+
69
+ publish-pypi:
70
+ name: Publish to PyPI
71
+ needs: build
72
+ runs-on: ubuntu-latest
73
+ if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'pypi')
74
+ environment:
75
+ name: pypi
76
+ url: https://pypi.org/project/oehrpy/
77
+ permissions:
78
+ id-token: write
79
+ steps:
80
+ - name: Download artifacts
81
+ uses: actions/download-artifact@v4
82
+ with:
83
+ name: dist
84
+ path: dist/
85
+
86
+ - name: Publish to PyPI
87
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,44 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ permissions:
9
+ contents: write
10
+ issues: write
11
+ pull-requests: write
12
+
13
+ jobs:
14
+ release:
15
+ name: Semantic Release
16
+ runs-on: ubuntu-latest
17
+ if: github.repository == 'platzhersh/oehrpy'
18
+ concurrency:
19
+ group: release
20
+ cancel-in-progress: false
21
+
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ with:
25
+ fetch-depth: 0
26
+ token: ${{ secrets.GH_TOKEN }}
27
+
28
+ - name: Set up Python
29
+ uses: actions/setup-python@v5
30
+ with:
31
+ python-version: "3.12"
32
+
33
+ - name: Install dependencies
34
+ run: |
35
+ python -m pip install --upgrade pip
36
+ pip install python-semantic-release build
37
+
38
+ - name: Python Semantic Release
39
+ id: release
40
+ uses: python-semantic-release/python-semantic-release@v9
41
+ with:
42
+ github_token: ${{ secrets.GH_TOKEN }}
43
+ git_committer_name: "github-actions[bot]"
44
+ git_committer_email: "github-actions[bot]@users.noreply.github.com"
@@ -0,0 +1,68 @@
1
+ name: Fetch Web Template
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - feat/integration-testing-with-ehrbase
7
+
8
+ jobs:
9
+ fetch:
10
+ runs-on: ubuntu-latest
11
+ services:
12
+ postgres:
13
+ image: ehrbase/ehrbase-v2-postgres:16.2
14
+ env:
15
+ POSTGRES_DB: ehrbase
16
+ POSTGRES_USER: postgres
17
+ POSTGRES_PASSWORD: postgres
18
+ EHRBASE_USER: ehrbase
19
+ EHRBASE_PASSWORD: ehrbase
20
+ options: >-
21
+ --health-cmd "pg_isready -U postgres"
22
+ --health-interval 10s
23
+ --health-timeout 5s
24
+ --health-retries 5
25
+
26
+ steps:
27
+ - name: Start EHRBase
28
+ run: |
29
+ docker run -d --name ehrbase --network host \
30
+ -e DB_URL=jdbc:postgresql://localhost:5432/ehrbase \
31
+ -e DB_USER=ehrbase \
32
+ -e DB_PASS=ehrbase \
33
+ -e DB_USER_ADMIN=ehrbase \
34
+ -e DB_PASS_ADMIN=ehrbase \
35
+ -e SECURITY_AUTHTYPE=BASIC \
36
+ -e SECURITY_AUTHUSER=ehrbase-user \
37
+ -e SECURITY_AUTHPASSWORD=SuperSecretPassword \
38
+ -e SECURITY_AUTHADMINUSER=ehrbase-admin \
39
+ -e SECURITY_AUTHADMINPASSWORD=EvenMoreSecretPassword \
40
+ ehrbase/ehrbase:2.0.0
41
+
42
+ - name: Wait for EHRBase
43
+ run: |
44
+ for i in {1..30}; do
45
+ sleep 3
46
+ curl -sf -u ehrbase-user:SuperSecretPassword \
47
+ http://localhost:8080/ehrbase/rest/status && break || echo "Waiting..."
48
+ done
49
+
50
+ - name: Upload template
51
+ run: |
52
+ curl -X POST -u ehrbase-user:SuperSecretPassword \
53
+ -H "Content-Type: application/xml" \
54
+ -H "Accept: */*" \
55
+ --data @tests/fixtures/vital_signs.opt \
56
+ http://localhost:8080/ehrbase/rest/openehr/v1/definition/template/adl1.4 || true
57
+
58
+ - name: Fetch Web Template
59
+ run: |
60
+ curl -u ehrbase-user:SuperSecretPassword \
61
+ "http://localhost:8080/ehrbase/rest/openehr/v1/definition/template/adl1.4/IDCR%20-%20Vital%20Signs%20Encounter.v1" \
62
+ | python3 -m json.tool > web_template.json
63
+
64
+ - name: Upload artifact
65
+ uses: actions/upload-artifact@v3
66
+ with:
67
+ name: web-template
68
+ path: web_template.json
@@ -0,0 +1,95 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ *.egg-info/
24
+ .installed.cfg
25
+ *.egg
26
+
27
+ # PyInstaller
28
+ *.manifest
29
+ *.spec
30
+
31
+ # Installer logs
32
+ pip-log.txt
33
+ pip-delete-this-directory.txt
34
+
35
+ # Unit test / coverage reports
36
+ htmlcov/
37
+ .tox/
38
+ .nox/
39
+ .coverage
40
+ .coverage.*
41
+ .cache
42
+ nosetests.xml
43
+ coverage.xml
44
+ *.cover
45
+ *.py,cover
46
+ .hypothesis/
47
+ .pytest_cache/
48
+
49
+ # Translations
50
+ *.mo
51
+ *.pot
52
+
53
+ # Environments
54
+ .env
55
+ .venv
56
+ env/
57
+ venv/
58
+ ENV/
59
+ env.bak/
60
+ venv.bak/
61
+
62
+ # IDEs
63
+ .idea/
64
+ .vscode/
65
+ *.swp
66
+ *.swo
67
+ *~
68
+
69
+ # Jupyter Notebook
70
+ .ipynb_checkpoints
71
+
72
+ # mypy
73
+ .mypy_cache/
74
+ .dmypy.json
75
+ dmypy.json
76
+
77
+ # Pyre
78
+ .pyre/
79
+
80
+ # pytype
81
+ .pytype/
82
+
83
+ # ruff
84
+ .ruff_cache/
85
+
86
+ # OS
87
+ .DS_Store
88
+ Thumbs.db
89
+
90
+ # BMM repository clone (downloaded during generation)
91
+ generator/bmm/specifications-ITS-BMM/
92
+ generator/bmm-repo/
93
+
94
+ # JSON Schema repository clone (downloaded for RM 1.1.0 generation)
95
+ generator/specifications-ITS-JSON/
@@ -0,0 +1,52 @@
1
+ # CHANGELOG
2
+
3
+
4
+ ## v0.1.0 (2026-01-31)
5
+
6
+ ### Bug Fixes
7
+
8
+ - Install build module inside semantic-release Docker container (#17)
9
+ ([#17](https://github.com/platzhersh/oehrpy/pull/17),
10
+ [`23ced62`](https://github.com/platzhersh/oehrpy/commit/23ced6206b6f18ad8e55576c3201b0afdb60685a))
11
+
12
+ - Update FLAT format paths based on EHRBase 2.26.0 web template (#11)
13
+ ([#11](https://github.com/platzhersh/oehrpy/pull/11),
14
+ [`1a4d0aa`](https://github.com/platzhersh/oehrpy/commit/1a4d0aaca0640711ceef771e00ba5e16560ee523))
15
+
16
+ ### Documentation
17
+
18
+ - Add contribution guidelines (#14) ([#14](https://github.com/platzhersh/oehrpy/pull/14),
19
+ [`8b12373`](https://github.com/platzhersh/oehrpy/commit/8b123738235b96e226e356ff9a0484a056f639c8))
20
+
21
+ - Add OPT Parser documentation to GitHub Pages (#9)
22
+ ([#9](https://github.com/platzhersh/oehrpy/pull/9),
23
+ [`7ed27de`](https://github.com/platzhersh/oehrpy/commit/7ed27de53baaddc53c50e23cc4d4613495f339bf))
24
+
25
+ ### Features
26
+
27
+ - Add automated release workflow with python-semantic-release (#16)
28
+ ([#16](https://github.com/platzhersh/oehrpy/pull/16),
29
+ [`8201f6a`](https://github.com/platzhersh/oehrpy/commit/8201f6aadc9b7e008bcaf5d4a12c0880222852e1))
30
+
31
+ - Add complete OPT (Operational Template) support with builder generation (#8)
32
+ ([#8](https://github.com/platzhersh/oehrpy/pull/8),
33
+ [`f938e23`](https://github.com/platzhersh/oehrpy/commit/f938e23293db86c613b041e8301403367325b82c))
34
+
35
+ - Add GitHub Actions CI/CD workflow (#3) ([#3](https://github.com/platzhersh/oehrpy/pull/3),
36
+ [`ad43fdd`](https://github.com/platzhersh/oehrpy/commit/ad43fdd104dea399efdc013f718ee94f9df01ad5))
37
+
38
+ - Add PyPI publishing support (#13) ([#13](https://github.com/platzhersh/oehrpy/pull/13),
39
+ [`052e447`](https://github.com/platzhersh/oehrpy/commit/052e44759657f036114e7eab8a652b0cb0883aae))
40
+
41
+ - Implement features from PRD-0000 (#2) ([#2](https://github.com/platzhersh/oehrpy/pull/2),
42
+ [`829ea0b`](https://github.com/platzhersh/oehrpy/commit/829ea0bde75e20d1b72c4c2409c0ed0cb3084cfa))
43
+
44
+ - Set up GitHub Pages with landing page and brand kit (#4)
45
+ ([#4](https://github.com/platzhersh/oehrpy/pull/4),
46
+ [`aa65777`](https://github.com/platzhersh/oehrpy/commit/aa657770be4a2da13898c83b3bc21abe475f3ac3))
47
+
48
+ ### Testing
49
+
50
+ - Add integration test setup with ehrbase (#10)
51
+ ([#10](https://github.com/platzhersh/oehrpy/pull/10),
52
+ [`f1a2aa0`](https://github.com/platzhersh/oehrpy/commit/f1a2aa00669cf46b265a8209c9a012436de9a980))