Пример #1
0
    def test_QueryExecutionerWorkflow(sample_queries):
        qExec = QueryExecutioner()

        assert (qExec.endpoint == "https://api-next.datengui.de/graphql"
                ), "Default endpoint is wrong"

        res_query1 = qExec.run_query(sample_queries.data_query1)
        assert res_query1 is not None, "query did not return results"

        assert len(
            res_query1.query_results) > 0, "query did not return results"
        assert (type(res_query1.query_results) is
                dict), "query results are not a python json representation"

        assert type(res_query1.meta_data) == dict, "meta data not a dict"
        assert len(res_query1.meta_data) > 0, "meta data absent"
        assert len(res_query1.meta_data) == 1, "too much meta data"

        assert "BEVMK3" in res_query1.meta_data, "statistic absend"
        assert (res_query1.meta_data["BEVMK3"] !=
                "NO DESCRIPTION FOUND"), "descrption was not obtained"

        info = qExec.get_type_info("Region")
        assert info.kind == "OBJECT", "Region should be an object"
        assert info.enum_values is None, "Region doesn't have enum values"
        assert type(info.fields) == dict, "Fields should be a dict"

        stat_args = info.fields["BEVMK3"].get_arguments()
        assert len(stat_args) > 0
        assert "statistics" in stat_args

        enum_vals = qExec.get_type_info("BEVMK3Statistics").enum_values
        assert type(enum_vals) == dict, "Enum values should be dict"
        assert len(enum_vals) > 0, "Enums should have values"
Пример #2
0
def test_build_execute_transform_integration_all_regions(query_all_regions):
    """
    Smoke test covering all_regions
    """
    q_exec = QueryExecutioner()

    res = q_exec.run_query(query_all_regions)

    output_transf = QueryOutputTransformer(res)
    output_transf.transform()
Пример #3
0
def test_build_execute_transform_integration_multi_region(query_multi_regions):
    """
    Smoke test covering multiple regions in
    region query.
    """

    q_exec = QueryExecutioner()

    res = q_exec.run_query(query_multi_regions)

    output_transf = QueryOutputTransformer(res)
    output_transf.transform()
Пример #4
0
def test_get_type_info_caches_results(type_request_response):
    req_mock, expected_result = type_request_response
    qe = QueryExecutioner()
    qe._send_request = req_mock
    qe.__class__._META_DATA_CACHE = dict()  # clear cache
    assert ("BEVMK3Statistics" not in qe.__class__._META_DATA_CACHE
            ), "statistics should not be in cache"
    res = qe.get_type_info("BEVMK3Statistics")
    assert res == expected_result, "incorrect response processing"
    qe._send_request.assert_called_once()
    assert "BEVMK3Statistics" in qe.__class__._META_DATA_CACHE
    assert (qe.__class__._META_DATA_CACHE["BEVMK3Statistics"] ==
            expected_result), "cache results are wrong"
Пример #5
0
 def _get_return_type(self, fieldname):
     return (
         QueryExecutioner()
         .get_type_info(self.return_type)
         .fields[fieldname]
         .get_return_type()
     )
Пример #6
0
def test_create_stat_desc_dic(sample_stat_meta_response):
    desc_dict = QueryExecutioner._create_stat_desc_dic(
        sample_stat_meta_response)
    assert desc_dict["AENW01"][
        0] == "Description 1", "first dict entry is wrong"
    assert (desc_dict["AENW02"][0] == "NO DESCRIPTION FOUND"
            ), "second dict entry is wrong"
Пример #7
0
    def results(self,
                verbose_statistics: bool = False,
                verbose_enums: bool = False) -> DataFrame:
        """Runs the query and returns a Pandas DataFrame with the results.
           It also fills the instance variable result_meta_data with meta
           data specific to the query instance.

        Arguments:
            verbose_statistics -- Toggles whether statistic column names
            displayed with their short description in the result data frame
            verbose_enums -- Toggles whether enum values are displayed
            with their short description in the result data frame

        :raises RuntimeError: If the query fails raise RuntimeError.
        :return: A DataFrame with the queried data.
        :rtype: DataFrame
        """

        result = QueryExecutioner(statistics_meta_data_provider=self.
                                  _stat_meta_data_provider).run_query(self)
        if result:
            # It is currently assumed that all graphql queries
            # that are generated internally for the Query instance
            # at hand yield the same meta data.
            self.result_meta_data = result[0].meta_data
            return QueryOutputTransformer(result).transform(
                verbose_statistic_names=verbose_statistics,
                verbose_enum_values=verbose_enums,
            )
        else:
            raise RuntimeError("No results could be returned for this Query.")
