Python wrapper for DHIS2
Project description
A Python library for DHIS2 wrapping requests.
Common HTTP operations (GET, POST, PUT, PATCH, DELETE)
Additional utilities like paging with GET or partitioned POSTs
SQL Views
Server-side UID generation
CSV/JSON file loading
Defaults to json, supported GETs: xml, csv, pdf, xls
logzero for logging
Supported and tested on Python 2.7, 3.4-3.7 and DHIS2 versions >= 2.25
Installation
Simply use pipenv (or pip):
pipenv install dhis2.py --upgrade
For instructions on installing Python / pip see The Hitchhiker’s Guide to Python.
Quickstart
Create an API object:
from dhis2 import Dhis
api = Dhis('play.dhis2.org/demo', 'admin', 'district', api_version=29, user_agent='myApp/0.1')
optional arguments:
api_version: DHIS2 API version
user_agent: submit your own User-Agent header
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()
Examples
Real-world script examples can be found in the examples folder.
Get info about the DHIS2 instance
print(api.version)
# '2.29'
print(api.version_int)
# 29
print(api.revision)
# '17f7f0b'
print(api.api_url)
# 'https://play.dhis2.org/2.29/api/29'
Load authentication from file
Load from a auth JSON file in order to not store credentials in scripts. Must have the following structure:
{
"dhis": {
"baseurl": "https://play.dhis2.org/demo",
"username": "admin",
"password": "district"
}
}
from dhis2 import Dhis
api = Dhis.from_auth_file('path/to/auth.json', api_version=29, user_agent='myApp/1.0')
If no file path is specified, it tries to find a file called dish.json in:
the DHIS_HOME environment variable
your Home folder
API paging
Paging for larger GET requests.
Two possible ways:
Process every page as they come in:
for page in api.get_paged('organisationUnits', page_size=100):
print(page)
# { "organisationUnits": [ {...}, {...} ] } (100 organisationUnits)
Load all pages before proceeding (this may take a long time) - to do this, do not use for and add merge=True:
all_pages = api.get_paged('organisationUnits', page_size=100, merge=True):
print(all_pages)
# { "organisationUnits": [ {...}, {...} ] } (all organisationUnits)
Note: Returns directly a JSON object, not a requests.response object unlike normal GETs.
Multiple params
You may submit params as a list of tuples instead when you need to pass multiple parameters with the same key, e.g.:
r = api.get('dataValueSets', params=[
('dataSet', 'pBOMPrpg1QX'), ('dataSet', 'BfMAe6Itzgt'),
('orgUnit', 'YuQRtpLP10I'), ('orgUnit', 'vWbkYPRmKyS'),
('startDate', '2013-01-01'), ('endDate', '2013-01-31')
]
)
or
r = api.get('dataValueSets', params={
'dataSet': ['pBOMPrpg1QX', 'BfMAe6Itzgt'],
'orgUnit': ['YuQRtpLP10I', 'vWbkYPRmKyS'],
'startDate': '2013-01-01',
'endDate': '2013-01-31'
})
SQL Views
Get SQL View data as if you’d open a CSV file, optimized for larger payloads:
# poll a sqlView of type VIEW or MATERIALIZED_VIEW:
for row in api.get_sqlview('YOaOY605rzh', execute=True, criteria={'name': '0-11m'}):
print(row)
# {'code': 'COC_358963', 'name': '0-11m'}
# similarly, poll a sqlView of type QUERY:
for row in api.get_sqlview('qMYMT0iUGkG', var={'valueType': 'INTEGER'}):
print(row)
# if you want a list directly, cast it to a ``list`` or add ``merge=True``:
data = list(api.get_sqlview('qMYMT0iUGkG', var={'valueType': 'INTEGER'}))
# OR
# data = api.get_sqlview('qMYMT0iUGkG', var={'valueType': 'INTEGER'}, merge=True)
Note: Returns directly a JSON object, not a requests.response object unlike normal GETs.
Beginning of 2.26 you can also use normal filtering on sqlViews. In that case, it’s recommended to use the stream=True parameter of the Dhis.get() method.
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).
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'])))
Generate UIDs
Create UIDs on the server (not limited to 10000):
uids = api.generate_uids(20000)
print(uids)
# ['Rp268JB6Ne4', 'fa7uwpCKIwa', ... ]
If you want UIDs generated locally (no server calls), add local=True.
GET other content types
Usually defaults to JSON but you can get other file types:
r = api.get('organisationUnits/Rp268JB6Ne4', file_type='xml')
print(r.text)
# <?xml version='1.0' encoding='UTF-8'?><organisationUnit ...
r = api.get('organisationUnits/Rp268JB6Ne4', file_type='pdf')
with open('/path/to/file.pdf', 'wb') as f:
f.write(r.content)
Load a JSON file
from dhis2 import load_json
json_data = load_json('/path/to/file.json')
print(json_data)
# { "id": ... }
Load a CSV file
from dhis2 import load_csv
for row in load_csv('/path/to/file.csv'):
print(row)
# { "id": ... }
# or for a normal list
data = list(load_csv('/path/to/file.csv'))
Logging
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.warn('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]
Pretty JSON
Print easy-readable JSON objects with colors.
obj = {"dataElements": [{"name": "Accute Flaccid Paralysis (Deaths < 5 yrs)", "id": "FTRrcoaog83", "aggregationType": "SUM"}]}
pretty_json(obj)
{
"dataElements": [
{
"aggregationType": "SUM",
"id": "FTRrcoaog83",
"name": "Accute Flaccid Paralysis (Deaths < 5 yrs)"
}
]
}
Exceptions
There are two exceptions:
APIException: 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.
Contribute
Feedback welcome!
Check the changelog
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
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
File details
Details for the file dhis2.py-1.6.1.tar.gz
.
File metadata
- Download URL: dhis2.py-1.6.1.tar.gz
- Upload date:
- Size: 15.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.9.1 pkginfo/1.4.1 requests/2.18.4 setuptools/39.0.1 requests-toolbelt/0.8.0 tqdm/4.19.5 CPython/2.7.12
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | e1ff2698e16f9bd10c3b5cd75235c7339887211c7614b6853d16da6b91496c6c |
|
MD5 | b5da110bad10746deb2bcef88a21da57 |
|
BLAKE2b-256 | 5d7fd888beade3c8cbb44080fef72ed68f11c873f2794dd12b91050b222239b8 |
Provenance
File details
Details for the file dhis2.py-1.6.1-py2.py3-none-any.whl
.
File metadata
- Download URL: dhis2.py-1.6.1-py2.py3-none-any.whl
- Upload date:
- Size: 17.8 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.9.1 pkginfo/1.4.1 requests/2.18.4 setuptools/39.0.1 requests-toolbelt/0.8.0 tqdm/4.19.5 CPython/2.7.12
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6a650a65cc7f58876e6c2e4639f58147233822e2883051ddfa9c64d717fd2c58 |
|
MD5 | 9985fccc72761fd38a752c4bc5374cc8 |
|
BLAKE2b-256 | 7209b2cf378ab9171d3b26717162a933115b33e50709872190c2a424f64d5cf5 |