diff --git a/bavapi/client.py b/bavapi/client.py index 28885d7..aa823b7 100644 --- a/bavapi/client.py +++ b/bavapi/client.py @@ -345,7 +345,7 @@ async def audiences( Return inactive audiences only if set to `1`, default 0 groups : int or list[int], optional Audience group ID or list of audience group IDs, default None - filters : AudiencesFilters or dict of filters, optional + filters : AudiencesFilters or dict[str, Any], optional AudiencesFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -384,7 +384,7 @@ async def audiences( Returns ------- pandas.DataFrame - DataFrame with `brands` endpoint results. + DataFrame with `audiences` endpoint results. """ filters = _filters.AudiencesFilters.ensure( filters, @@ -441,8 +441,8 @@ async def brand_metrics( private : Literal[0, 1], optional Return inactive brand metrics only if set to `1`, default 0 groups : int or list[int], optional - Brand metrics group ID or list of Brand metrics group IDs, default None - filters : BrandMetricsFilters or dict of filters, optional + Brand metrics group ID or list of brand metrics group IDs, default None + filters : BrandMetricsFilters or dict[str, Any], optional BrandMetricsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -530,7 +530,7 @@ async def brand_metric_groups( Fount metric group ID, default None If a metric group ID is provided, only that metric group will be returned - filters : BrandMetricGroupsFilters or dict of filters, optional + filters : BrandMetricGroupsFilters or dict[str, Any], optional BrandMetricGroupsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -621,7 +621,7 @@ async def brands( If a brand ID is provided, only that brand will be returned studies : int or list[int], optional Fount study IDs, default None - filters : BrandsFilters or dict of filters, optional + filters : BrandsFilters or dict[str, Any], optional BrandsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -751,7 +751,7 @@ async def brandscape_data( Search by brand name, default None studies : int or list[int], optional Fount studies IDs, default None - filters : BrandscapeFilters or dict of filters, optional + filters : BrandscapeFilters or dict[str, Any], optional BrandscapeFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -861,7 +861,7 @@ async def categories( Fount category ID, default None If a category ID is provided, only that category will be returned - filters : CategoriesFilters or dict of filters, optional + filters : CategoriesFilters or dict[str, Any], optional CategoriesFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -954,7 +954,7 @@ async def cities( Fount city ID, default None If a city ID is provided, only that city will be returned - filters : CitiesFilters or dict of filters, optional + filters : CitiesFilters or dict[str, Any], optional CitiesFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1047,7 +1047,7 @@ async def collections( Only return collections that have been shared with the user, default 0 mine : Literal[0, 1], optional Only return collections created by the user, default 0 - filters : CollectionsFilters or dict of filters, optional + filters : CollectionsFilters or dict[str, Any], optional CollectionsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1142,7 +1142,7 @@ async def companies( Fount company ID, default None If a company ID is provided, only that company will be returned - filters : CompaniesFilters or dict of filters, optional + filters : CompaniesFilters or dict[str, Any], optional CompaniesFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1240,7 +1240,7 @@ async def countries( Fount country ID, default None If a country ID is provided, only that country will be returned - filters : CountriesFilters or dict of filters, optional + filters : CountriesFilters or dict[str, Any], optional CountriesFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1325,7 +1325,7 @@ async def regions( Fount region ID, default None If a region ID is provided, only that region will be returned - filters : RegionsFilters or dict of filters, optional + filters : RegionsFilters or dict[str, Any], optional RegionsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1409,7 +1409,7 @@ async def sectors( Fount sectors ID, default None If a sector ID is provided, only that sector will be returned - filters : SectorsFilters or dict of filters, optional + filters : SectorsFilters or dict[str, Any], optional SectorsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1505,7 +1505,7 @@ async def studies( study_id : int, optional Fount study ID, default None If a study ID is provided, only that study will be returned - filters : StudiesFilters or dict of filters, optional + filters : StudiesFilters or dict[str, Any], optional StudiesFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1590,7 +1590,7 @@ async def years( Fount year ID, default None If a year ID is provided, only that year will be returned - filters : YearsFilters or dict of filters, optional + filters : YearsFilters or dict[str, Any], optional YearsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1629,7 +1629,7 @@ async def years( Returns ------- pandas.DataFrame - DataFrame with `regions` endpoint results. + DataFrame with `years` endpoint results. """ filters = _filters.YearsFilters.ensure( filters, diff --git a/bavapi/parsing/params.py b/bavapi/parsing/params.py index 0692552..f924cbb 100644 --- a/bavapi/parsing/params.py +++ b/bavapi/parsing/params.py @@ -67,7 +67,7 @@ def list_to_str(mapping: BaseMutableParamsMapping) -> BaseMutableParamsMappingVa Returns ------- ParamsMappingValues - Dictionary without strings + Dictionary with lists converted to comma-separated strings """ for key, value in mapping.items(): if not isinstance(value, str) and isinstance(value, Sequence): diff --git a/bavapi/parsing/responses.py b/bavapi/parsing/responses.py index 3ee492a..ce58585 100644 --- a/bavapi/parsing/responses.py +++ b/bavapi/parsing/responses.py @@ -163,5 +163,30 @@ def parse_response( index=index, ) .dropna(axis=1, how="all") - .transform(pd.to_numeric, errors="ignore") + .transform(convert_numeric) ) + + +def convert_numeric(series: pd.Series) -> pd.Series: + """Convert pandas series into appropriate numeric types. + + - Float and int values are returned directly with no conversion. + - String values are converted to int if possible, else float. Otherwise, return the + series with no conversion. + + Parameters + ---------- + series : pd.Series + Pandas series to convert to numeric type + + Returns + ------- + pd.Series + Pandas series with numeric dtype, or current dtype if coercion is not possible + """ + if series.dtype in (float, int): + return series + try: + return series.astype(int) + except ValueError: + return series.astype(float, errors="ignore") diff --git a/bavapi/sync.py b/bavapi/sync.py index abe82a5..1a9aa16 100644 --- a/bavapi/sync.py +++ b/bavapi/sync.py @@ -185,7 +185,7 @@ async def audiences( Return inactive audiences only if set to `1`, default 0 groups : int or list[int], optional Audience group ID or list of audience group IDs, default None - filters : AudiencesFilters or dict of filters, optional + filters : AudiencesFilters or dict[str, Any], optional AudiencesFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -236,7 +236,7 @@ async def audiences( Returns ------- pandas.DataFrame - DataFrame with `brands` endpoint results + DataFrame with `audiences` endpoint results """ async with Client( @@ -307,7 +307,7 @@ async def brand_metrics( Return inactive brand metrics only if set to `1`, default 0 groups : int or list[int], optional Brand metrics group ID or list of brand metrics group IDs, default None - filters : BrandMetricsFilters or dict of filters, optional + filters : BrandMetricsFilters or dict[str, Any], optional BrandMetricsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -420,7 +420,7 @@ async def brand_metric_groups( Fount brand metric group ID, default None If a metric group ID is provided, only that metric group will be returned - filters : BrandMetricGroupsFilters or dict of filters, optional + filters : BrandMetricGroupsFilters or dict[str, Any], optional BrandMetricGroupsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -536,7 +536,7 @@ async def brands( If a brand ID is provided, only that brand will be returned studies : int or list[int], optional Fount study IDs, default None - filters : BrandsFilters or dict of filters, optional + filters : BrandsFilters or dict[str, Any], optional BrandsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -690,7 +690,7 @@ async def brandscape_data( Search by brand name, default None studies : int or list[int], optional Fount studies IDs, default None - filters : BrandscapeFilters or dict of filters, optional + filters : BrandscapeFilters or dict[str, Any], optional BrandscapeFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -820,7 +820,7 @@ async def categories( Fount category ID, default None If a category ID is provided, only that category will be returned - filters : CategoriesFilters or dict of filters, optional + filters : CategoriesFilters or dict[str, Any], optional CategoriesFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -938,7 +938,7 @@ async def cities( Fount city ID, default None If a city ID is provided, only that city will be returned - filters : CitiesFilters or dict of filters, optional + filters : CitiesFilters or dict[str, Any], optional CitiesFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1056,7 +1056,7 @@ async def collections( Only return collections that have been shared with the user, default 0 mine : Literal[0, 1], optional Only return collections created by the user, default 0 - filters : CollectionsFilters or dict of filters, optional + filters : CollectionsFilters or dict[str, Any], optional CollectionsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1176,7 +1176,7 @@ async def companies( Fount company ID, default None If a company ID is provided, only that company will be returned - filters : CompaniesFilters or dict of filters, optional + filters : CompaniesFilters or dict[str, Any], optional CompaniesFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1299,7 +1299,7 @@ async def countries( Years of recency of studies in a specific country, default None Only return countries which have had a BAV study in the past X years - filters : CountriesFilters or dict of filters, optional + filters : CountriesFilters or dict[str, Any], optional CountriesFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1409,7 +1409,7 @@ async def regions( Fount region ID, default None If a region ID is provided, only that region will be returned - filters : RegionsFilters or dict of filters, optional + filters : RegionsFilters or dict[str, Any], optional RegionsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1518,7 +1518,7 @@ async def sectors( Fount sectors ID, default None If a sector ID is provided, only that sector will be returned - filters : SectorsFilters or dict of filters, optional + filters : SectorsFilters or dict[str, Any], optional SectorsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1639,7 +1639,7 @@ async def studies( study_id : int, optional Fount study ID, default None If a study ID is provided, only that study will be returned - filters : StudiesFilters or dict of filters, optional + filters : StudiesFilters or dict[str, Any], optional StudiesFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None @@ -1749,7 +1749,7 @@ async def years( Fount year ID, default None If a year ID is provided, only that year will be returned - filters : YearsFilters or dict of filters, optional + filters : YearsFilters or dict[str, Any], optional YearsFilters object or dictionary of filter parameters, default None fields : str or list[str], optional Fields to retrieve in API response, default None diff --git a/docs/fetch_contributing.py b/docs/fetch_contributing.py index d60f79d..c702961 100644 --- a/docs/fetch_contributing.py +++ b/docs/fetch_contributing.py @@ -30,7 +30,11 @@ """ -md5_found = found[0] if (found := re.findall(r"", docs_contributing)) else "none" +md5_found = ( + found[0] + if (found := re.findall(r"", docs_contributing)) + else "none" +) if hashed_hex != md5_found: # Substitute found docs links with relative docs path @@ -39,5 +43,3 @@ with open("./docs/contributing.md", "w", encoding="utf-8") as file: file.write("\n".join((MKDOCS_HEADER, contributing))) - - print("updated contributing...") diff --git a/docs/release-notes.md b/docs/release-notes.md index b45b76f..116b6c2 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -2,6 +2,24 @@ ## `1.0` +### `1.0.2` (2024-02-08) + +#### Fix + +- :warning: Fix deprecation warning when parsing responses into dataframes with `pandas>=2.2`. + +#### Docs + +- :sparkles: Add ability to copy code blocks from the documentation. + +#### Test + +- :test_tube: Added tests for correct dtype conversions. + +#### Internal + +- :broom: Cleaned up unused and ignored logging for development scripts. + ### `1.0.1` (2024-01-19) #### Fix diff --git a/mkdocs.yml b/mkdocs.yml index 2f51dfe..f0fb352 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,7 +4,7 @@ site_url: https://wppbav.github.io/bavapi-sdk-python repo_name: wppbav/bavapi-sdk-python repo_url: https://github.com/wppbav/bavapi-sdk-python -copyright: Copyright © 2023 WPPBAV +copyright: Copyright © 2024 WPPBAV theme: name: material @@ -15,6 +15,7 @@ theme: repo: fontawesome/brands/github features: - content.code.annotate + - content.code.copy - navigation.footer - navigation.instant - navigation.instant.progress @@ -27,7 +28,7 @@ theme: - media: "(prefers-color-scheme)" toggle: icon: material/brightness-auto - name: Switch to light mode + name: Switch to dark mode # Palette toggle for light mode - media: "(prefers-color-scheme: dark)" @@ -45,7 +46,7 @@ theme: accent: indigo toggle: icon: material/brightness-7 - name: Switch to dark mode + name: Use system setting extra_css: [extra.css] @@ -96,7 +97,7 @@ nav: - Endpoints: endpoints/ - SDK API Reference: reference/ - Contributing: contributing.md - - Fount API Reference: https://developer.wppbav.com/docs/2.x/intro + - ↗ Fount API Documentation: https://developer.wppbav.com/docs/2.x/intro plugins: - search diff --git a/pyproject.toml b/pyproject.toml index 3c026ee..53be2fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "wpp-bavapi" -version = "1.0.1" +version = "1.0.2" authors = [ { name = "Ignacio Maiz Vilches", email = "ignacio.maiz@bavgroup.com" }, ] diff --git a/tests/parsing/test_responses.py b/tests/parsing/test_responses.py index 6287828..d53a7ee 100644 --- a/tests/parsing/test_responses.py +++ b/tests/parsing/test_responses.py @@ -117,4 +117,12 @@ def test_parse_response(mock_dropna: mock.Mock, mock_transform: mock.Mock): assert res.shape == (2, 1) mock_dropna.assert_called_once_with(axis=1, how="all") - mock_transform.assert_called_once_with(pd.to_numeric, errors="ignore") + mock_transform.assert_called_once_with(responses.convert_numeric) + + +def test_convert_numeric(): + assert responses.convert_numeric(pd.Series(["a", "b"])).dtype == object + assert responses.convert_numeric(pd.Series(["1", "2"])).dtype == int + assert responses.convert_numeric(pd.Series(["nan", "2.5"])).dtype == float + assert responses.convert_numeric(pd.Series([None, 2.5])).dtype == float + assert responses.convert_numeric(pd.Series([1, 2])).dtype == int