Пример #8
0
def test_generate_post_json(sample_queries):
    post_jsons = QueryExecutioner._generate_post_json(
        sample_queries.data_query1)
    sample_queries.data_query1.get_graphql_query.assert_called_once()
    assert "query" in post_jsons[0], "post jsons does not contain a query key"
    assert (
        post_jsons[0]["query"] == sample_queries.data_query1.get_graphql_query.
        return_value[0]), "query not part of the post json"
Пример #9
0
    def get_info(field: str = None) -> Optional[TypeMetaData]:
        """Get information on a specific field.
        If field is not specified return meta data for
        all statistics that can be queried.

        Arguments:
            field -- the field to get information on. If None,
            then information on all possible fields of a query are
            returned.

        Returns:
            Optional[TypeMetaData] -- Response from QueryExecutioner on meta data info
        """
        if field:
            return QueryExecutioner().get_type_info(field)
        else:
            return QueryExecutioner().get_type_info(Query._return_type_region)
Пример #10
0
    def enum_info(self) -> Optional[str]:
        """Get information on possible enum vaules for field.

        :return:  Possible enum values for the field as string.
        :rtype: Optional[str]
        """

        meta = QueryExecutioner().get_type_info(self.name)
        return Field._no_none_values(self._enum_info_helper, meta, "enum_values")
Пример #11
0
def test_filter_stat_metatdata(sample_stat_meta_response):
    processed_stat_meta = QueryExecutioner._process_stat_meta_data(
        sample_stat_meta_response)
    assert all(
        all(("name" in stat, "description" in stat, "args" in stat))
        for stat in processed_stat_meta)
    assert all(
        any(arg["name"] == "statistics" for arg in field["args"])
        for field in processed_stat_meta)
    assert len(processed_stat_meta) == 2, "too many fields filtered out"
Пример #12
0
def save_result_files_from_query(query, name, result_path):
    """
        Helper function that for the construction of files
        to be loaded by `construct_execution_results`
    """
    qe = QueryExecutioner()
    execution_results = qe.run_query(query)

    query_json_file = os.path.join(result_path, f"{name}_query.json")
    result_json_file = os.path.join(result_path, f"{name}.json")
    meta_json_file = os.path.join(result_path, f"{name}_meta.json")

    with open(query_json_file, "w") as file:
        json.dump(query.get_graphql_query(), file)

    with open(result_json_file, "w") as file:
        json.dump([res.query_results for res in execution_results], file)

    with open(meta_json_file, "w") as file:
        json.dump(execution_results[0].meta_data, file)
Пример #13
0
    def results(
        self,
        verbose_statistics: bool = False,
        verbose_enums: bool = False,
        add_units: bool = False,
        remove_duplicates: bool = True,
    ) -> DataFrame:
        """Runs the query and returns a Pandas DataFrame with the results.
           It also fills the instance variable result_meta_data with meta
           data specific to the query instance.

        :param verbose_statistics: Toggles whether statistic column names
            displayed with their short description in the result data frame
        :param verbose_enums: Toggles whether enum values are displayed
            with their short description in the result data frame
        :param add_units: Adds units available in the metadata to the
            result dataframe. Care should be taken, because not every
            statistic specifies these corretly. When in doubt one should
            refer to the statistic description.
        :param remove_duplicates: Removes duplicates from query results, i.e. if the
            exact same number has been reported for the same statistic, year, region
            etc. from the same source it gets removed. Such duplications are sometimes
            caused on the API side and this is convenience functionality to remove them.
            The removal happens before potentially joining several different statistics.
            Unless diagnosing the API the default (True) is generally in the users
            interest.

        :raises RuntimeError: If the query fails raise RuntimeError.
        :return: A DataFrame with the queried data.
        :rtype: DataFrame
        """
        if not self._contains_statistic_field():
            raise Exception(
                "No statistic field is defined in query, please add statistic field "
                "via method add_field.")

        result = QueryExecutioner(statistics_meta_data_provider=self.
                                  _stat_meta_data_provider).run_query(self)
        if result:
            # It is currently assumed that all graphql queries
            # that are generated internally for the Query instance
            # at hand yield the same meta data.
            if self._query_result_contains_undefined_region(result):
                raise ValueError("Queried region is invalid.")
            self.result_meta_data = result[0].meta_data
            return QueryOutputTransformer(result).transform(
                verbose_statistic_names=verbose_statistics,
                verbose_enum_values=verbose_enums,
                add_units=add_units,
                remove_duplicates=remove_duplicates,
            )
        else:
            raise RuntimeError("No results could be returned for this Query.")
