ebird-api-data 0.4.0__tar.gz → 0.5.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.
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/PKG-INFO +14 -1
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/README.md +13 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/pyproject.toml +2 -2
- ebird_api_data-0.5.0/src/ebird/api/data/__init__.py +1 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/admin.py +2 -15
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/factories.py +0 -50
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/fixtures/README.md +0 -1
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/fixtures/generate_portugal_data.py +1 -4
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/fixtures/portugal_observations.json +0 -4908
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/loaders.py +159 -88
- ebird_api_data-0.5.0/src/ebird/api/data/migrations/0003_remove_checklist_published_and_more.py +24 -0
- ebird_api_data-0.5.0/src/ebird/api/data/migrations/0004_remove_observer_multiple.py +17 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/__init__.py +0 -2
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/checklist.py +0 -5
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/models.md +0 -50
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/observation.py +0 -5
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/observer.py +0 -6
- ebird_api_data-0.4.0/src/ebird/api/data/__init__.py +0 -1
- ebird_api_data-0.4.0/src/ebird/api/data/models/filter.py +0 -116
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/.gitignore +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/LICENSE +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/apps.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/faker_providers.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/fields.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/locale/en/LC_MESSAGES/django.mo +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/locale/en/LC_MESSAGES/django.po +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/management/__init__.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/management/commands/__init__.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/management/commands/add_checklists.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/migrations/0001_initial.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/migrations/0002_expand_filter.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/migrations/__init__.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/country.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/county.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/location.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/species.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/state.py +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/templates/admin/data/species/change_list_object_tools.html +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/templates/admin/data/species/fetch_species.html +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/templates/data/widgets/translation_field.html +0 -0
- {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/widgets.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ebird-api-data
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: eBird API Data is a reusable Django app for loading data from eBird into a database.
|
|
5
5
|
Author-email: Stuart MacKay <smackay@flagstonesoftware.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -158,6 +158,19 @@ python manage.py runserver
|
|
|
158
158
|
Now, either visit the site, http:localhost:8000/, or log into the Django Admin,
|
|
159
159
|
http:localhost:8000/admin to browse the tables.
|
|
160
160
|
|
|
161
|
+
IMPORTANT: There is a serious flaw in the eBird API - observers are identified
|
|
162
|
+
by name. That means if more than one observer shares the same name then only
|
|
163
|
+
one Observer record will be added to the database, and all the checklists will
|
|
164
|
+
be assigned to them. In practice, most people ensure their name is unique by
|
|
165
|
+
adding middle initial's etc. However it is a problem with "Anonymous eBirder".
|
|
166
|
+
The solution is to add two Observer records with the name "Anonymous eBirder",
|
|
167
|
+
and a fake identifier, e.g. ANON1, ANON2, etc. That way the loader will first
|
|
168
|
+
scrape the web page for the checklist where the identifier, e.g. USER2743448,
|
|
169
|
+
can be found, and so the checklist will be assigned to the correct Observer.
|
|
170
|
+
Use this workaround for any other observers you encounter that share the same
|
|
171
|
+
name. This won't work retroactively, but then you can delete the checklists,
|
|
172
|
+
and manually reload them.
|
|
173
|
+
|
|
161
174
|
## Project Information
|
|
162
175
|
|
|
163
176
|
* Documentation: https://ebird-api-data.readthedocs.io/en/latest/
|
|
@@ -129,6 +129,19 @@ python manage.py runserver
|
|
|
129
129
|
Now, either visit the site, http:localhost:8000/, or log into the Django Admin,
|
|
130
130
|
http:localhost:8000/admin to browse the tables.
|
|
131
131
|
|
|
132
|
+
IMPORTANT: There is a serious flaw in the eBird API - observers are identified
|
|
133
|
+
by name. That means if more than one observer shares the same name then only
|
|
134
|
+
one Observer record will be added to the database, and all the checklists will
|
|
135
|
+
be assigned to them. In practice, most people ensure their name is unique by
|
|
136
|
+
adding middle initial's etc. However it is a problem with "Anonymous eBirder".
|
|
137
|
+
The solution is to add two Observer records with the name "Anonymous eBirder",
|
|
138
|
+
and a fake identifier, e.g. ANON1, ANON2, etc. That way the loader will first
|
|
139
|
+
scrape the web page for the checklist where the identifier, e.g. USER2743448,
|
|
140
|
+
can be found, and so the checklist will be assigned to the correct Observer.
|
|
141
|
+
Use this workaround for any other observers you encounter that share the same
|
|
142
|
+
name. This won't work retroactively, but then you can delete the checklists,
|
|
143
|
+
and manually reload them.
|
|
144
|
+
|
|
132
145
|
## Project Information
|
|
133
146
|
|
|
134
147
|
* Documentation: https://ebird-api-data.readthedocs.io/en/latest/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ebird-api-data"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.5.0"
|
|
4
4
|
description = "eBird API Data is a reusable Django app for loading data from eBird into a database."
|
|
5
5
|
keywords = ["checklists", "observations", "species", "Django", "eBird", "models"]
|
|
6
6
|
license = "MIT"
|
|
@@ -64,7 +64,7 @@ dev-dependencies = [
|
|
|
64
64
|
]
|
|
65
65
|
|
|
66
66
|
[tool.bumpversion]
|
|
67
|
-
current_version = "0.
|
|
67
|
+
current_version = "0.5.0"
|
|
68
68
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
|
69
69
|
serialize = ["{major}.{minor}.{patch}"]
|
|
70
70
|
ignore_missing_version = false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.5.0"
|
|
@@ -266,10 +266,10 @@ class ObservationAdmin(admin.ModelAdmin):
|
|
|
266
266
|
|
|
267
267
|
@admin.register(models.Observer)
|
|
268
268
|
class ObserverAdmin(admin.ModelAdmin):
|
|
269
|
-
list_display = ("name", "identifier", "
|
|
269
|
+
list_display = ("name", "identifier", "enabled")
|
|
270
270
|
ordering = ("name",)
|
|
271
271
|
search_fields = ("name", "identifier")
|
|
272
|
-
list_filter = ("
|
|
272
|
+
list_filter = ("enabled",)
|
|
273
273
|
form = ObservationForm
|
|
274
274
|
|
|
275
275
|
def formfield_for_dbfield(self, db_field, request, **kwargs):
|
|
@@ -370,16 +370,3 @@ class SpeciesAdmin(admin.ModelAdmin):
|
|
|
370
370
|
extra_context = extra_context or {}
|
|
371
371
|
extra_context["fetch_species_url"] = reverse("admin:data_species_fetch")
|
|
372
372
|
return super().changelist_view(request, extra_context=extra_context)
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
@admin.register(models.Filter)
|
|
376
|
-
class FilterAdmin(admin.ModelAdmin):
|
|
377
|
-
list_display = ("name", "enabled")
|
|
378
|
-
search_fields = ("name", "species__common_name")
|
|
379
|
-
list_filter = ("enabled",)
|
|
380
|
-
autocomplete_fields = ("species", "location", "update_species")
|
|
381
|
-
formfield_overrides = {
|
|
382
|
-
TextField: {
|
|
383
|
-
"widget": TextInput(attrs={"class": "vTextField"}),
|
|
384
|
-
}
|
|
385
|
-
}
|
|
@@ -34,7 +34,6 @@ from ebird.api.data.models import (
|
|
|
34
34
|
Observer,
|
|
35
35
|
Checklist,
|
|
36
36
|
Observation,
|
|
37
|
-
Filter,
|
|
38
37
|
)
|
|
39
38
|
from ebird.api.data.faker_providers import (
|
|
40
39
|
BirdProvider,
|
|
@@ -144,7 +143,6 @@ class ObserverFactory(DjangoModelFactory):
|
|
|
144
143
|
identifier = factory.LazyFunction(lambda: fake.observer_identifier())
|
|
145
144
|
name = factory.LazyFunction(lambda: fake.observer_name())
|
|
146
145
|
original = factory.LazyAttribute(lambda obj: obj.name)
|
|
147
|
-
multiple = False
|
|
148
146
|
enabled = True
|
|
149
147
|
|
|
150
148
|
data = factory.LazyFunction(
|
|
@@ -167,7 +165,6 @@ class ChecklistFactory(DjangoModelFactory):
|
|
|
167
165
|
# Timestamps
|
|
168
166
|
added = factory.Faker("date_time_this_year", tzinfo=None)
|
|
169
167
|
edited = factory.LazyAttribute(lambda obj: obj.added)
|
|
170
|
-
published = True
|
|
171
168
|
|
|
172
169
|
# Relationships
|
|
173
170
|
country = factory.SubFactory(CountryFactory)
|
|
@@ -278,7 +275,6 @@ class ObservationFactory(DjangoModelFactory):
|
|
|
278
275
|
|
|
279
276
|
# Timestamps
|
|
280
277
|
edited = factory.Faker("date_time_this_year", tzinfo=None)
|
|
281
|
-
published = True
|
|
282
278
|
|
|
283
279
|
# Relationships
|
|
284
280
|
checklist = factory.SubFactory(ChecklistFactory)
|
|
@@ -314,52 +310,6 @@ class ObservationFactory(DjangoModelFactory):
|
|
|
314
310
|
data = factory.Dict({})
|
|
315
311
|
|
|
316
312
|
|
|
317
|
-
class FilterFactory(DjangoModelFactory):
|
|
318
|
-
"""
|
|
319
|
-
Factory for Filter model.
|
|
320
|
-
|
|
321
|
-
Creates filters for bulk-updating species in observations.
|
|
322
|
-
"""
|
|
323
|
-
|
|
324
|
-
class Meta:
|
|
325
|
-
model = Filter
|
|
326
|
-
|
|
327
|
-
enabled = True
|
|
328
|
-
name = factory.Faker("sentence", nb_words=3)
|
|
329
|
-
|
|
330
|
-
species = factory.SubFactory(SpeciesFactory)
|
|
331
|
-
update_species = factory.SubFactory(SpeciesFactory)
|
|
332
|
-
|
|
333
|
-
# Optional geographic filters
|
|
334
|
-
country = factory.Maybe(
|
|
335
|
-
"with_country",
|
|
336
|
-
yes_declaration=factory.SubFactory(CountryFactory),
|
|
337
|
-
no_declaration=None
|
|
338
|
-
)
|
|
339
|
-
state = factory.Maybe(
|
|
340
|
-
"with_state",
|
|
341
|
-
yes_declaration=factory.SubFactory(StateFactory),
|
|
342
|
-
no_declaration=None
|
|
343
|
-
)
|
|
344
|
-
county = factory.Maybe(
|
|
345
|
-
"with_county",
|
|
346
|
-
yes_declaration=factory.SubFactory(CountyFactory),
|
|
347
|
-
no_declaration=None
|
|
348
|
-
)
|
|
349
|
-
location = factory.Maybe(
|
|
350
|
-
"with_location",
|
|
351
|
-
yes_declaration=factory.SubFactory(LocationFactory),
|
|
352
|
-
no_declaration=None
|
|
353
|
-
)
|
|
354
|
-
|
|
355
|
-
class Params:
|
|
356
|
-
# Parameters to control which geographic filters to include
|
|
357
|
-
with_country = False
|
|
358
|
-
with_state = False
|
|
359
|
-
with_county = False
|
|
360
|
-
with_location = False
|
|
361
|
-
|
|
362
|
-
|
|
363
313
|
# Convenience functions for common scenarios
|
|
364
314
|
|
|
365
315
|
def create_coastal_checklist(**kwargs):
|
|
@@ -215,7 +215,6 @@ class ChecklistTestCase(TestCase):
|
|
|
215
215
|
|
|
216
216
|
# Verify the checklist was created
|
|
217
217
|
self.assertIsNotNone(checklist.identifier)
|
|
218
|
-
self.assertTrue(checklist.published)
|
|
219
218
|
|
|
220
219
|
# Verify observations were created
|
|
221
220
|
observations = Observation.objects.filter(checklist=checklist)
|
{ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/fixtures/generate_portugal_data.py
RENAMED
|
@@ -320,14 +320,13 @@ def generate_observers():
|
|
|
320
320
|
"fields": {
|
|
321
321
|
"name": name,
|
|
322
322
|
"original": name,
|
|
323
|
-
"multiple": multiple,
|
|
324
323
|
"enabled": enabled,
|
|
325
324
|
"data": {},
|
|
326
325
|
"created": "2024-01-01T00:00:00Z",
|
|
327
326
|
"modified": "2024-01-01T00:00:00Z",
|
|
328
327
|
}
|
|
329
328
|
}
|
|
330
|
-
for obs_id, name,
|
|
329
|
+
for obs_id, name, enabled in OBSERVERS
|
|
331
330
|
]
|
|
332
331
|
|
|
333
332
|
|
|
@@ -409,7 +408,6 @@ def generate_checklists_and_observations():
|
|
|
409
408
|
"fields": {
|
|
410
409
|
"added": started.isoformat() + "Z",
|
|
411
410
|
"edited": started.isoformat() + "Z",
|
|
412
|
-
"published": True,
|
|
413
411
|
"country_id": "PT",
|
|
414
412
|
"state_id": state_code,
|
|
415
413
|
"county_id": county_code,
|
|
@@ -464,7 +462,6 @@ def generate_checklists_and_observations():
|
|
|
464
462
|
"pk": obs_id,
|
|
465
463
|
"fields": {
|
|
466
464
|
"edited": started.isoformat() + "Z",
|
|
467
|
-
"published": True,
|
|
468
465
|
"checklist_id": checklist_id,
|
|
469
466
|
"species_id": species_code,
|
|
470
467
|
"observer_id": observer_id,
|