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.
Files changed (41) hide show
  1. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/PKG-INFO +14 -1
  2. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/README.md +13 -0
  3. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/pyproject.toml +2 -2
  4. ebird_api_data-0.5.0/src/ebird/api/data/__init__.py +1 -0
  5. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/admin.py +2 -15
  6. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/factories.py +0 -50
  7. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/fixtures/README.md +0 -1
  8. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/fixtures/generate_portugal_data.py +1 -4
  9. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/fixtures/portugal_observations.json +0 -4908
  10. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/loaders.py +159 -88
  11. ebird_api_data-0.5.0/src/ebird/api/data/migrations/0003_remove_checklist_published_and_more.py +24 -0
  12. ebird_api_data-0.5.0/src/ebird/api/data/migrations/0004_remove_observer_multiple.py +17 -0
  13. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/__init__.py +0 -2
  14. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/checklist.py +0 -5
  15. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/models.md +0 -50
  16. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/observation.py +0 -5
  17. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/observer.py +0 -6
  18. ebird_api_data-0.4.0/src/ebird/api/data/__init__.py +0 -1
  19. ebird_api_data-0.4.0/src/ebird/api/data/models/filter.py +0 -116
  20. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/.gitignore +0 -0
  21. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/LICENSE +0 -0
  22. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/apps.py +0 -0
  23. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/faker_providers.py +0 -0
  24. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/fields.py +0 -0
  25. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/locale/en/LC_MESSAGES/django.mo +0 -0
  26. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/locale/en/LC_MESSAGES/django.po +0 -0
  27. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/management/__init__.py +0 -0
  28. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/management/commands/__init__.py +0 -0
  29. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/management/commands/add_checklists.py +0 -0
  30. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/migrations/0001_initial.py +0 -0
  31. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/migrations/0002_expand_filter.py +0 -0
  32. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/migrations/__init__.py +0 -0
  33. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/country.py +0 -0
  34. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/county.py +0 -0
  35. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/location.py +0 -0
  36. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/species.py +0 -0
  37. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/models/state.py +0 -0
  38. {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
  39. {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
  40. {ebird_api_data-0.4.0 → ebird_api_data-0.5.0}/src/ebird/api/data/templates/data/widgets/translation_field.html +0 -0
  41. {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.4.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.4.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.4.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", "multiple", "enabled")
269
+ list_display = ("name", "identifier", "enabled")
270
270
  ordering = ("name",)
271
271
  search_fields = ("name", "identifier")
272
- list_filter = ("multiple", "enabled")
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)
@@ -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, multiple, enabled in OBSERVERS
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,