Пример #14
0
def get_statistics(search: Optional[str] = None) -> pd.DataFrame:
    stat_descr = QueryExecutioner().get_stat_descriptions()
    stat_frame = pd.DataFrame(
        [(stat, *stat_descr[stat]) for stat in stat_descr],
        columns=["statistics", "short_description", "long_description"],
    )
    if search is not None:
        search_string = cast(str, search)  # noqa: F841
        return stat_frame.query(
            "short_description.str.contains(@search_string,case=False)")
    else:
        return stat_frame
Пример #15
0
    def description(self) -> Optional[str]:
        """Get description of field.

        :return: Description of the field as string.
        :rtype: Optional[str]
        """

        parent = self.parent_field
        if parent is not None:
            meta = QueryExecutioner().get_type_info(parent.return_type)
            return Field._no_none_values(self._description_helper, meta, "fields")
        else:
            return None
Пример #16
0
    def arguments_info(self) -> Optional[str]:
        """Get information on possible arguments for field. The name of the argument is
        followed by the kind and name of the input type for the argument in brackets.
        If the argument is a list, the kind and name of the list elements are
        included in the brackets as well.

        :return: Possible arguments for the field as string and their input types.
        :rtype: Optional[str]
        """

        parent = self.parent_field
        if parent is not None:
            meta = QueryExecutioner().get_type_info(parent.return_type)
            return Field._no_none_values(self._arguments_info_helper, meta, "fields")
        else:
            return None
Пример #17
0
    def meta_data(self) -> QueryResultsMeta:
        """Runs the query and returns a Dict with the meta data of the queries results.

        :raises RuntimeError: If the Query did not return any results.
        E.g. if the Query was ill-formed.
        :return: A Dict with the queried meta data.
            If the query fails raise RuntimeError.
        :rtype: Union[Dict[str, Any], List[Dict[str, Any]]]
        """

        result = QueryExecutioner(statistics_meta_data_provider=self.
                                  _stat_meta_data_provider).run_query(self)
        if result:
            # TODO: correct indexing?
            return result[0].meta_data
        else:
            raise RuntimeError("No results could be returned for this Query.")
Пример #18
0
    def get_info(self) -> None:
        """Prints summarized information on a field's meta data.

        :return: None
        :rtype: None
        """

        kind: str = "kind:\n"
        meta = QueryExecutioner().get_type_info(self.name)
        if meta is not None:
            kind += meta.kind
        else:
            kind += "None"
        description = "description:\n" + str(self.description())
        arguments = "arguments:\n" + str(self.arguments_info())
        fields = "fields:\n" + str(self.fields_info())
        enum_values = "enum values:\n" + str(self.enum_info())
        print("\n\n".join([kind, description, arguments, fields, enum_values]))
Пример #19
0
    def meta_data(self) -> Union[Dict[str, Any], List[Dict[str, Any]]]:
        """Runs the query and returns a Dict with the meta data of the queries results.

        Raises:
            RuntimeError: If the Query did not return any results.
            E.g. if the Query was ill-formed.

        Returns:
            Union[Dict[str, Any], List[Dict[str, Any]]] --
            A Dict with the queried meta data.
            If the query fails raise RuntimeError.
        """
        result = QueryExecutioner().run_query(self)
        if result:
            # TODO: correct indexing?
            return result[0].meta_data
        else:
            raise RuntimeError("No results could be returned for this Query.")
