ebird-api 3.4.2__tar.gz → 4.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. {ebird_api-3.4.2 → ebird_api-4.1.0}/CHANGELOG.md +7 -0
  2. {ebird_api-3.4.2/src/ebird_api.egg-info → ebird_api-4.1.0}/PKG-INFO +19 -21
  3. {ebird_api-3.4.2 → ebird_api-4.1.0}/README.md +16 -17
  4. {ebird_api-3.4.2 → ebird_api-4.1.0}/pyproject.toml +6 -7
  5. ebird_api-4.1.0/src/ebird/api/requests/__init__.py +39 -0
  6. {ebird_api-3.4.2/src/ebird/api → ebird_api-4.1.0/src/ebird/api/requests}/checklists.py +2 -2
  7. {ebird_api-3.4.2/src/ebird/api → ebird_api-4.1.0/src/ebird/api/requests}/client.py +2 -2
  8. {ebird_api-3.4.2/src/ebird/api → ebird_api-4.1.0/src/ebird/api/requests}/hotspots.py +2 -2
  9. {ebird_api-3.4.2/src/ebird/api → ebird_api-4.1.0/src/ebird/api/requests}/observations.py +2 -2
  10. {ebird_api-3.4.2/src/ebird/api → ebird_api-4.1.0/src/ebird/api/requests}/regions.py +2 -2
  11. {ebird_api-3.4.2/src/ebird/api → ebird_api-4.1.0/src/ebird/api/requests}/species.py +2 -2
  12. {ebird_api-3.4.2/src/ebird/api → ebird_api-4.1.0/src/ebird/api/requests}/statistics.py +2 -2
  13. {ebird_api-3.4.2/src/ebird/api → ebird_api-4.1.0/src/ebird/api/requests}/taxonomy.py +2 -2
  14. {ebird_api-3.4.2/src/ebird/api → ebird_api-4.1.0/src/ebird/api/requests}/utils.py +35 -7
  15. {ebird_api-3.4.2/src/ebird/api → ebird_api-4.1.0/src/ebird/api/requests}/validation.py +1 -1
  16. {ebird_api-3.4.2 → ebird_api-4.1.0/src/ebird_api.egg-info}/PKG-INFO +19 -21
  17. ebird_api-4.1.0/src/ebird_api.egg-info/SOURCES.txt +21 -0
  18. ebird_api-3.4.2/src/ebird/api/__init__.py +0 -35
  19. ebird_api-3.4.2/src/ebird_api.egg-info/SOURCES.txt +0 -21
  20. {ebird_api-3.4.2 → ebird_api-4.1.0}/LICENSE.txt +0 -0
  21. {ebird_api-3.4.2 → ebird_api-4.1.0}/setup.cfg +0 -0
  22. {ebird_api-3.4.2 → ebird_api-4.1.0}/setup.py +0 -0
  23. {ebird_api-3.4.2/src/ebird/api → ebird_api-4.1.0/src/ebird/api/requests}/constants.py +0 -0
  24. {ebird_api-3.4.2 → ebird_api-4.1.0}/src/ebird_api.egg-info/dependency_links.txt +0 -0
  25. {ebird_api-3.4.2 → ebird_api-4.1.0}/src/ebird_api.egg-info/top_level.txt +0 -0
