From d77e9c68b1e83474f6339e267f61d433994ca7dd Mon Sep 17 00:00:00 2001 From: gbabineau Date: Tue, 25 Mar 2025 16:48:32 -0400 Subject: [PATCH] Add rank parameter to get_historic_observations --- src/ebird/api/client.py | 2 ++ src/ebird/api/observations.py | 8 +++++++- src/ebird/api/validation.py | 9 +++++++++ .../unit/validation/test_clean_observation_rank.py | 13 +++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/unit/validation/test_clean_observation_rank.py diff --git a/src/ebird/api/client.py b/src/ebird/api/client.py index 4847abc..dd104fa 100644 --- a/src/ebird/api/client.py +++ b/src/ebird/api/client.py @@ -41,6 +41,7 @@ def __init__(self, api_key, locale): self.hotspot = False self.provisional = True self.sort = "date" + self.rank = "mrec" def get_observations(self, area): """Get recent observations (up to 30 days ago) for a region or location. @@ -127,6 +128,7 @@ def get_historic_observations(self, area, date): hotspot=self.hotspot, detail=self.detail, category=self.category, + rank=self.rank, ) def get_nearby_observations(self, lat, lng, dist=25): diff --git a/src/ebird/api/observations.py b/src/ebird/api/observations.py index 024c934..51d8f45 100644 --- a/src/ebird/api/observations.py +++ b/src/ebird/api/observations.py @@ -15,6 +15,7 @@ clean_locale, clean_max_observations, clean_provisional, + clean_observation_rank, clean_sort, ) @@ -633,6 +634,7 @@ def get_historic_observations( hotspot=False, detail="simple", category=None, + rank="mrec", ): """Get recent observations for a region. @@ -671,6 +673,10 @@ def get_historic_observations( More than one value can be given in a comma-separated string. The default value is None and records from all categories will be returned. + :param rank: return the last (rank='mrec') or first(rank='create') + observation on the date. See the eBird API documentation for a description + of the fields. + :return: the list of observations in simple format. :raises ValueError: if any of the arguments fail the validation checks. @@ -686,7 +692,7 @@ def get_historic_observations( url = HISTORIC_OBSERVATIONS_URL % (cleaned[0], date.strftime("%Y/%m/%d")) params = { - "rank": "mrec", + "rank": clean_observation_rank(rank), "detail": clean_detail(detail), "sppLocale": clean_locale(locale), "includeProvisional": clean_provisional(provisional), diff --git a/src/ebird/api/validation.py b/src/ebird/api/validation.py index 3250d1a..bac694e 100644 --- a/src/ebird/api/validation.py +++ b/src/ebird/api/validation.py @@ -200,6 +200,15 @@ def clean_detail(value): return cleaned +def clean_observation_rank(value): + cleaned = clean_code(value, transform=Transform.LOWER) + if cleaned not in ("mrec", "create"): + raise ValueError( + "Value for 'rank', %s, must be either 'mrec' or 'create'" % value + ) + return cleaned + + def clean_provisional(value): return "true" if bool(value) else "false" diff --git a/tests/unit/validation/test_clean_observation_rank.py b/tests/unit/validation/test_clean_observation_rank.py new file mode 100644 index 0000000..e698321 --- /dev/null +++ b/tests/unit/validation/test_clean_observation_rank.py @@ -0,0 +1,13 @@ +import unittest + +from ebird.api.validation import clean_observation_rank + + +class CleanObservationRankTests(unittest.TestCase): + """Tests for the rank validation function.""" + + def test_codes_are_lower_case(self): + self.assertEqual("mrec", clean_observation_rank("Mrec")) + + def test_invalid_code_raises_error(self): + self.assertRaises(ValueError, clean_observation_rank, "none")