Пример #20
0
    def results(self) -> DataFrame:
        """Runs the query and returns a Pandas DataFrame with the results.

        Raises:
            RuntimeError: If the Query did not return any results.
            E.g. if the Query was ill-formed.

        Returns:
            DataFrame --
            A DataFrame with the queried data.
            If the query fails raise RuntimeError.
        """
        result = QueryExecutioner().run_query(self)
        if result:
            # TODO: adapt QueryOutputTransformer to process list of results
            return QueryOutputTransformer(result[0].query_results[0]).transform()
        else:
            raise RuntimeError("No results could be returned for this Query.")
Пример #21
0
class Query:
    """A query to get information via the datenguide API for regionalstatistik.
    The query contains all fields and arguments.

    :param start_field: The top node field; either allRegions or Region.
    :type start_field: Field
    :param region_field: A field of type 'Region' that is needed
    if start_field is allRegions, defaults to None
    :type region_field: Field, optional
    :param default_fields: Wether default fields shall
            be attached to the fields., defaults to True
    :type default_fields: bool, optional
    :raises RuntimeError: [description]
    """

    # static variables based on QueryExecutioner

    # static variable with all subfields of "Query"
    _query_fields: Optional[TypeMetaData] = QueryExecutioner().get_type_info("Query")

    _return_type_region: str = ""
    _return_type_allreg: str = ""
    if _query_fields:

        # static variable with return type of "region"
        _return_type_region = (
            _query_fields.fields["region"].get_return_type()
            if _query_fields.fields
            else ""
        )

        # static variable with return type of "allRegions"
        _return_type_allreg = (
            _query_fields.fields["allRegions"].get_return_type()
            if _query_fields.fields
            else ""
        )

    # static variable with all subfields of "Region"
    _region_fields: Optional[TypeMetaData] = QueryExecutioner().get_type_info(
        _return_type_region
    )

    # static variable with all subfields of "allRegions"
    _allregions_fields: Optional[TypeMetaData] = QueryExecutioner().get_type_info(
        _return_type_allreg
    )

    # static variable with return type of field "regions"
    _return_type_regions: str = "Region"

    def __init__(
        self,
        start_field: Field,
        region_field: Field = None,
        default_fields: bool = True,
    ):
        self.start_field = start_field
        self.region_field = region_field

    @classmethod
    def region(
        cls,
        region: Union[str, List[str]],
        fields: List[Union[str, "Field"]] = [],
        default_fields: bool = True,
    ) -> "Query":
        """Factory method to instantiate a Query with a single region through
            its region id.

        :param region: The region id(s) the statistics shall return
        :type region: Union[str, List[str]]
        :param fields: all fields that shall be
                returned from the query for that region.
                Can either be simple fields (e.g. name)
                or fields with nested fields.
        :type fields: list
                or fields with nested fields.
        :param default_fields: Wether default fields shall
        :type default_fields: bool

        :raises RuntimeError: [description]

        :return: A query object with region as start Field.
        :rtype: Query
        """

        if default_fields:
            defaults: List[Union[str, "Field"]] = ["id", "name"]
            fields = defaults + fields

        # add quotation marks around id for correct query
        if isinstance(region, list):
            region_arg: Union[str, List[str]] = [('"' + x + '"') for x in region]
        else:
            region_arg = ['"' + region + '"']

        return cls(
            start_field=Field(
                "region",
                fields,
                args={"id": region_arg},
                return_type=Query._return_type_region,
                default_fields=default_fields,
            )
        )

    @classmethod
    def all_regions(
        cls,
        fields: List[Union[str, "Field"]] = [],
        parent: str = None,
        nuts: int = None,
        lau: int = None,
        default_fields: bool = True,
    ) -> "Query":
        """Factory method to instantiate a Query with allRegions start field.
        A parent id, nuts or lau can be further specified for the query.

        :param fields: all fields that shall be returned
            for that region. Can either be simple fields (e.g. name)
            or fields with nested fields.
        :param parent: The region id of the parent region
            the statistics shall be queried for.
            (E.g. the id for a state where all sub regions within the
            state shall be queried for.)
        :type parent:
        :param nuts: The administration level: 1 – Bundesländer
            2 – Regierungsbezirke / statistische Regionen
            3 – Kreise / kreisfreie Städte.
            Default None returns results for all levels.
        :type nuts: int, optional
        :param lau: The administration level: 1 - Verwaltungsgemeinschaften
            2 - Gemeinden.
            Default returns results for all levels.
        :type lau: int, optional
        :type fields: list
        :param default_fields: Wether default fields shall
            be attached to the fields.
        :type default_fields: bool


        :return:  A query object with allRegions as start Field.
        :rtype: Query
        """

        # add page and itemsPerPage as arguments for QueryExecutioner
        args = {"page": "$page", "itemsPerPage": "$itemsPerPage"}

        region_args = {}
        if parent:
            region_args["parent"] = '"' + parent + '"'
        if nuts:
            region_args["nuts"] = str(nuts)
        if lau:
            region_args["lau"] = str(lau)

        if default_fields:
            defaults: List[Union[str, "Field"]] = ["id", "name"]
            fields = defaults + fields

        regions = Field(
            "regions",
            fields=fields,
            args=region_args,
            return_type=Query._return_type_regions,
        )

        # add fields page, itemsperPage and total for QueryExecutioner
        return cls(
            start_field=Field(
                "allRegions",
                fields=[regions, "page", "itemsPerPage", "total"],
                args=args,
                return_type=Query._return_type_allreg,
                default_fields=default_fields,
            ),
            region_field=regions,
        )

    def add_field(self, field: Union[str, Field], default_fields=True) -> Field:
        """Ad a field to the query.

        Arguments:
            field -- Field to be added.
            default_fields-- Wether default fields
        should be attached or not.

        Raises:
            RuntimeError: If the allRegions Query has
            no regions field a subfield can be attached to.

        Returns:
            Field -- The added field.
        """
        if self.start_field.name == "allRegions":
            if self.region_field is not None:
                return self.region_field.add_field(field, default_fields=default_fields)
            else:
                raise RuntimeError(
                    "All Regions Query initialized without regions field."
                )
        else:
            return self.start_field.add_field(field, default_fields=default_fields)

    def drop_field(self, field: str) -> "Query":
        """Drop an attached field of the query.

        Arguments:
            field -- The name of the field to be droped.

        Returns:
            Query -- the query without the dropped field.
        """
        if self.start_field.name == "allRegions":
            if self.region_field is not None:
                self.region_field.drop_field(field)
                return self
            else:
                raise RuntimeError(
                    "All Regions Query initialized without regions field."
                )
        else:
            self.start_field.drop_field(field)
            return self

    def get_graphql_query(self) -> List[str]:
        """Formats the Query into a String that can be queried from the Datenguide API.

        Returns:
            List -- the Query as a String.
        """
        if self.start_field.name == "allRegions":
            query_prefix = "query ($page : Int, $itemsPerPage : Int) "
        else:
            query_prefix = ""

        # for region with multiple region IDs return a list of queries
        if (self.start_field.name == "region") and isinstance(
            self.start_field.args.get("id", ""), list
        ):
            query_list: List[str] = []
            for region_id in self.start_field.args["id"]:
                query_list += [
                    (
                        "{"
                        + self.start_field._get_fields_to_query(
                            self.start_field, region_id
                        )
                        + "}"
                    )
                ]
            return query_list
        else:
            return [
                query_prefix
                + "{"
                + self.start_field._get_fields_to_query(self.start_field)
                + "}"
            ]

    def get_fields(self) -> List[str]:
        """Get all fields of a query.

        Returns:
            List -- a list field names.
        """
        return self.start_field.get_fields()

    def results(self) -> DataFrame:
        """Runs the query and returns a Pandas DataFrame with the results.

        Raises:
            RuntimeError: If the Query did not return any results.
            E.g. if the Query was ill-formed.

        Returns:
            DataFrame --
            A DataFrame with the queried data.
            If the query fails raise RuntimeError.
        """
        result = QueryExecutioner().run_query(self)
        if result:
            # TODO: adapt QueryOutputTransformer to process list of results
            return QueryOutputTransformer(result[0].query_results[0]).transform()
        else:
            raise RuntimeError("No results could be returned for this Query.")

    def meta_data(self) -> Union[Dict[str, Any], List[Dict[str, Any]]]:
        """Runs the query and returns a Dict with the meta data of the queries results.

        Raises:
            RuntimeError: If the Query did not return any results.
            E.g. if the Query was ill-formed.

        Returns:
            Union[Dict[str, Any], List[Dict[str, Any]]] --
            A Dict with the queried meta data.
            If the query fails raise RuntimeError.
        """
        result = QueryExecutioner().run_query(self)
        if result:
            # TODO: correct indexing?
            return result[0].meta_data
        else:
            raise RuntimeError("No results could be returned for this Query.")

    @staticmethod
    def get_info(field: str = None) -> Optional[TypeMetaData]:
        """Get information on a specific field.
        If field is not specified return meta data for
        all statistics that can be queried.

        Arguments:
            field -- the field to get information on. If None,
            then information on all possible fields of a query are
            returned.

        Returns:
            Optional[TypeMetaData] -- Response from QueryExecutioner on meta data info
        """
        if field:
            return QueryExecutioner().get_type_info(field)
        else:
            return QueryExecutioner().get_type_info(Query._return_type_region)