@@ -8,6 +8,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
8
8
  This project adheres to [PEP440](https://www.python.org/dev/peps/pep-0440/)
9
9
  and by implication, [Semantic Versioning](http://semver.org/).
10
10
 
11
+ ## [4.1.0] - 2026-06-14
12
+ - Retry requests, with exponentinal back-off, if an error occurs.
13
+
14
+ ## [4.0.0] - 2025-07-09
15
+ - Moved the package to ebird.api.requests to make space for other projects.
16
+ - Changed the minimum supported python version to 3.10
17
+
11
18
  ## [3.4.2] - 2025-04-05
12
19
  - Added a timeout so the client will raise an error if the connection
13
20
  to eBird freezes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ebird-api
3
- Version: 3.4.2
3
+ Version: 4.1.0
4
4
  Summary: Wrapper for accessing the eBird API
5
5
  Author-email: Project Babbler <projectbabbler@gmail.com>
6
6
  License: MIT License
@@ -15,28 +15,26 @@ Classifier: License :: OSI Approved :: MIT License
15
15
  Classifier: Operating System :: OS Independent
16
16
  Classifier: Programming Language :: Python
17
17
  Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.8
19
- Classifier: Programming Language :: Python :: 3.9
20
18
  Classifier: Programming Language :: Python :: 3.10
21
19
  Classifier: Programming Language :: Python :: 3.11
22
20
  Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
23
22
  Classifier: Programming Language :: Python :: Implementation :: CPython
24
23
  Classifier: Natural Language :: English
25
24
  Classifier: Topic :: Utilities
26
25
  Classifier: Topic :: Internet
27
- Requires-Python: >=3.8
26
+ Requires-Python: >=3.10
28
27
  Description-Content-Type: text/markdown
29
28
  License-File: LICENSE.txt
30
29
  Dynamic: license-file
31
30
 
32
- [![Build Status](https://travis-ci.org/ProjectBabbler/ebird-api.svg?branch=master)](https://travis-ci.org/ProjectBabbler/ebird-api)
33
31
  [![PyPI version](https://badge.fury.io/py/ebird-api.svg)](https://badge.fury.io/py/ebird-api)
34
32
  [![Supported Python Versions](https://img.shields.io/pypi/pyversions/ebird-api.svg)](https://img.shields.io/pypi/pyversions/ebird-api)
35
33
 
36
34
  # eBird API
37
35
 
38
- eBird API provides a set of wrapper functions for accessing the end-points
39
- in the eBird API 2.0.
36
+ eBird API Requests provides a set of wrapper functions for accessing the
37
+ end-points in the eBird API 2.0.
40
38
 
41
39
  ## Install
42
40
 
@@ -71,7 +69,7 @@ what you want to do - they will be interested to hear it.
71
69
  ```python
72
70
  import os
73
71
 
74
- from ebird.api import get_observations
72
+ from ebird.api.requests import get_observations
75
73
 
76
74
  # Always store secrets outside the code, so you don't accidentally
77
75
  # commit them. Environment variables are ideal for this.
@@ -97,7 +95,7 @@ regions:
97
95
  ```python
98
96
  import os
99
97
 
100
- from ebird.api import get_observations
98
+ from ebird.api.requests import get_observations
101
99
 
102
100
  api_key = os.environ["EBIRD_API_KEY"]
103
101
 
@@ -119,7 +117,7 @@ or taxonomy:
119
117
  ```python
120
118
  import os
121
119
 
122
- from ebird.api import get_observations
120
+ from ebird.api.requests import get_observations
123
121
 
124
122
  api_key = os.environ["EBIRD_API_KEY"]
125
123
 
@@ -134,7 +132,7 @@ species:
134
132
  ```python
135
133
  import os
136
134
 
137
- from ebird.api import get_nearby_observations
135
+ from ebird.api.requests import get_nearby_observations
138
136
 
139
137
  api_key = os.environ["EBIRD_API_KEY"]
140
138
 
@@ -151,7 +149,7 @@ a small number of species:
151
149
  ```python
152
150
  import os
153
151
 
154
- from ebird.api import (
152
+ from ebird.api.requests import (
155
153
  get_notable_observations,
156
154
  get_nearby_notable,
157
155
  get_species_observations,
@@ -178,7 +176,7 @@ For the more travel-minded you can also find out the nearest place to see a give
178
176
  ```python
179
177
  import os
180
178
 
181
- from ebird.api import get_nearest_species
179
+ from ebird.api.requests import get_nearest_species
182
180
 
183
181
  api_key = os.environ["EBIRD_API_KEY"]
184
182
 
@@ -199,7 +197,7 @@ checklist. You can then call get_checklist() to get the list of observations.
199
197
  ```python
200
198
  import os
201
199
 
202
- from ebird.api import get_visits, get_checklist
200
+ from ebird.api.requests import get_visits, get_checklist
203
201
 
204
202
  api_key = os.environ["EBIRD_API_KEY"]
205
203
 
@@ -224,7 +222,7 @@ on the location of a given hotspot.
224
222
  ```python
225
223
  import os
226
224
 
227
- from ebird.api import get_hotspots, get_nearby_hotspots, get_hotspot
225
+ from ebird.api.requests import get_hotspots, get_nearby_hotspots, get_hotspot
228
226
 
229
227
  api_key = os.environ["EBIRD_API_KEY"]
230
228
 
@@ -251,7 +249,7 @@ by a region use get_region().
251
249
  ```python
252
250
  import os
253
251
 
254
- from ebird.api import get_regions, get_adjacent_regions, get_region
252
+ from ebird.api.requests import get_regions, get_adjacent_regions, get_region
255
253
 
256
254
  api_key = os.environ["EBIRD_API_KEY"]
257
255
 
@@ -282,7 +280,7 @@ that are used in the other API calls.
282
280
  ```python
283
281
  import os
284
282
 
285
- from ebird.api import get_taxonomy, get_taxonomy_forms, get_taxonomy_versions
283
+ from ebird.api.requests import get_taxonomy, get_taxonomy_forms, get_taxonomy_versions
286
284
 
287
285
  api_key = os.environ["EBIRD_API_KEY"]
288
286
 
@@ -315,7 +313,7 @@ lots of people are out trying to get the greatest number of species.
315
313
  import os
316
314
 
317
315
  from datetime import date
318
- from ebird.api import get_top_100, get_totals
316
+ from ebird.api.requests import get_top_100, get_totals
319
317
 
320
318
  api_key = os.environ["EBIRD_API_KEY"]
321
319
 
@@ -335,7 +333,7 @@ have to keep passing them as arguments.
335
333
  ```python
336
334
  import os
337
335
 
338
- from ebird.api import Client
336
+ from ebird.api.requests import Client
339
337
 
340
338
  api_key = os.environ["EBIRD_API_KEY"]
341
339
  locale = 'es'
@@ -357,8 +355,8 @@ only returns JSON.
357
355
 
358
356
  ## Compatibility
359
357
 
360
- ebird-api works with currently supported versions of Python, 3.8+. However,
361
- it is known to work with earlier versions, at least 3.5 - 3.7, without any
358
+ ebird-api works with currently supported versions of Python, 3.10+. However,
359
+ it is known to work with earlier versions, at least 3.5 - 3.8, without any
362
360
  problems.
363
361
 
364
362
  ## Troubleshooting
@@ -1,11 +1,10 @@
1
- [![Build Status](https://travis-ci.org/ProjectBabbler/ebird-api.svg?branch=master)](https://travis-ci.org/ProjectBabbler/ebird-api)
2
1
  [![PyPI version](https://badge.fury.io/py/ebird-api.svg)](https://badge.fury.io/py/ebird-api)
3
2
  [![Supported Python Versions](https://img.shields.io/pypi/pyversions/ebird-api.svg)](https://img.shields.io/pypi/pyversions/ebird-api)
4
3
 
5
4
  # eBird API
6
5
 
7
- eBird API provides a set of wrapper functions for accessing the end-points
8
- in the eBird API 2.0.
6
+ eBird API Requests provides a set of wrapper functions for accessing the
7
+ end-points in the eBird API 2.0.
9
8
 
10
9
  ## Install
11
10
 
@@ -40,7 +39,7 @@ what you want to do - they will be interested to hear it.
40
39
  ```python
41
40
  import os
42
41
 
43
- from ebird.api import get_observations
42
+ from ebird.api.requests import get_observations
44
43
 
45
44
  # Always store secrets outside the code, so you don't accidentally
46
45
  # commit them. Environment variables are ideal for this.
@@ -66,7 +65,7 @@ regions:
66
65
  ```python
67
66
  import os
68
67
 
69
- from ebird.api import get_observations
68
+ from ebird.api.requests import get_observations
70
69
 
71
70
  api_key = os.environ["EBIRD_API_KEY"]
72
71
 
@@ -88,7 +87,7 @@ or taxonomy:
88
87
  ```python
89
88
  import os
90
89
 
91
- from ebird.api import get_observations
90
+ from ebird.api.requests import get_observations
92
91
 
93
92
  api_key = os.environ["EBIRD_API_KEY"]
94
93
 
@@ -103,7 +102,7 @@ species:
103
102
  ```python
104
103
  import os
105
104
 
106
- from ebird.api import get_nearby_observations
105
+ from ebird.api.requests import get_nearby_observations
107
106
 
108
107
  api_key = os.environ["EBIRD_API_KEY"]
109
108
 
@@ -120,7 +119,7 @@ a small number of species:
120
119
  ```python
121
120
  import os
122
121
 
123
- from ebird.api import (
122
+ from ebird.api.requests import (
124
123
  get_notable_observations,
125
124
  get_nearby_notable,
126
125
  get_species_observations,
@@ -147,7 +146,7 @@ For the more travel-minded you can also find out the nearest place to see a give
147
146
  ```python
148
147
  import os
149
148
 
150
- from ebird.api import get_nearest_species
149
+ from ebird.api.requests import get_nearest_species
151
150
 
152
151
  api_key = os.environ["EBIRD_API_KEY"]
153
152
 
@@ -168,7 +167,7 @@ checklist. You can then call get_checklist() to get the list of observations.
168
167
  ```python
169
168
  import os
170
169
 
171
- from ebird.api import get_visits, get_checklist
170
+ from ebird.api.requests import get_visits, get_checklist
172
171
 
173
172
  api_key = os.environ["EBIRD_API_KEY"]
174
173
 
@@ -193,7 +192,7 @@ on the location of a given hotspot.
193
192
  ```python
194
193
  import os
195
194
 
196
- from ebird.api import get_hotspots, get_nearby_hotspots, get_hotspot
195
+ from ebird.api.requests import get_hotspots, get_nearby_hotspots, get_hotspot
197
196
 
198
197
  api_key = os.environ["EBIRD_API_KEY"]
199
198
 
@@ -220,7 +219,7 @@ by a region use get_region().
220
219
  ```python
221
220
  import os
222
221
 
223
- from ebird.api import get_regions, get_adjacent_regions, get_region
222
+ from ebird.api.requests import get_regions, get_adjacent_regions, get_region
224
223
 
225
224
  api_key = os.environ["EBIRD_API_KEY"]
226
225
 
@@ -251,7 +250,7 @@ that are used in the other API calls.
251
250
  ```python
252
251
  import os
253
252
 
254
- from ebird.api import get_taxonomy, get_taxonomy_forms, get_taxonomy_versions
253
+ from ebird.api.requests import get_taxonomy, get_taxonomy_forms, get_taxonomy_versions
255
254
 
256
255
  api_key = os.environ["EBIRD_API_KEY"]
257
256
 
@@ -284,7 +283,7 @@ lots of people are out trying to get the greatest number of species.
284
283
  import os
285
284
 
286
285
  from datetime import date
287
- from ebird.api import get_top_100, get_totals
286
+ from ebird.api.requests import get_top_100, get_totals
288
287
 
289
288
  api_key = os.environ["EBIRD_API_KEY"]
290
289
 
@@ -304,7 +303,7 @@ have to keep passing them as arguments.
304
303
  ```python
305
304
  import os
306
305
 
307
- from ebird.api import Client
306
+ from ebird.api.requests import Client
308
307
 
309
308
  api_key = os.environ["EBIRD_API_KEY"]
310
309
  locale = 'es'
@@ -326,8 +325,8 @@ only returns JSON.
326
325
 
327
326
  ## Compatibility
328
327
 
329
- ebird-api works with currently supported versions of Python, 3.8+. However,
330
- it is known to work with earlier versions, at least 3.5 - 3.7, without any
328
+ ebird-api works with currently supported versions of Python, 3.10+. However,
329
+ it is known to work with earlier versions, at least 3.5 - 3.8, without any
331
330
  problems.
332
331
 
333
332
  ## Troubleshooting
@@ -14,11 +14,10 @@ classifiers = [
14
14
  "Operating System :: OS Independent",
15
15
  "Programming Language :: Python",
16
16
  "Programming Language :: Python :: 3",
17
- "Programming Language :: Python :: 3.8",
18
- "Programming Language :: Python :: 3.9",
19
17
  "Programming Language :: Python :: 3.10",
20
18
  "Programming Language :: Python :: 3.11",
21
19
  "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
22
21
  "Programming Language :: Python :: Implementation :: CPython",
23
22
  "Natural Language :: English",
24
23
  "Topic :: Utilities",
@@ -29,8 +28,8 @@ keywords = ["eBird", "API", "client"]
29
28
  license = {text = "MIT License"}
30
29
  name = "ebird-api"
31
30
  readme = "README.md"
32
- requires-python = ">= 3.8"
33
- version = "3.4.2"
31
+ requires-python = ">= 3.10"
32
+ version = "4.1.0"
34
33
 
35
34
  [project.urls]
36
35
  Repository = "https://github.com/ProjectBabbler/ebird-api.git"
@@ -38,7 +37,7 @@ Issues = "https://github.com/ProjectBabbler/ebird-api/issues"
38
37
  Changelog = "https://github.com/ProjectBabbler/ebird-api/blob/master/CHANGELOG.md"
39
38
 
40
39
  [tool.bumpversion]
41
- current_version = "3.4.2"
40
+ current_version = "4.1.0"
42
41
  parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
43
42
  serialize = ["{major}.{minor}.{patch}"]
44
43
  ignore_missing_version = false
@@ -52,7 +51,7 @@ message = "New version: {current_version} → {new_version}"
52
51
  commit_args = ""
53
52
 
54
53
  [[tool.bumpversion.files]]
55
- filename = "src/ebird/api/__init__.py"
54
+ filename = "src/ebird/api/requests/__init__.py"
56
55
  search = '__version__ = "{current_version}"'
57
56
  replace = '__version__ = "{new_version}"'
58
57
 
@@ -98,7 +97,7 @@ legacy_tox_ini = """
98
97
  requires =
99
98
  tox>=4.2
100
99
  tox-uv>=1.11.3
101
- envlist = py38, py39, py310, py311, py312
100
+ envlist = py310, py311, py312, py313
102
101
 
103
102
  [testenv]
104
103
  commands = pytest
@@ -0,0 +1,39 @@
1
+ # flake8: noqa
2
+
3
+ """A set of wrapper functions for accessing the eBird API."""
4
+
5
+ __version__ = "4.1.0"
6
+
7
+ from ebird.api.requests.checklists import get_checklist, get_visits
8
+ from ebird.api.requests.client import Client
9
+ from ebird.api.requests.constants import LOCALES
10
+ from ebird.api.requests.hotspots import (
11
+ get_hotspot,
12
+ get_hotspots,
13
+ get_location,
14
+ get_nearby_hotspots,
15
+ )
16
+ from ebird.api.requests.observations import (
17
+ get_historic_observations,
18
+ get_nearby_notable,
19
+ get_nearby_observations,
20
+ get_nearby_species,
21
+ get_nearest_species,
22
+ get_notable_observations,
23
+ get_observations,
24
+ get_species_observations,
25
+ )
26
+ from ebird.api.requests.regions import (
27
+ get_adjacent_regions,
28
+ get_region,
29
+ get_regions,
30
+ )
31
+ from ebird.api.requests.species import get_species_list
32
+ from ebird.api.requests.statistics import get_top_100, get_totals
33
+ from ebird.api.requests.taxonomy import (
34
+ get_taxonomy,
35
+ get_taxonomy_forms,
36
+ get_taxonomy_groups,
37
+ get_taxonomy_locales,
38
+ get_taxonomy_versions,
39
+ )
@@ -1,7 +1,7 @@
1
1
  """Functions for fetching checklists and information about visits."""
2
2
 
3
- from ebird.api.utils import call
4
- from ebird.api.validation import (
3
+ from ebird.api.requests.utils import call
4
+ from ebird.api.requests.validation import (
5
5
  clean_area,
6
6
  clean_code,
7
7
  clean_date,
@@ -4,7 +4,7 @@
4
4
 
5
5
  import socket
6
6
 
7
- from ebird.api import (
7
+ from ebird.api.requests import (
8
8
  checklists,
9
9
  constants,
10
10
  hotspots,
@@ -13,7 +13,7 @@ from ebird.api import (
13
13
  statistics,
14
14
  taxonomy,
15
15
  )
16
- from ebird.api.validation import clean_locale
16
+ from ebird.api.requests.validation import clean_locale
17
17
 
18
18
 
19
19
  class Client:
@@ -2,8 +2,8 @@
2
2
 
3
3
  from urllib.error import HTTPError
4
4
 
5
- from ebird.api.utils import call
6
- from ebird.api.validation import (
5
+ from ebird.api.requests.utils import call
6
+ from ebird.api.requests.validation import (
7
7
  clean_back,
8
8
  clean_dist,
9
9
  clean_lat,
@@ -2,8 +2,8 @@
2
2
 
3
3
  """Functions for fetching information about what species have been seen."""
4
4
 
5
- from ebird.api.utils import call
6
- from ebird.api.validation import (
5
+ from ebird.api.requests.utils import call
6
+ from ebird.api.requests.validation import (
7
7
  clean_areas,
8
8
  clean_back,
9
9
  clean_categories,
@@ -1,7 +1,7 @@
1
1
  """Functions for fetching information about regions."""
2
2
 
3
- from ebird.api.utils import call
4
- from ebird.api.validation import clean_region, clean_region_type
3
+ from ebird.api.requests.utils import call
4
+ from ebird.api.requests.validation import clean_region, clean_region_type
5
5
 
6
6
  REGION_LIST_URL = "https://api.ebird.org/v2/ref/region/list/%s/%s"
7
7
  ADJACENT_REGIONS_URL = "https://api.ebird.org/v2/ref/adjacent/%s"
@@ -1,7 +1,7 @@
1
1
  """Functions for fetching information about species."""
2
2
 
3
- from ebird.api.utils import call
4
- from ebird.api.validation import clean_area
3
+ from ebird.api.requests.utils import call
4
+ from ebird.api.requests.validation import clean_area
5
5
 
6
6
  SPECIES_LIST_URL = "https://api.ebird.org/v2/product/spplist/%s"
7
7
 
@@ -1,7 +1,7 @@
1
1
  """Functions for fetching basic statistics about observers and observations."""
2
2
 
3
- from ebird.api.utils import call
4
- from ebird.api.validation import (
3
+ from ebird.api.requests.utils import call
4
+ from ebird.api.requests.validation import (
5
5
  clean_area,
6
6
  clean_date,
7
7
  clean_max_observers,
@@ -1,7 +1,7 @@
1
1
  """Functions for fetching information about the taxonomy used by eBird."""
2
2
 
3
- from ebird.api.utils import call
4
- from ebird.api.validation import (
3
+ from ebird.api.requests.utils import call
4
+ from ebird.api.requests.validation import (
5
5
  clean_categories,
6
6
  clean_codes,
7
7
  clean_locale,
@@ -1,10 +1,12 @@
1
1
  """Various functions used in the API."""
2
2
 
3
3
  import json
4
+ import time
5
+ from urllib.error import HTTPError
4
6
  from urllib.parse import urlencode
5
7
  from urllib.request import Request, urlopen
6
8
 
7
- from ebird.api import constants
9
+ from ebird.api.requests import constants
8
10
 
9
11
  _parameter_defaults = {
10
12
  "back": constants.DEFAULT_BACK,
@@ -74,7 +76,7 @@ def filter_parameters(params):
74
76
  return filtered
75
77
 
76
78
 
77
- def get_response(url, params=None, headers=None):
79
+ def get_response(url, params=None, headers=None, max_retries=3, backoff_factor=1.0):
78
80
  """Get the content from the eBird API.
79
81
 
80
82
  :param url: the URL for the API call.
@@ -84,7 +86,14 @@ def get_response(url, params=None, headers=None):
84
86
  :type params: dict
85
87
 
86
88
  :param headers: the headers to add to the request.
87
- :type params: dict
89
+ :type headers: dict
90
+
91
+ :param max_retries: number of times to retry after a 429 response.
92
+ :type max_retries: int
93
+
94
+ :param backoff_factor: seconds to wait before the first retry; doubles
95
+ on each subsequent attempt.
96
+ :type backoff_factor: float
88
97
 
89
98
  :return: the content returned by the API
90
99
  :rtype: str
@@ -104,7 +113,15 @@ def get_response(url, params=None, headers=None):
104
113
  for name, value in headers.items():
105
114
  request.add_header(name, value)
106
115
 
107
- return urlopen(request).read()
116
+ for attempt in range(max_retries + 1):
117
+ try:
118
+ return urlopen(request).read()
119
+ except HTTPError as exc:
120
+ if attempt == max_retries:
121
+ raise
122
+ retry_after = exc.headers.get("Retry-After") if exc.code == 429 else None
123
+ delay = float(retry_after) if retry_after else backoff_factor * (2**attempt)
124
+ time.sleep(delay)
108
125
 
109
126
 
110
127
  def get_json(content):
@@ -138,7 +155,7 @@ def save_json(filename, data, indent=None):
138
155
  json.dump(data, outfile, indent=indent)
139
156
 
140
157
 
141
- def call(url, params, headers):
158
+ def call(url, params, headers, max_retries=3, backoff_factor=1.0):
142
159
  """Call the eBird API.
143
160
 
144
161
  :param url: the URL for the API call.
@@ -148,7 +165,14 @@ def call(url, params, headers):
148
165
  :type params: dict
149
166
 
150
167
  :param headers: the headers to add to the request.
151
- :type params: dict
168
+ :type headers: dict
169
+
170
+ :param max_retries: number of times to retry after a 429 response.
171
+ :type max_retries: int
172
+
173
+ :param backoff_factor: seconds to wait before the first retry; doubles
174
+ on each subsequent attempt.
175
+ :type backoff_factor: float
152
176
 
153
177
  :return: the content returned by the API
154
178
  :rtype: dict | list
@@ -161,4 +185,8 @@ def call(url, params, headers):
161
185
  """
162
186
  filtered = filter_parameters(params)
163
187
  mapped = map_parameters(filtered)
164
- return get_json(get_response(url, mapped, headers))
188
+ return get_json(
189
+ get_response(
190
+ url, mapped, headers, max_retries=max_retries, backoff_factor=backoff_factor
191
+ )
192
+ )
@@ -6,7 +6,7 @@ import re
6
6
  from datetime import date, datetime
7
7
  from enum import Enum
8
8
 
9
- from ebird.api import constants
9
+ from ebird.api.requests import constants
10
10
 
11
11
  _locales = constants.LOCALES.values()
12
12
  _region_types = ", ".join(constants.REGION_TYPES)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ebird-api
3
- Version: 3.4.2
3
+ Version: 4.1.0
4
4
  Summary: Wrapper for accessing the eBird API
5
5
  Author-email: Project Babbler <projectbabbler@gmail.com>
6
6
  License: MIT License
@@ -15,28 +15,26 @@ Classifier: License :: OSI Approved :: MIT License
15
15
  Classifier: Operating System :: OS Independent
16
16
  Classifier: Programming Language :: Python
17
17
  Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.8
19
- Classifier: Programming Language :: Python :: 3.9
20
18
  Classifier: Programming Language :: Python :: 3.10
21
19
  Classifier: Programming Language :: Python :: 3.11
22
20
  Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
23
22
  Classifier: Programming Language :: Python :: Implementation :: CPython
24
23
  Classifier: Natural Language :: English
25
24
  Classifier: Topic :: Utilities
26
25
  Classifier: Topic :: Internet
27
- Requires-Python: >=3.8
26
+ Requires-Python: >=3.10
28
27
  Description-Content-Type: text/markdown
29
28
  License-File: LICENSE.txt
30
29
  Dynamic: license-file
31
30
 
32
- [![Build Status](https://travis-ci.org/ProjectBabbler/ebird-api.svg?branch=master)](https://travis-ci.org/ProjectBabbler/ebird-api)
33
31
  [![PyPI version](https://badge.fury.io/py/ebird-api.svg)](https://badge.fury.io/py/ebird-api)
34
32
  [![Supported Python Versions](https://img.shields.io/pypi/pyversions/ebird-api.svg)](https://img.shields.io/pypi/pyversions/ebird-api)
35
33
 
36
34
  # eBird API
37
35
 
38
- eBird API provides a set of wrapper functions for accessing the end-points
39
- in the eBird API 2.0.
36
+ eBird API Requests provides a set of wrapper functions for accessing the
37
+ end-points in the eBird API 2.0.
40
38
 
41
39
  ## Install
42
40
 
@@ -71,7 +69,7 @@ what you want to do - they will be interested to hear it.
71
69
  ```python
72
70
  import os
73
71
 
74
- from ebird.api import get_observations
72
+ from ebird.api.requests import get_observations
75
73
 
76
74
  # Always store secrets outside the code, so you don't accidentally
77
75
  # commit them. Environment variables are ideal for this.
@@ -97,7 +95,7 @@ regions:
97
95
  ```python
98
96
  import os
99
97
 
100
- from ebird.api import get_observations
98
+ from ebird.api.requests import get_observations
101
99
 
102
100
  api_key = os.environ["EBIRD_API_KEY"]
103
101
 
@@ -119,7 +117,7 @@ or taxonomy:
119
117
  ```python
120
118
  import os
121
119
 
122
- from ebird.api import get_observations
120
+ from ebird.api.requests import get_observations
123
121
 
124
122
  api_key = os.environ["EBIRD_API_KEY"]
125
123
 
@@ -134,7 +132,7 @@ species:
134
132
  ```python
135
133
  import os
136
134
 
137
- from ebird.api import get_nearby_observations
135
+ from ebird.api.requests import get_nearby_observations
138
136
 
139
137
  api_key = os.environ["EBIRD_API_KEY"]
140
138
 
@@ -151,7 +149,7 @@ a small number of species:
151
149
  ```python
152
150
  import os
153
151
 
154
- from ebird.api import (
152
+ from ebird.api.requests import (
155
153
  get_notable_observations,
156
154
  get_nearby_notable,
157
155
  get_species_observations,
@@ -178,7 +176,7 @@ For the more travel-minded you can also find out the nearest place to see a give
178
176
  ```python
179
177
  import os
180
178
 
181
- from ebird.api import get_nearest_species
179
+ from ebird.api.requests import get_nearest_species
182
180
 
183
181
  api_key = os.environ["EBIRD_API_KEY"]
184
182
 
@@ -199,7 +197,7 @@ checklist. You can then call get_checklist() to get the list of observations.
199
197
  ```python
200
198
  import os
201
199
 
202
- from ebird.api import get_visits, get_checklist
200
+ from ebird.api.requests import get_visits, get_checklist
203
201
 
204
202
  api_key = os.environ["EBIRD_API_KEY"]
205
203
 
@@ -224,7 +222,7 @@ on the location of a given hotspot.
224
222
  ```python
225
223
  import os
226
224
 
227
- from ebird.api import get_hotspots, get_nearby_hotspots, get_hotspot
225
+ from ebird.api.requests import get_hotspots, get_nearby_hotspots, get_hotspot
228
226
 
229
227
  api_key = os.environ["EBIRD_API_KEY"]
230
228
 
@@ -251,7 +249,7 @@ by a region use get_region().
251
249
  ```python
252
250
  import os
253
251
 
254
- from ebird.api import get_regions, get_adjacent_regions, get_region
252
+ from ebird.api.requests import get_regions, get_adjacent_regions, get_region
255
253
 
256
254
  api_key = os.environ["EBIRD_API_KEY"]
257
255
 
@@ -282,7 +280,7 @@ that are used in the other API calls.
282
280
  ```python
283
281
  import os
284
282
 
285
- from ebird.api import get_taxonomy, get_taxonomy_forms, get_taxonomy_versions
283
+ from ebird.api.requests import get_taxonomy, get_taxonomy_forms, get_taxonomy_versions
286
284
 
287
285
  api_key = os.environ["EBIRD_API_KEY"]
288
286
 
@@ -315,7 +313,7 @@ lots of people are out trying to get the greatest number of species.
315
313
  import os
316
314
 
317
315
  from datetime import date
318
- from ebird.api import get_top_100, get_totals
316
+ from ebird.api.requests import get_top_100, get_totals
319
317
 
320
318
  api_key = os.environ["EBIRD_API_KEY"]
321
319
 
@@ -335,7 +333,7 @@ have to keep passing them as arguments.
335
333
  ```python
336
334
  import os
337
335
 
338
- from ebird.api import Client
336
+ from ebird.api.requests import Client
339
337
 
340
338
  api_key = os.environ["EBIRD_API_KEY"]
341
339
  locale = 'es'
@@ -357,8 +355,8 @@ only returns JSON.
357
355
 
358
356
  ## Compatibility
359
357
 
360
- ebird-api works with currently supported versions of Python, 3.8+. However,
361
- it is known to work with earlier versions, at least 3.5 - 3.7, without any
358
+ ebird-api works with currently supported versions of Python, 3.10+. However,
359
+ it is known to work with earlier versions, at least 3.5 - 3.8, without any
362
360
  problems.
363
361
 
364
362
  ## Troubleshooting
@@ -0,0 +1,21 @@
1
+ CHANGELOG.md
2
+ LICENSE.txt
3
+ README.md
4
+ pyproject.toml
5
+ setup.py
6
+ src/ebird/api/requests/__init__.py
7
+ src/ebird/api/requests/checklists.py
8
+ src/ebird/api/requests/client.py
9
+ src/ebird/api/requests/constants.py
10
+ src/ebird/api/requests/hotspots.py
11
+ src/ebird/api/requests/observations.py
12
+ src/ebird/api/requests/regions.py
13
+ src/ebird/api/requests/species.py
14
+ src/ebird/api/requests/statistics.py
15
+ src/ebird/api/requests/taxonomy.py
16
+ src/ebird/api/requests/utils.py
17
+ src/ebird/api/requests/validation.py
18
+ src/ebird_api.egg-info/PKG-INFO
19
+ src/ebird_api.egg-info/SOURCES.txt
20
+ src/ebird_api.egg-info/dependency_links.txt
21
+ src/ebird_api.egg-info/top_level.txt
@@ -1,35 +0,0 @@
1
- # flake8: noqa
2
-
3
- """A set of wrapper functions for accessing the eBird API."""
4
-
5
- __version__ = "3.4.2"
6
-
7
- from ebird.api.checklists import get_checklist, get_visits
8
- from ebird.api.client import Client
9
- from ebird.api.constants import LOCALES
10
- from ebird.api.hotspots import (
11
- get_hotspot,
12
- get_hotspots,
13
- get_location,
14
- get_nearby_hotspots,
15
- )
16
- from ebird.api.observations import (
17
- get_historic_observations,
18
- get_nearby_notable,
19
- get_nearby_observations,
20
- get_nearby_species,
21
- get_nearest_species,
22
- get_notable_observations,
23
- get_observations,
24
- get_species_observations,
25
- )
26
- from ebird.api.regions import get_adjacent_regions, get_region, get_regions
27
- from ebird.api.species import get_species_list
28
- from ebird.api.statistics import get_top_100, get_totals
29
- from ebird.api.taxonomy import (
30
- get_taxonomy,
31
- get_taxonomy_forms,
32
- get_taxonomy_groups,
33
- get_taxonomy_locales,
34
- get_taxonomy_versions,
35
- )
@@ -1,21 +0,0 @@
1
- CHANGELOG.md
2
- LICENSE.txt
3
- README.md
4
- pyproject.toml
5
- setup.py
6
- src/ebird/api/__init__.py
7
- src/ebird/api/checklists.py
8
- src/ebird/api/client.py
9
- src/ebird/api/constants.py
10
- src/ebird/api/hotspots.py
11
- src/ebird/api/observations.py
12
- src/ebird/api/regions.py
13
- src/ebird/api/species.py
14
- src/ebird/api/statistics.py
15
- src/ebird/api/taxonomy.py
16
- src/ebird/api/utils.py
17
- src/ebird/api/validation.py
18
- src/ebird_api.egg-info/PKG-INFO
19
- src/ebird_api.egg-info/SOURCES.txt
20
- src/ebird_api.egg-info/dependency_links.txt
21
- src/ebird_api.egg-info/top_level.txt
File without changes
File without changes
File without changes