Python wrapper for DHIS2
Project description
A Python library for DHIS2 wrapping requests for general-purpose API interaction with DHIS2. It attempts to be useful for any data/metadata import tasks including various utilities like file loading, UID generation and logging. A strong focus is on JSON.
Supported and tested on Python 2 and 3 on Linux/macOS, Windows and DHIS2 versions >= 2.25.
1 Installation
1.1 with pipenv
Simply use pipenv:
pipenv install dhis2.py --upgrade
1.2 with pip
pip install dhis2.py --upgrade
For instructions on installing Python / pip for your operating system see The Hitchhiker’s Guide to Python.
2 Quickstart
Create an API object:
from dhis2 import Api
api = Api('play.dhis2.org/demo', 'admin', 'district')
Then run requests on it:
r = api.get('organisationUnits/Rp268JB6Ne4', params={'fields': 'id,name'})
print(r.json())
# { "name": "Adonkia CHP", "id": "Rp268JB6Ne4" }
r = api.post('metadata', json={'dataElements': [ ... ] })
print(r.status_code) # 200
api.get()
api.post()
api.put()
api.patch()
api.delete()
see below for more methods.
3 Usage
3.1 Getting things
3.2 Updating / deleting things
Normal methods:
api.post()
api.put()
api.patch()
api.delete()
3.2.1 Post partitioned payloads
If you have such a large payload (e.g. metadata imports) that you frequently get a HTTP Error: 413 Request Entity Too Large response e.g. from Nginx you might benefit from using the following method that splits your payload in partitions / chunks and posts them one-by-one. You define the amount of elements in each POST by specifying a number in thresh (default: 1000).
Note that it is only possible to submit one key per payload (e.g. dataElements only, not additionally organisationUnits in the same payload).
api.post_partitioned()
import json
data = {
"organisationUnits": [
{...},
{...} # very large number of org units
]
{
for response in api.post_partitioned('metadata', json=data, thresh=5000):
text = json.loads(response.text)
print('[{}] - {}'.format(text['status'], json.dumps(text['stats'])))
3.3 Multiple params with same key
If you need to pass multiple parameters to your request with the same key, you may submit as a list of tuples instead when e.g.:
r = api.get('dataValueSets', params=[
('dataSet', 'pBOMPrpg1QX'), ('dataSet', 'BfMAe6Itzgt'),
('orgUnit', 'YuQRtpLP10I'), ('orgUnit', 'vWbkYPRmKyS'),
('startDate', '2013-01-01'), ('endDate', '2013-01-31')
]
)
alternatively:
r = api.get('dataValueSets', params={
'dataSet': ['pBOMPrpg1QX', 'BfMAe6Itzgt'],
'orgUnit': ['YuQRtpLP10I', 'vWbkYPRmKyS'],
'startDate': '2013-01-01',
'endDate': '2013-01-31'
})
3.4 Utilities
3.4.1 Load JSON file
from dhis2 import load_json
json_data = load_json('/path/to/file.json')
print(json_data)
# { "id": ... }
3.4.2 Load CSV file
Via a Python generator:
from dhis2 import load_csv
for row in load_csv('/path/to/file.csv'):
print(row)
# { "id": ... }
Via a normal list, loaded fully into memory:
data = list(load_csv('/path/to/file.csv'))
3.4.3 Generate UID
Create UID:
uid = generate_uid()
print(uid)
# 'Rp268JB6Ne4'
If you need a list of 1000 UIDs:
uids = [generate_uid() for _ in range(1000)]
3.4.4 Validate UID
uid = 'MmwcGkxy876'
print(is_valid_uid(uid))
# True
uid = 25329
print(is_valid_uid(uid))
# False
uid = 'MmwcGkxy876 '
print(is_valid_uid(uid))
# False
3.4.5 Clean an object
Useful for removing e.g. all user or userGroupAccesses from an object.
from dhis2 import clean_obj
# obj = {
# "dataElements": [
# {
# "name": "GL- DE001",
# "user": {
# "id": "gONaRemoveThis"
# }
# }
# ]
# }
cleaned = clean_obj(obj, 'user')
print(cleaned)
# obj = {
# "dataElements": [
# {
# "name": "GL- DE001",
# }
# ]
# }
Submit more keys to remove by wrapping them into a list or set. This works recursively.
3.4.6 Print pretty JSON
Print easy-readable JSON objects with colors, utilizes Pygments.
from dhis2 import pretty_json
obj = {"dataElements": [{"name": "Accute Flaccid Paralysis (Deaths < 5 yrs)", "id": "FTRrcoaog83", "aggregationType": "SUM"}]}
pretty_json(obj)
… prints (in a terminal it will have colors):
{
"dataElements": [
{
"aggregationType": "SUM",
"id": "FTRrcoaog83",
"name": "Accute Flaccid Paralysis (Deaths < 5 yrs)"
}
]
}
3.5 Logging
Logging utilizes logzero.
Color output depending on log level
DHIS2 log format including the line of the caller
optional logfile= specifies a rotating log file path (20 x 10MB files)
from dhis2 import setup_logger, logger
setup_logger(logfile='/var/log/app.log')
logger.info('my log message')
logger.warning('missing something')
logger.error('something went wrong')
logger.exception('with stacktrace')
* INFO 2018-06-01 18:19:40,001 my log message [script:86] * ERROR 2018-06-01 18:19:40,007 something went wrong [script:87]
Use setup_logger(include_caller=False) if you want to remove [script:86] from logs.
3.6 Exceptions
There are two exceptions:
RequestException: DHIS2 didn’t like what you requested. See the exception’s code, url and description.
ClientException: Something didn’t work with the client not involving DHIS2.
They both inherit from Dhis2PyException.
4 Examples
Real-world script examples can be found in the examples folder.
dhis2.py is used in dhis2-pk (dhis2-pocket-knife)
5 Changelog
Versions changelog
6 Contribute
Feedback welcome!
Add issue
Install the dev environment (see below)
Fork, add changes to master branch, ensure tests pass with full coverage and add a Pull Request
pip install pipenv
git clone https://github.com/davidhuser/dhis2.py
cd dhis2.py
pipenv install --dev
pipenv run tests
7 License
dhis2.py’s source is provided under MIT license. See LICENCE for details.
Copyright (c), 2019, David Huser
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for dhis2.py-2.0.0-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 29a7490e2f337b7f490592270708a2e3a95b7437e14d24648590872094026319 |
|
MD5 | 1ca1cdf0cb7d9c6f350c9dc1b074fa96 |
|
BLAKE2b-256 | f143e0a85bbcd0edf4a3b6592121638c9cd7f678c29d4fedfff05ce656a48b12 |