class Dhis2Extractor(object): """This class fetches DHIS2 data using the dhis2 library and outputs it in various formats.""" FORMAT_CSV = "csv" def __init__(self, url, *, username, password): # Let's re-use an existing library instead of maintaining our own self._api = Api(url, username, password) def extract_organisation_units(self, *, fields=":all", output_format, output_path): """ Extract organisation units. Methods should always expose parameters subject to changes, such as field names and output options. :param fields: :param output_format: :param output_path: :return: """ try: response_data = self._api.get_paged("organisationUnits", params={"fields": fields}, merge=True) except RequestException as e: # Always handle exceptions raise Dhis2ExtractorException( # Prefer f-strings to concatenation / string interpolation f"An error occurred while fetching DHIS2 data (URL: {e.url}, status code: {e.code})" ) organisation_units = response_data["organisationUnits"] dataframe = pd.DataFrame.from_dict(organisation_units) return self._dump(dataframe, output_format=output_format, output_path=output_path) def _dump(self, dataframe, *, output_format, output_path): if output_format == self.FORMAT_CSV: return dataframe.to_csv(output_path) raise NotImplementedError(f'Unknown output format "{output_format}"')
def make_category_options_public(self, credentials): api = Api(credentials.url, credentials.login, credentials.password) for page in api.get_paged("categoryOptions", params={"fields": ":all"}, page_size=100): for category_option in page["categoryOptions"]: if category_option["name"] != "default": try: api.post( "sharing?type=categoryOption&id=" + category_option["id"], { "meta": {"allowPublicAccess": True, "allowExternalAccess": False}, "object": { "id": category_option["id"], "name": category_option["name"], "displayName": category_option["displayName"], "publicAccess": "rwrw----", "user": category_option["user"], "externalAccess": False, }, }, ) except Exception as e: print("Failed to fix ", category_option["name"], e)
class Dhis2Client: def __init__(self, *, url, username, password, verbose=False): self._api = Api(url, username, password) self.name = url self.verbose = verbose def fetch_info(self): info = self._api.get_info() self.name = info["systemName"] return info def fetch_data_elements(self): results = [] for page in self._api.get_paged("dataElements", params={"fields": ":all"}, page_size=100): if self.verbose: logger.info( "sync_log %s: page from data_elements %s", self.name, page.get("pager"), ) results.extend( [DataElementResult(data) for data in page["dataElements"]]) return results def fetch_datasets(self): results = [] for page in self._api.get_paged("dataSets", params={"fields": ":all"}, page_size=100): if self.verbose: logger.info("sync_log %s: page from datasets %s", self.name, page.get("pager")) results.extend([DataSetResult(data) for data in page["dataSets"]]) return results def fetch_indicator_types(self): results = [] for page in self._api.get_paged("indicatorTypes", params={"fields": ":all"}, page_size=100): if self.verbose: logger.info( "sync_log %s: page from indicator_types %s", self.name, page.get("pager"), ) results.extend( [IndicatorTypeResult(data) for data in page["indicatorTypes"]]) return results def fetch_indicators(self): results = [] for page in self._api.get_paged("indicators", params={"fields": ":all"}, page_size=100): if self.verbose: logger.info("sync_log %s: page from indicators %s", self.name, page.get("pager")) results.extend( [IndicatorResult(data) for data in page["indicators"]]) return results def fetch_organisation_units(self): results = [] for page in self._api.get_paged("organisationUnits", params={"fields": ":all"}, page_size=100): if self.verbose: logger.info( "sync_log %s: page from organisation_units %s", self.name, page.get("pager"), ) # rewrite path -> replace "/" by "." for correct ltree path # warning: in place edit, can side effect on tests for element in page["organisationUnits"]: if "path" in element: element["path"] = element["path"].replace("/", ".").strip(".") results.extend([ OrganisationUnitResult(data) for data in page["organisationUnits"] ]) return results