Ejemplo n.º 1
0
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}"')
Ejemplo n.º 2
0
 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)
Ejemplo n.º 3
0
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