Пример #22
0
def download_all_regions() -> pd.DataFrame:
    """[summary]

    :raises RuntimeError: [description]
    :raises RuntimeError: [description]
    :return: [description]
    :rtype: pd.DataFrame
    """
    def nuts_query(nuts_level):
        q = Query.all_regions(nuts=nuts_level)
        return q

    def lau_query(lau_level):
        q = Query.all_regions(lau=lau_level)
        return q

    qb_all = Query.all_regions()

    qe = QueryExecutioner()
    print("start")
    all_regions = qe.run_query(qb_all)
    print("all")
    r_nuts1 = qe.run_query(nuts_query(1))
    print("nuts1")
    r_nuts2 = qe.run_query(nuts_query(2))
    print("nuts2")
    r_nuts3 = qe.run_query(nuts_query(3))
    print("nuts3")
    r_lau1 = qe.run_query(lau_query(1))
    print("lau")
    # currently no distinction between different laus
    # on datehenguide side
    # r_lau2 = qe.run_query(lau_query(2))

    levels = {
        "nuts1": r_nuts1,
        "nuts2": r_nuts2,
        "nuts3": r_nuts3,
        "lau": r_lau1,
        # 'lau2':r_lau2
    }

    def isAnscestor(region_id, candidate):
        """[summary]

        :param region_id: [description]
        :type region_id: [type]
        :param candidate: [description]
        :type candidate: [type]
        :return: [description]
        :rtype: [type]
        """
        return region_id.startswith(candidate) and candidate != region_id

    def parent(region_id, region_details):
        """[summary]

        :param region_id: [description]
        :type region_id: [type]
        :param region_details: [description]
        :type region_details: [type]
        :return: [description]
        :rtype: [type]
        """
        desc = region_details.assign(ansc=lambda df: df.index.map(
            lambda i: isAnscestor(region_id, i))).query("ansc")
        max_lev = desc.level.max()  # noqa: F841
        parent_frame = desc.query("level == @max_lev")
        if not parent_frame.empty:
            return parent_frame.iloc[0, :].name
        else:
            None

    if all_regions is None:
        raise RuntimeError("Was not able to download all regions")

    for k in levels:
        if levels[k] is None:
            raise RuntimeError(f"Was not able to download {k} regions")

    all_regions_df = pd.concat([
        pd.DataFrame(page["data"]["allRegions"]["regions"])
        for page in cast(List[ExecutionResults], all_regions)[0].query_results
    ]).set_index("id")

    level_df = pd.concat(
        pd.concat([
            pd.DataFrame(page["data"]["allRegions"]["regions"]) for page in
            cast(List[ExecutionResults], levels[k])[0].query_results
        ]).assign(level=k) for k in levels)

    all_rg_parents = all_regions_df.join(
        level_df.set_index("id").loc[:, "level"]).assign(
            parent=lambda df: df.index.map(
                partial(
                    parent,
                    region_details=all_regions_df.assign(level=lambda df: df.
                                                         index.map(len)),
                )))
    all_rg_parents.loc[all_rg_parents.level == "nuts1", "parent"] = "DG"

    return all_rg_parents
