comhom-sdk 0.1.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.
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: comhom-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The official SDK for integrating homelessness data into the Comhom Platform.
|
|
5
|
+
Author: Socialit
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: jsonschema~=4.25.1
|
|
13
|
+
Dynamic: author
|
|
14
|
+
Dynamic: classifier
|
|
15
|
+
Dynamic: description
|
|
16
|
+
Dynamic: description-content-type
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
Dynamic: requires-dist
|
|
19
|
+
Dynamic: requires-python
|
|
20
|
+
Dynamic: summary
|
|
21
|
+
|
|
22
|
+
# Uploading Answers with `comhom_sdk.py`
|
|
23
|
+
|
|
24
|
+
This guide is for end users who want to upload answer data to Comhom using a file.
|
|
25
|
+
|
|
26
|
+
Script location: `sdk/comhom_sdk.py`
|
|
27
|
+
|
|
28
|
+
## Before you start
|
|
29
|
+
|
|
30
|
+
You need:
|
|
31
|
+
|
|
32
|
+
- Python 3.10+
|
|
33
|
+
- A valid API key with permission to upload answers
|
|
34
|
+
- A data file in `.json` or `.csv` format
|
|
35
|
+
|
|
36
|
+
If needed, install dependency:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install jsonschema
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
When you generate an API key on the platform, it is downloaded as `comhom.key`. The SDK uses that filename by default for `--api-key-file`.
|
|
43
|
+
|
|
44
|
+
Your organization is resolved automatically from the API key — you do not pass an organization ID to the SDK.
|
|
45
|
+
|
|
46
|
+
## 1) Prepare your API key file
|
|
47
|
+
|
|
48
|
+
Create a plain text file (for example `comhom.key`) that contains only your key:
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
your-api-key-here
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 2) Prepare your answers file
|
|
55
|
+
|
|
56
|
+
You can use **JSON** or **CSV**.
|
|
57
|
+
|
|
58
|
+
Each row is one answer. Required fields:
|
|
59
|
+
|
|
60
|
+
| Field | Description |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `respondent_code` | Stable, pseudonymous identifier for the respondent |
|
|
63
|
+
| `question_code` | Code of the question being answered |
|
|
64
|
+
| `value` | The answer (format depends on question type; see below) |
|
|
65
|
+
| `answered_at` | Date the answer was collected (`YYYY-MM-DD`) |
|
|
66
|
+
| `consent_signed` | Whether the respondent consented to data use (`true` / `false`) |
|
|
67
|
+
|
|
68
|
+
### Question codes and values
|
|
69
|
+
|
|
70
|
+
Valid `question_code` values come from the Comhom question catalogue. Examples from the platform fixtures:
|
|
71
|
+
|
|
72
|
+
| `question_code` | Type | Example `value` |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| `sex_gender` | Single choice | `cisgender_woman` |
|
|
75
|
+
| `age` | Single choice | `25_34` |
|
|
76
|
+
| `nationality` | Single choice | `national_country` |
|
|
77
|
+
| `A2` | Date | `2026-01-10` |
|
|
78
|
+
| `A4` | Single choice | `programme_completion` |
|
|
79
|
+
| `A5` | Program | `housing_first` (your org's program code) |
|
|
80
|
+
| `A6` | Multiple choice | `["cm", "hn"]` |
|
|
81
|
+
|
|
82
|
+
**Value formats:**
|
|
83
|
+
|
|
84
|
+
- **Single choice** — one option code (for example `sex_gender` → `cisgender_woman`, or `age` → `25_34`).
|
|
85
|
+
- **Multiple choice** — a list of option codes (for example `A6` → `["cm", "hn"]`).
|
|
86
|
+
- **Date** — `YYYY-MM-DD` (for example `A2` → `2026-01-10`).
|
|
87
|
+
- **Program (A5)** — a program `code` from your organization (created on the platform first; not a global option).
|
|
88
|
+
|
|
89
|
+
Only rows with `consent_signed: true` are loaded.
|
|
90
|
+
|
|
91
|
+
### JSON format
|
|
92
|
+
|
|
93
|
+
Use either:
|
|
94
|
+
|
|
95
|
+
- A top-level array of answers, or
|
|
96
|
+
- An object with an `answers` array
|
|
97
|
+
|
|
98
|
+
Example — one beneficiary with micro- and meso-variable answers:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
[
|
|
102
|
+
{
|
|
103
|
+
"respondent_code": "hash_7f3a9c2e",
|
|
104
|
+
"question_code": "sex_gender",
|
|
105
|
+
"answered_at": "2026-06-15",
|
|
106
|
+
"consent_signed": true,
|
|
107
|
+
"value": "cisgender_woman"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"respondent_code": "hash_7f3a9c2e",
|
|
111
|
+
"question_code": "age",
|
|
112
|
+
"answered_at": "2026-06-15",
|
|
113
|
+
"consent_signed": true,
|
|
114
|
+
"value": "25_34"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"respondent_code": "hash_7f3a9c2e",
|
|
118
|
+
"question_code": "A2",
|
|
119
|
+
"answered_at": "2026-06-15",
|
|
120
|
+
"consent_signed": true,
|
|
121
|
+
"value": "2026-01-10"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"respondent_code": "hash_7f3a9c2e",
|
|
125
|
+
"question_code": "A5",
|
|
126
|
+
"answered_at": "2026-06-15",
|
|
127
|
+
"consent_signed": true,
|
|
128
|
+
"value": "housing_first"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"respondent_code": "hash_7f3a9c2e",
|
|
132
|
+
"question_code": "A6",
|
|
133
|
+
"answered_at": "2026-06-15",
|
|
134
|
+
"consent_signed": true,
|
|
135
|
+
"value": ["cm", "hn"]
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### CSV format
|
|
141
|
+
|
|
142
|
+
Required columns:
|
|
143
|
+
|
|
144
|
+
- `respondent_code`
|
|
145
|
+
- `question_code`
|
|
146
|
+
- `answered_at`
|
|
147
|
+
- `consent_signed`
|
|
148
|
+
- `value`
|
|
149
|
+
|
|
150
|
+
`answered_at` is the collection/snapshot date for each answer. If your source system does not track per-answer timestamps, set one date for the whole export.
|
|
151
|
+
|
|
152
|
+
Upload behavior:
|
|
153
|
+
|
|
154
|
+
- Duplicate rows in the same file for the same beneficiary/question/date: the **last row wins**.
|
|
155
|
+
- Same value as the latest known snapshot on or before that date: the row is **skipped** (safe to re-upload).
|
|
156
|
+
- Same date with a changed value: the existing snapshot is **updated**.
|
|
157
|
+
- New date with a changed value: a new history row is **created**.
|
|
158
|
+
|
|
159
|
+
Example:
|
|
160
|
+
|
|
161
|
+
```csv
|
|
162
|
+
respondent_code,question_code,answered_at,consent_signed,value
|
|
163
|
+
hash_7f3a9c2e,sex_gender,2026-06-15,true,cisgender_woman
|
|
164
|
+
hash_7f3a9c2e,age,2026-06-15,true,25_34
|
|
165
|
+
hash_7f3a9c2e,A2,2026-06-15,true,2026-01-10
|
|
166
|
+
hash_7f3a9c2e,A5,2026-06-15,true,housing_first
|
|
167
|
+
hash_7f3a9c2e,A6,2026-06-15,true,"[""cm"",""hn""]"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## 3) Run the upload
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
python3 sdk/comhom_sdk.py upload \
|
|
174
|
+
--input-file "/path/to/answers.json" \
|
|
175
|
+
--api-key-file comhom.key
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
If your input is CSV, just change `--input-file` to the CSV path.
|
|
179
|
+
|
|
180
|
+
By default, uploads go to **sandbox**. Add `--production` to target production.
|
|
181
|
+
|
|
182
|
+
## Generating synthetic answers (optional)
|
|
183
|
+
|
|
184
|
+
You can generate synthetic answers to a file using the platform's answer upload JSON schema. The SDK fetches the org-specific schema automatically using your API key. Generation is separate from upload: write a file with `generate`, then upload it with `upload`.
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
python3 sdk/comhom_sdk.py generate \
|
|
188
|
+
--total-answers 1000 \
|
|
189
|
+
--respondent-count 20 \
|
|
190
|
+
--output-file "/path/to/synthetic_answers.json" \
|
|
191
|
+
--api-key-file comhom.key
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
To upload the generated file:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
python3 sdk/comhom_sdk.py upload \
|
|
198
|
+
--input-file "/path/to/synthetic_answers.json" \
|
|
199
|
+
--api-key-file comhom.key
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
The output format is determined by the extension:
|
|
203
|
+
|
|
204
|
+
- `.json` -> JSON array
|
|
205
|
+
- `.csv` -> CSV with the required columns
|
|
206
|
+
|
|
207
|
+
## Command options
|
|
208
|
+
|
|
209
|
+
### `upload`
|
|
210
|
+
|
|
211
|
+
| Option | Short | Required | Description |
|
|
212
|
+
|---|---|---|---|
|
|
213
|
+
| `--input-file` | `-i` | Yes | Path to `.json` or `.csv` file |
|
|
214
|
+
| `--api-key-file` | `-k` | No | Path to API key file (default: `comhom.key`) |
|
|
215
|
+
| `--production` | `-p` | No | Upload to production (default is sandbox) |
|
|
216
|
+
| `--batch-size` | `-b` | No | Answers per request (default `500`) |
|
|
217
|
+
|
|
218
|
+
### `generate`
|
|
219
|
+
|
|
220
|
+
| Option | Short | Required | Description |
|
|
221
|
+
|---|---|---|---|
|
|
222
|
+
| `--total-answers` | `-n` | Yes | Number of synthetic answers to generate |
|
|
223
|
+
| `--output-file` | `-o` | Yes | Path to write `.json` or `.csv` output |
|
|
224
|
+
| `--respondent-count` | `-c` | No | Number of respondent codes to use (default `1`) |
|
|
225
|
+
| `--respondent-prefix` | `-p` | No | Prefix for respondent codes (default `R`) |
|
|
226
|
+
| `--answered-at` | `-a` | No | Fixed answered date (`YYYY-MM-DD`) for all answers |
|
|
227
|
+
| `--days-back` | `-d` | No | If `--answered-at` is not set, random date within last N days (default `365`; use `0` for today only) |
|
|
228
|
+
| `--seed` | `-s` | No | Seed for deterministic generation |
|
|
229
|
+
| `--api-key-file` | `-k` | No | Path to API key file (default: `comhom.key`) |
|
|
230
|
+
|
|
231
|
+
### `validate`
|
|
232
|
+
|
|
233
|
+
| Option | Short | Required | Description |
|
|
234
|
+
|---|---|---|---|
|
|
235
|
+
| `--input-file` | `-i` | Yes | Path to `.json` or `.csv` file |
|
|
236
|
+
| `--api-key-file` | `-k` | No | Path to API key file (default: `comhom.key`) |
|
|
237
|
+
| `--errors-file` | `-e` | No | Write all validation errors to a CSV file when validation fails |
|
|
238
|
+
|
|
239
|
+
### `delete`
|
|
240
|
+
|
|
241
|
+
| Option | Short | Required | Description |
|
|
242
|
+
|---|---|---|---|
|
|
243
|
+
| `--respondent-code` | `-r` | Yes | Beneficiary/respondent code whose answers to delete |
|
|
244
|
+
| `--api-key-file` | `-k` | No | Path to API key file (default: `comhom.key`) |
|
|
245
|
+
| `--production` | `-p` | No | Delete production data instead of sandbox (default is sandbox) |
|
|
246
|
+
|
|
247
|
+
## What the script does
|
|
248
|
+
|
|
249
|
+
### `upload`
|
|
250
|
+
|
|
251
|
+
1. Read your API key from file
|
|
252
|
+
2. Read and parse your JSON/CSV answers
|
|
253
|
+
3. Download the current upload schema from the platform using your API key (includes org-specific enums such as A5 program codes)
|
|
254
|
+
4. Validate your file locally before sending
|
|
255
|
+
5. Upload answers in batches
|
|
256
|
+
|
|
257
|
+
### `generate`
|
|
258
|
+
|
|
259
|
+
1. Fetch the answer upload JSON schema from the platform using your API key
|
|
260
|
+
2. Generate synthetic answers that conform to the schema
|
|
261
|
+
3. Write them to a JSON or CSV file
|
|
262
|
+
|
|
263
|
+
### `validate`
|
|
264
|
+
|
|
265
|
+
1. Read and parse your JSON/CSV answers
|
|
266
|
+
2. Download the current upload schema from the platform using your API key
|
|
267
|
+
3. Validate every answer row locally without uploading
|
|
268
|
+
|
|
269
|
+
Example:
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
python3 sdk/comhom_sdk.py validate \
|
|
273
|
+
--input-file "/path/to/answers.json" \
|
|
274
|
+
--api-key-file comhom.key \
|
|
275
|
+
--errors-file errors.csv
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### `delete`
|
|
279
|
+
|
|
280
|
+
1. Read your API key from file
|
|
281
|
+
2. Resolve your organization from the API key
|
|
282
|
+
3. Delete all answers for the given `respondent_code` in sandbox or production
|
|
283
|
+
|
|
284
|
+
Example:
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
python3 sdk/comhom_sdk.py delete \
|
|
288
|
+
--respondent-code hash_7f3a9c2e \
|
|
289
|
+
--api-key-file comhom.key
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Success and errors
|
|
293
|
+
|
|
294
|
+
- On success, upload returns counts for `created`, `updated`, and `skipped` rows.
|
|
295
|
+
- On failure, you will see an error message and no further batches are sent.
|
|
296
|
+
- When `validate` fails, use `--errors-file` to export every error row for review.
|
|
297
|
+
|
|
298
|
+
Common issues:
|
|
299
|
+
|
|
300
|
+
- Wrong API key or no permission
|
|
301
|
+
- Missing required columns in CSV
|
|
302
|
+
- Invalid date format (must be `YYYY-MM-DD`)
|
|
303
|
+
- `consent_signed` not set to `true`
|
|
304
|
+
- Invalid `question_code` or option code for that question
|
|
305
|
+
- A5 `value` not matching a program code in your organization
|
|
306
|
+
- Extra/invalid fields that do not match schema
|
|
307
|
+
|
|
308
|
+
## Notes
|
|
309
|
+
|
|
310
|
+
- By default, uploads go to sandbox.
|
|
311
|
+
- Use `--production` (or `-p`) to upload to or delete from production.
|
|
312
|
+
- The API key file defaults to `comhom.key` if `--api-key-file` is omitted.
|
|
313
|
+
- Client-side schema validation checks structure and required fields before upload.
|
|
314
|
+
- Question-specific `value` validation is finalized by the server during upload.
|
|
315
|
+
- Keep `comhom.key` out of source control.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
comhom_sdk.py,sha256=dOZppbdpHpSY7C5qLUjR0-WPOMmDgQ6NzwaBPkeJwck,46711
|
|
2
|
+
comhom_sdk-0.1.0.dist-info/licenses/LICENSE,sha256=ssp_yhT70JjhePrSrWhsyqFuaByX_As-yXPQ5ryV8qk,1065
|
|
3
|
+
comhom_sdk-0.1.0.dist-info/METADATA,sha256=XpYd_vYS2uRDqpG9_8pzG9Q-rvLfz4GIqNmciAQhRjQ,9845
|
|
4
|
+
comhom_sdk-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
5
|
+
comhom_sdk-0.1.0.dist-info/top_level.txt,sha256=vncKMaRwJcNCh1m_YQfza50f07d4bqwX_bTSPwhdWM0,11
|
|
6
|
+
comhom_sdk-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Socialit
|
|
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 @@
|
|
|
1
|
+
comhom_sdk
|