Пример #23
0
def test_query_executioner_workflow(query):
    """Functional test for the query executioner"""

    # Ira (W. Cotton, probably the first person to use the term API) want to
    # try the query execution part of the datenguide GraphQL wrapper library.
    # He already worked through Query builder objects ready for execution.
    # He understands that he first has to create an executioner object that
    # it uses the right by default, so that he does not have to supply any
    # parameters.

    q_exec = QueryExecutioner()

    # After creating the object Ira is actually a little sceptical whether
    # the endpoint will correct so he extracts the endpoint and compares it
    # with his expectations.

    assert (q_exec.endpoint == "https://api-next.datengui.de/graphql"
            ), "Default endpoint is wrong"

    # Being satisfied that everything is setup with the correct endpoint Ira
    # now wants to execute one of his queries to see that he gets some return
    # values.

    res_query1 = query.results()

    assert res_query1 is not None, "query did not return results"

    # He wants to have a closer look at the raw return query results and
    # remembers that they are sorted in the results field and he has a look.

    assert (type(res_query1) is
            pd.DataFrame), "query results are not a python json representation"

    stats = query.get_info()

    # Ira remembers that he read about the executioners functionality to
    # return metadata along with the query results. So he wants to check
    # whether this metadata is actually present. And that it only contains
    # meta data related to his query

    meta_query1 = query.meta_data()
    meta_query1_alternative = query.result_meta_data

    # In particular Ira would like to have a more human readable description
    # of the statistic he asked for.

    assert "BEVMK3" in meta_query1["statistics"], "statistic absend"
    assert (meta_query1["statistics"]["BEVMK3"] !=
            "NO DESCRIPTION FOUND"), "descrption was not obtained"
    assert "BEVMK3" in meta_query1["units"], "units absend"
    assert meta_query1["units"][
        "BEVMK3"] == "Anzahl", "correct unit was not obtained"
    assert (meta_query1 == meta_query1_alternative
            ), "meta_data_query_alternatives_should be equal"

    # Although he is satisfied with having access to the meta information
    # already he would like to try the functionality where this information
    # is used directly to get more verbose query results.

    res_query1_verbose_cols = query.results(verbose_statistics=True)
    print(res_query1_verbose_cols.columns)
    assert (
        # "Von der Scheidung betroffene Kinder (BEVMK3)" in res_query1_verbose_cols
        "Von der Scheidung betroffene Kinder (BEVMK3)" in
        res_query1_verbose_cols), "verbose statistic name is not present"

    # Being satisfied with the results he obtained for his simple query
    # he actually wants to try a larger one across several regions. He heard
    # that this might be an issue for the server in general, but that the
    # executioner takes care of addressing this issue by itself.

    # Since this is a lot of information Ira would particularly
    # like to drill down on the arguments that are allowed for his
    # favorite statistic BEVMK3

    stat_args = stats.fields["BEVMK3"].get_arguments()
    assert len(stat_args) > 0
    assert "statistics" in stat_args

    # Although this is already really helpful Ira notices that
    # one of the arguments is an ENUM and he would like to know
    # the possible values that he can use for it.

    enum_vals = query.get_info("BEVMK3Statistics").enum_values
    assert type(enum_vals) == dict, "Enum values should be dict"
    assert len(enum_vals) > 0, "Enums should have values"

    # Ira wants to add another statistic to his query.
    statistic1 = query.add_field("BEV001")
    statistic1.add_field("year")
    statistic1.add_args({"year": 2017})

    assert type(statistic1) == Field, "statistic is not a Field"

    # Then he wants to get metainfo on the field.

    stringio = io.StringIO()
    sys.stdout = stringio

    statistic1.get_info()
    stats_info = re.sub(r"\n", "", stringio.getvalue())
    assert "OBJECT" in stats_info, "BEV001 should be an object"
Пример #24
0
def test_extract_stat_desc(stat_description):
    extracted_text = QueryExecutioner._extract_main_description(
        stat_description[0])
    assert (extracted_text == stat_description[1]
            ), "extracted text does not match bold part"
Пример #25
0
 def _description_helper(self, meta_fields) -> Optional[str]:
     return QueryExecutioner._extract_main_description(
         meta_fields[self.name]["description"]
     )