diff --git a/docker/Dockerfile b/docker/Dockerfile index f237870..760b53c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,15 +1,15 @@ FROM python:3.10-slim-bullseye AS runtime -COPY naturerecorderpy-1.0.23.0 /opt/naturerecorderpy-1.0.23.0 +COPY naturerecorderpy-1.0.24.0 /opt/naturerecorderpy-1.0.24.0 -WORKDIR /opt/naturerecorderpy-1.0.23.0 +WORKDIR /opt/naturerecorderpy-1.0.24.0 RUN apt-get update -y RUN pip install -r requirements.txt -RUN pip install nature_recorder-1.0.23-py3-none-any.whl +RUN pip install nature_recorder-1.0.24-py3-none-any.whl -ENV NATURE_RECORDER_DATA_FOLDER=/var/opt/naturerecorderpy-1.0.23.0 -ENV NATURE_RECORDER_DB=/var/opt/naturerecorderpy-1.0.23.0/naturerecorder.db +ENV NATURE_RECORDER_DATA_FOLDER=/var/opt/naturerecorderpy-1.0.24.0 +ENV NATURE_RECORDER_DB=/var/opt/naturerecorderpy-1.0.24.0/naturerecorder.db ENTRYPOINT [ "python" ] CMD [ "-m", "naturerec_web", "production" ] diff --git a/features/steps/common.py b/features/steps/common.py index ab4621d..f084184 100644 --- a/features/steps/common.py +++ b/features/steps/common.py @@ -69,7 +69,7 @@ def _(context): species = create_test_species(row["Species"], category.id) gender = [key for key, value in Gender.gender_map().items() if value == row["Gender"]][0] with_young = 1 if row["WithYoung"] == "Yes" else 0 - _ = create_sighting(location.id, species.id, sighting_date, int(row["Number"]), gender, with_young) + _ = create_sighting(location.id, species.id, sighting_date, int(row["Number"]), gender, with_young, None) @given("A set of conservation status schemes") diff --git a/features/steps/jobs.py b/features/steps/jobs.py index 8b43f79..8bf61f1 100644 --- a/features/steps/jobs.py +++ b/features/steps/jobs.py @@ -21,7 +21,7 @@ def _(context): category = create_test_category("Birds") species = create_test_species("Cormorant", category.id) gender = [key for key, value in Gender.gender_map().items() if value == "Unknown"][0] - _ = create_sighting(location.id, species.id, sighting_date, None, gender, 0) + _ = create_sighting(location.id, species.id, sighting_date, None, gender, 0, None) # Kick off the export exporter = SightingsExportHelper("sightings.csv", None, None, None, None) diff --git a/setup.py b/setup.py index 6620aaf..3052966 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ def find_package_files(directory, remove_root): setuptools.setup( name="nature_recorder", - version="1.0.23", + version="1.0.24", description="Wildlife sightings database", packages=setuptools.find_packages("src"), include_package_data=True, diff --git a/sql/add_notes.sql b/sql/add_notes.sql new file mode 100644 index 0000000..1455bc9 --- /dev/null +++ b/sql/add_notes.sql @@ -0,0 +1,2 @@ +ALTER TABLE Sightings + ADD Notes TEXT NULL; diff --git a/src/naturerec_model/data_exchange/sightings_data_exchange_helper_base.py b/src/naturerec_model/data_exchange/sightings_data_exchange_helper_base.py index 7842c84..533b1bd 100644 --- a/src/naturerec_model/data_exchange/sightings_data_exchange_helper_base.py +++ b/src/naturerec_model/data_exchange/sightings_data_exchange_helper_base.py @@ -31,6 +31,8 @@ +-----------+-----------------------------------------------------------------------------+ | Longitude | Longitude for the location in decimal format | +-----------+-----------------------------------------------------------------------------+ +| Notes | Sighting notes | ++-----------+-----------------------------------------------------------------------------+ """ from .data_exchange_helper_base import DataExchangeHelperBase @@ -51,7 +53,8 @@ class SightingsDataExchangeHelperBase(DataExchangeHelperBase): 'Postcode', 'Country', 'Latitude', - 'Longitude' + 'Longitude', + 'Notes' ] def __init__(self, action): diff --git a/src/naturerec_model/data_exchange/sightings_import_helper.py b/src/naturerec_model/data_exchange/sightings_import_helper.py index d225098..51ea50f 100644 --- a/src/naturerec_model/data_exchange/sightings_import_helper.py +++ b/src/naturerec_model/data_exchange/sightings_import_helper.py @@ -39,7 +39,8 @@ def import_sightings(self): number = int(row[2]) if row[2].strip() else None gender = [key for key, value in Gender.gender_map().items() if value == row[3].strip().title()][0] with_young = 1 if row[4].strip().title() == "Yes" else 0 - _ = create_sighting(location_id, species_id, date, number, gender, with_young) + notes = row[14] if row[14] else None + _ = create_sighting(location_id, species_id, date, number, gender, with_young, notes) def _read_csv_rows(self): """ @@ -74,7 +75,7 @@ def _validate_row(cls, row, row_number): :param row: CSV row (collection of fields) :param row_number: Row number for error reporting """ - if len(row) != 14: + if len(row) != 15: raise ValueError(f"Malformed data at row {row_number}") cls._check_not_empty(row, 0, row_number) # Species diff --git a/src/naturerec_model/logic/sightings.py b/src/naturerec_model/logic/sightings.py index 8edd62a..041eacb 100644 --- a/src/naturerec_model/logic/sightings.py +++ b/src/naturerec_model/logic/sightings.py @@ -27,7 +27,7 @@ def _check_for_existing_records(session, location_id, species_id, date): return [sighting.id for sighting in sightings] -def create_sighting(location_id, species_id, date, number, gender, with_young): +def create_sighting(location_id, species_id, date, number, gender, with_young, notes): """ Create a new sighting @@ -37,6 +37,7 @@ def create_sighting(location_id, species_id, date, number, gender, with_young): :param number: Number of individuals seen :param gender: Gender of the individuals seen :param with_young: Whether or not young were seen + :param notes: Sighting notes :return: An instance of the Sighting class for the created record """ try: @@ -51,7 +52,8 @@ def create_sighting(location_id, species_id, date, number, gender, with_young): sighting_date=date, number=number, gender=gender, - withYoung=with_young) + withYoung=with_young, + notes=notes) session.add(sighting) except IntegrityError as e: raise ValueError("Invalid sighting properties") from e @@ -59,7 +61,7 @@ def create_sighting(location_id, species_id, date, number, gender, with_young): return sighting -def update_sighting(sighting_id, location_id, species_id, date, number, gender, with_young): +def update_sighting(sighting_id, location_id, species_id, date, number, gender, with_young, notes): """ Update an existing sighting @@ -70,6 +72,7 @@ def update_sighting(sighting_id, location_id, species_id, date, number, gender, :param number: Number of individuals seen :param gender: Gender of the individuals seen :param with_young: Whether or not young were seen + :param notes: Sighting notes :return: An instance of the Sighting class for the updated record """ try: @@ -97,6 +100,7 @@ def update_sighting(sighting_id, location_id, species_id, date, number, gender, sighting.number = number sighting.gender = gender sighting.withYoung = with_young + sighting.notes = notes session.add(sighting) except IntegrityError as e: raise ValueError("Invalid sighting properties") from e diff --git a/src/naturerec_model/model/sighting.py b/src/naturerec_model/model/sighting.py index bbbaa7b..242f6db 100644 --- a/src/naturerec_model/model/sighting.py +++ b/src/naturerec_model/model/sighting.py @@ -32,6 +32,8 @@ class Sighting(Base): withYoung = Column(Integer, default=0, nullable=False) #: Number of individuals seen gender = Column(Integer, default=Gender.UNKNOWN, nullable=False) + #: Sighting notes + notes = Column(String, default=None, nullable=True) #: Related location instance location = relationship("Location", lazy="joined") @@ -50,7 +52,8 @@ def __repr__(self): f"date={self.date!r}, " \ f"number={self.number!r}, " \ f"withYoung={self.withYoung!r}, " \ - f"gender={self.gender!r})" + f"gender={self.gender!r}, " \ + f"notes={self.notes!r})" @property def sighting_date(self): @@ -88,5 +91,6 @@ def csv_columns(self): self.location.postcode, self.location.country, self.location.latitude, - self.location.longitude + self.location.longitude, + self.notes ] diff --git a/src/naturerec_web/sightings/sightings_blueprint.py b/src/naturerec_web/sightings/sightings_blueprint.py index 3062b24..78ac444 100644 --- a/src/naturerec_web/sightings/sightings_blueprint.py +++ b/src/naturerec_web/sightings/sightings_blueprint.py @@ -3,6 +3,7 @@ """ import datetime +import html from flask import Blueprint, render_template, request, session, redirect from flask_login import login_required from naturerec_model.logic import list_sightings, get_sighting, create_sighting, update_sighting @@ -186,6 +187,9 @@ def edit(sighting_id): category_id = get_posted_int("category") session["category_id"] = category_id + # Get the notes and escape them + notes = html.escape(request.form["notes"]) + if sighting_id: _ = update_sighting(sighting_id, location_id, @@ -193,7 +197,8 @@ def edit(sighting_id): sighting_date, get_posted_int("number"), get_posted_int("gender"), - get_posted_bool("with_young")) + get_posted_bool("with_young"), + notes) sighting = get_sighting(sighting_id) else: created_id = create_sighting(location_id, @@ -201,7 +206,8 @@ def edit(sighting_id): sighting_date, get_posted_int("number"), get_posted_int("gender"), - get_posted_bool("with_young")).id + get_posted_bool("with_young"), + notes).id sighting = get_sighting(created_id) # Construct the confirmation message @@ -210,7 +216,12 @@ def edit(sighting_id): f"at {sighting.location.name} " \ f"on {sighting.display_date}" - return _render_sighting_editing_page(sighting_id, message, None) + # If we're editing an existing sighting, return to the sightings list page, so the + # change can be seen in the sightings list. Otherwise, return to the editing page + if sighting_id: + return redirect("/sightings/list") + else: + return _render_sighting_editing_page(sighting_id, message, None) except ValueError as e: return _render_sighting_editing_page(sighting_id, None, e) else: diff --git a/src/naturerec_web/sightings/templates/sightings/edit.html b/src/naturerec_web/sightings/templates/sightings/edit.html index 35bd486..d3afdc6 100644 --- a/src/naturerec_web/sightings/templates/sightings/edit.html +++ b/src/naturerec_web/sightings/templates/sightings/edit.html @@ -5,6 +5,7 @@ {% set number = sighting.number if sighting.number else "" %} {% set current_gender = sighting.gender %} {% set current_with_young = sighting.withYoung %} + {% set current_notes = sighting.notes if sighting.notes else "" %} {% else %} {% set title = "Add Sighting" %} {% set submit_title = "Add Sighting" %} @@ -12,6 +13,7 @@ {% set number = "" %} {% set current_gender = "" %} {% set current_with_young = "" %} + {% set current_notes = "" %} {% endif %} {% set location_required = "required" %} {% set species_required = "required" %} @@ -58,6 +60,10 @@

{{ title }}

{% endfor %} +
+ + +
{% if sighting %} +
+ + + + + diff --git a/src/naturerec_web/sightings/templates/sightings/sightings.html b/src/naturerec_web/sightings/templates/sightings/sightings.html index 7e94536..3c5616b 100644 --- a/src/naturerec_web/sightings/templates/sightings/sightings.html +++ b/src/naturerec_web/sightings/templates/sightings/sightings.html @@ -9,6 +9,7 @@ Number Gender Young + {% if edit_enabled %} @@ -18,6 +19,11 @@ {% for sighting in sightings %} + {% if sighting.notes != None %} + {% set sighting_notes = sighting.notes %} + {% else %} + {% set sighting_notes = "" %} + {% endif %} {{ sighting.display_date }} {{ sighting.location.name }} @@ -26,6 +32,14 @@ {{ sighting.number if sighting.number else "" }} {{ sighting.gender_name }} {{ sighting.with_young_name }} + + {% if sighting_notes | length > 0 %} + + {% else %} + + {% endif %} + {% if edit_enabled %} diff --git a/src/naturerec_web/static/css/site.css b/src/naturerec_web/static/css/site.css index 7cd15f4..2494a80 100644 --- a/src/naturerec_web/static/css/site.css +++ b/src/naturerec_web/static/css/site.css @@ -128,4 +128,14 @@ div.message { .geocode { color: #286090; cursor: pointer; +} + +/* --- Icons --------------------------------------------------------------- */ + +.icon-blue { + color: #0c6efd; +} + +.icon-grey { + color: grey; } \ No newline at end of file diff --git a/tests/naturerec_model/data_exchange/test_life_list_export_helper.py b/tests/naturerec_model/data_exchange/test_life_list_export_helper.py index 0f5afda..1684d4e 100644 --- a/tests/naturerec_model/data_exchange/test_life_list_export_helper.py +++ b/tests/naturerec_model/data_exchange/test_life_list_export_helper.py @@ -16,7 +16,8 @@ def setUp(self) -> None: self._category = create_category("Birds") self._gull = create_species(self._category.id, "Black-Headed Gull") self._location = create_location(name="Radley Lakes", county="Oxfordshire", country="United Kingdom") - _ = create_sighting(self._location.id, self._gull.id, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False) + _ = create_sighting(self._location.id, self._gull.id, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False, + None) def test_can_export_life_list(self): # Export the sightings diff --git a/tests/naturerec_model/data_exchange/test_sightings_export_helper.py b/tests/naturerec_model/data_exchange/test_sightings_export_helper.py index 13d80a7..fc469a7 100644 --- a/tests/naturerec_model/data_exchange/test_sightings_export_helper.py +++ b/tests/naturerec_model/data_exchange/test_sightings_export_helper.py @@ -17,7 +17,8 @@ def setUp(self) -> None: self._gull = create_species(self._category.id, "Black-Headed Gull") self._cormorant = create_species(self._category.id, "Cormorant") self._location = create_location(name="Radley Lakes", county="Oxfordshire", country="United Kingdom") - _ = create_sighting(self._location.id, self._gull.id, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False) + _ = create_sighting(self._location.id, self._gull.id, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False, + None) def test_can_export_sightings(self): # Export the sightings @@ -34,7 +35,7 @@ def test_can_export_sightings(self): self.assertEqual(2, len(rows)) self.assertEqual(SightingsExportHelper.COLUMN_NAMES, rows[0]) - self.assertEqual(14, len(rows[1])) + self.assertEqual(15, len(rows[1])) self.assertEqual("Black-Headed Gull", rows[1][0]) self.assertEqual("Birds", rows[1][1]) self.assertEqual("", rows[1][2]) diff --git a/tests/naturerec_model/data_exchange/test_sightings_import_helper.py b/tests/naturerec_model/data_exchange/test_sightings_import_helper.py index 1e0b381..708be21 100644 --- a/tests/naturerec_model/data_exchange/test_sightings_import_helper.py +++ b/tests/naturerec_model/data_exchange/test_sightings_import_helper.py @@ -33,9 +33,9 @@ def _perform_valid_import(self): filename = os.path.join(get_data_path(), "valid_status_import.csv") TestSightingsImportHelper._create_test_file(filename, [ "Species,Category,Number,Gender,WithYoung,Date,Location,Address,City,County,Postcode,Country," - "Latitude,Longitude\n", + "Latitude,Longitude,Notes\n", "Robin,Birds,1,Unknown,No,01/02/2021,Abingdon,An Address,Abingdon,Oxfordshire,OX14,United Kingdom," - "51.6708,-1.2880\n" + "51.6708,-1.2880,\n" ]) # Import the sightings diff --git a/tests/naturerec_model/logic/test_reports.py b/tests/naturerec_model/logic/test_reports.py index 91ed1b4..274cf14 100644 --- a/tests/naturerec_model/logic/test_reports.py +++ b/tests/naturerec_model/logic/test_reports.py @@ -11,7 +11,8 @@ def setUp(self) -> None: self._category = create_category("Birds") self._species = create_species(self._category.id, "Black-Headed Gull") self._location = create_location(name="Radley Lakes", county="Oxfordshire", country="United Kingdom") - create_sighting(self._location.id, self._species.id, datetime.date(2021, 12, 14), 30, Gender.UNKNOWN, False) + create_sighting(self._location.id, self._species.id, datetime.date(2021, 12, 14), 30, Gender.UNKNOWN, False, + None) def test_can_get_location_species_report(self): report_df = location_species_report(datetime.date(2021, 12, 1), datetime.datetime.today(), self._location.id, diff --git a/tests/naturerec_model/logic/test_sightings.py b/tests/naturerec_model/logic/test_sightings.py index a800a6f..98c9b7e 100644 --- a/tests/naturerec_model/logic/test_sightings.py +++ b/tests/naturerec_model/logic/test_sightings.py @@ -13,14 +13,14 @@ def setUp(self) -> None: category = create_category("Birds") species = create_species(category.id, "Black-Headed Gull") location = create_location(name="Radley Lakes", county="Oxfordshire", country="United Kingdom") - create_sighting(location.id, species.id, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False) + create_sighting(location.id, species.id, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False, "Notes") @staticmethod def create_additional_sightings(): category_id = get_category("Birds").id species = create_species(category_id, "Blackbird") location = create_location(name="Brock Hill", city="Lyndhurst", county="Hampshire", country="United Kingdom") - create_sighting(location.id, species.id, datetime.date(2021, 12, 13), None, Gender.UNKNOWN, False) + create_sighting(location.id, species.id, datetime.date(2021, 12, 13), None, Gender.UNKNOWN, False, None) def test_can_create_sighting(self): with Session.begin() as session: @@ -32,13 +32,14 @@ def test_can_create_sighting(self): self.assertIsNone(sighting.number) self.assertEqual(Gender.UNKNOWN, sighting.gender) self.assertFalse(0, sighting.withYoung) + self.assertEqual("Notes", sighting.notes) def test_can_update_sighting_date(self): with Session.begin() as session: sighting = session.query(Sighting).one() update_sighting(sighting.id, sighting.location.id, sighting.species.id, datetime.date(2021, 12, 15), None, - Gender.UNKNOWN, False) + Gender.UNKNOWN, False, "Notes") updated = get_sighting(sighting.id) self.assertEqual("Birds", updated.species.category.name) @@ -48,6 +49,7 @@ def test_can_update_sighting_date(self): self.assertIsNone(updated.number) self.assertEqual(Gender.UNKNOWN, updated.gender) self.assertFalse(0, updated.withYoung) + self.assertEqual("Notes", updated.notes) def test_can_update_sighting_location(self): with Session.begin() as session: @@ -55,7 +57,7 @@ def test_can_update_sighting_location(self): location = create_location(name="Brock Hill", city="Lyndhurst", county="Hampshire", country="United Kingdom") update_sighting(sighting.id, location.id, sighting.species.id, datetime.date(2021, 12, 14), None, - Gender.UNKNOWN, False) + Gender.UNKNOWN, False, "Notes") updated = get_sighting(sighting.id) self.assertEqual("Birds", updated.species.category.name) @@ -65,6 +67,7 @@ def test_can_update_sighting_location(self): self.assertIsNone(updated.number) self.assertEqual(Gender.UNKNOWN, updated.gender) self.assertFalse(0, updated.withYoung) + self.assertEqual("Notes", updated.notes) def test_can_update_sighting_species(self): with Session.begin() as session: @@ -73,7 +76,7 @@ def test_can_update_sighting_species(self): category_id = get_category("Birds").id species = create_species(category_id, "Blackbird") update_sighting(sighting.id, sighting.location.id, species.id, datetime.date(2021, 12, 14), None, - Gender.UNKNOWN, False) + Gender.UNKNOWN, False, "Notes") updated = get_sighting(sighting.id) self.assertEqual("Birds", updated.species.category.name) @@ -83,13 +86,14 @@ def test_can_update_sighting_species(self): self.assertIsNone(updated.number) self.assertEqual(Gender.UNKNOWN, updated.gender) self.assertFalse(0, updated.withYoung) + self.assertEqual("Notes", updated.notes) def test_can_update_sighting_number(self): with Session.begin() as session: sighting = session.query(Sighting).one() update_sighting(sighting.id, sighting.location.id, sighting.species.id, datetime.date(2021, 12, 14), 10, - Gender.UNKNOWN, False) + Gender.UNKNOWN, False, "Notes") updated = get_sighting(sighting.id) self.assertEqual("Birds", updated.species.category.name) @@ -99,13 +103,14 @@ def test_can_update_sighting_number(self): self.assertEqual(10, updated.number) self.assertEqual(Gender.UNKNOWN, updated.gender) self.assertFalse(0, updated.withYoung) + self.assertEqual("Notes", updated.notes) def test_can_update_sighting_gender(self): with Session.begin() as session: sighting = session.query(Sighting).one() update_sighting(sighting.id, sighting.location.id, sighting.species.id, datetime.date(2021, 12, 14), None, - Gender.MALE, False) + Gender.MALE, False, "Notes") updated = get_sighting(sighting.id) self.assertEqual("Birds", updated.species.category.name) @@ -115,13 +120,14 @@ def test_can_update_sighting_gender(self): self.assertIsNone(updated.number) self.assertEqual(Gender.MALE, updated.gender) self.assertFalse(0, updated.withYoung) + self.assertEqual("Notes", updated.notes) def test_can_update_sighting_with_young(self): with Session.begin() as session: sighting = session.query(Sighting).one() update_sighting(sighting.id, sighting.location.id, sighting.species.id, datetime.date(2021, 12, 14), None, - Gender.UNKNOWN, True) + Gender.UNKNOWN, True, "Notes") updated = get_sighting(sighting.id) self.assertEqual("Birds", updated.species.category.name) @@ -131,17 +137,35 @@ def test_can_update_sighting_with_young(self): self.assertIsNone(updated.number) self.assertEqual(Gender.UNKNOWN, updated.gender) self.assertTrue(1, updated.withYoung) + self.assertEqual("Notes", updated.notes) + + def test_can_update_sighting_notes(self): + with Session.begin() as session: + sighting = session.query(Sighting).one() + + update_sighting(sighting.id, sighting.location.id, sighting.species.id, datetime.date(2021, 12, 14), None, + Gender.UNKNOWN, True, "Updated notes") + updated = get_sighting(sighting.id) + + self.assertEqual("Birds", updated.species.category.name) + self.assertEqual("Black-Headed Gull", updated.species.name) + self.assertEqual("Radley Lakes", updated.location.name) + self.assertEqual(datetime.date(2021, 12, 14), updated.sighting_date) + self.assertIsNone(updated.number) + self.assertEqual(Gender.UNKNOWN, updated.gender) + self.assertTrue(1, updated.withYoung) + self.assertEqual("Updated notes", updated.notes) def test_cannot_update_sighting_to_create_duplicate(self): with Session.begin() as session: sighting = session.query(Sighting).one() new_sighting = create_sighting(sighting.location.id, sighting.species.id, datetime.date(2021, 12, 15), None, - Gender.UNKNOWN, False) + Gender.UNKNOWN, False, None) with self.assertRaises(ValueError): _ = update_sighting(new_sighting.id, new_sighting.locationId, new_sighting.speciesId, - datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False) + datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False, None) def test_cannot_update_missing_sighting(self): with Session.begin() as session: @@ -149,7 +173,7 @@ def test_cannot_update_missing_sighting(self): with self.assertRaises(ValueError): _ = update_sighting(-1, sighting.locationId, sighting.speciesId, datetime.date(2021, 12, 15), None, - Gender.UNKNOWN, False) + Gender.UNKNOWN, False, None) def test_cannot_update_sighting_for_missing_location(self): with Session.begin() as session: @@ -157,7 +181,7 @@ def test_cannot_update_sighting_for_missing_location(self): with self.assertRaises(ValueError): _ = update_sighting(sighting.id, -1, sighting.species.id, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, - False) + False, None) def test_cannot_update_sighting_for_missing_species(self): with Session.begin() as session: @@ -165,7 +189,7 @@ def test_cannot_update_sighting_for_missing_species(self): with self.assertRaises(ValueError): _ = update_sighting(sighting.id, sighting.location.id, -1, datetime.date(2021, 12, 14), None, - Gender.UNKNOWN, False) + Gender.UNKNOWN, False, None) def test_cannot_update_sighting_with_invalid_number(self): with Session.begin() as session: @@ -173,7 +197,7 @@ def test_cannot_update_sighting_with_invalid_number(self): with self.assertRaises(ValueError): _ = update_sighting(sighting.id, sighting.location.id, sighting.species.id, datetime.date(2021, 12, 14), - -1, Gender.UNKNOWN, False) + -1, Gender.UNKNOWN, False, None) def test_cannot_update_sighting_with_invalid_gender(self): with Session.begin() as session: @@ -181,7 +205,7 @@ def test_cannot_update_sighting_with_invalid_gender(self): with self.assertRaises(ValueError): _ = update_sighting(sighting.id, sighting.location.id, sighting.species.id, datetime.date(2021, 12, 14), - 0, 10, False) + 0, 10, False, None) def test_cannot_update_sighting_with_invalid_with_young(self): with Session.begin() as session: @@ -189,7 +213,7 @@ def test_cannot_update_sighting_with_invalid_with_young(self): with self.assertRaises(ValueError): _ = update_sighting(sighting.id, sighting.location.id, sighting.species.id, datetime.date(2021, 12, 14), - 0, Gender.UNKNOWN, -1) + 0, Gender.UNKNOWN, -1, None) def test_can_get_sighting_by_id(self): with Session.begin() as session: diff --git a/tests/naturerec_model/model/test_sighting.py b/tests/naturerec_model/model/test_sighting.py index 139c3a9..a77958c 100644 --- a/tests/naturerec_model/model/test_sighting.py +++ b/tests/naturerec_model/model/test_sighting.py @@ -14,7 +14,8 @@ def setUp(self) -> None: self._gull = create_species(self._category.id, "Black-Headed Gull") self._cormorant = create_species(self._category.id, "Cormorant") self._location = create_location(name="Radley Lakes", county="Oxfordshire", country="United Kingdom") - _ = create_sighting(self._location.id, self._gull.id, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False) + _ = create_sighting(self._location.id, self._gull.id, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False, + "Notes") def test_can_create_sighting(self): with Session.begin() as session: @@ -29,10 +30,11 @@ def test_can_create_sighting(self): self.assertEqual("Unknown", sighting.gender_name) self.assertFalse(0, sighting.withYoung) self.assertEqual("No", sighting.with_young_name) + self.assertEqual("Notes", sighting.notes) def test_can_create_sighting_for_males(self): sighting_id = create_sighting(self._location.id, self._cormorant.id, datetime.date(2021, 12, 14), None, - Gender.MALE, False).id + Gender.MALE, False, None).id with Session.begin() as session: sighting = session.query(Sighting).get(sighting_id) self.assertEqual(Gender.MALE, sighting.gender) @@ -40,7 +42,7 @@ def test_can_create_sighting_for_males(self): def test_can_create_sighting_for_females(self): sighting_id = create_sighting(self._location.id, self._cormorant.id, datetime.date(2021, 12, 14), None, - Gender.FEMALE, False).id + Gender.FEMALE, False, None).id with Session.begin() as session: sighting = session.query(Sighting).get(sighting_id) self.assertEqual(Gender.FEMALE, sighting.gender) @@ -48,7 +50,7 @@ def test_can_create_sighting_for_females(self): def test_can_create_sighting_for_both_genders(self): sighting_id = create_sighting(self._location.id, self._cormorant.id, datetime.date(2021, 12, 14), None, - Gender.BOTH, False).id + Gender.BOTH, False, None).id with Session.begin() as session: sighting = session.query(Sighting).get(sighting_id) self.assertEqual(Gender.BOTH, sighting.gender) @@ -56,7 +58,7 @@ def test_can_create_sighting_for_both_genders(self): def test_can_create_sighting_with_young(self): sighting_id = create_sighting(self._location.id, self._cormorant.id, datetime.date(2021, 12, 14), None, - Gender.UNKNOWN, True).id + Gender.UNKNOWN, True, None).id with Session.begin() as session: sighting = session.query(Sighting).get(sighting_id) self.assertTrue(sighting.withYoung) @@ -65,38 +67,38 @@ def test_can_create_sighting_with_young(self): def test_cannot_create_sighting_for_invalid_gender(self): with self.assertRaises(ValueError): _ = create_sighting(self._location.id, self._cormorant.id, datetime.date(2021, 12, 14), None, - -1, False) + -1, False, None) def test_cannot_create_same_sighting_twice(self): with self.assertRaises(ValueError): _ = create_sighting(self._location.id, self._gull.id, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, - False) + False, None) def test_cannot_create_sighting_for_missing_location(self): with self.assertRaises(ValueError): - _ = create_sighting(-1, self._cormorant.id, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False) + _ = create_sighting(-1, self._cormorant.id, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False, None) def test_cannot_create_sighting_for_missing_species(self): with self.assertRaises(ValueError): - _ = create_sighting(self._location.id, -1, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False) + _ = create_sighting(self._location.id, -1, datetime.date(2021, 12, 14), None, Gender.UNKNOWN, False, None) def test_cannot_create_sighting_with_invalid_number(self): with self.assertRaises(ValueError): _ = create_sighting(self._location.id, self._gull.id, datetime.date(2021, 12, 15), -1, Gender.UNKNOWN, - False) + False, None) def test_cannot_create_sighting_with_invalid_gender(self): with self.assertRaises(ValueError): - _ = create_sighting(self._location.id, self._gull.id, datetime.date(2021, 12, 15), None, 10, False) + _ = create_sighting(self._location.id, self._gull.id, datetime.date(2021, 12, 15), None, 10, False, None) def test_cannot_create_sighting_with_invalid_with_young(self): with self.assertRaises(ValueError): - _ = create_sighting(self._location.id, self._gull.id, datetime.date(2021, 12, 15), None, 10, -1) + _ = create_sighting(self._location.id, self._gull.id, datetime.date(2021, 12, 15), None, 10, -1, None) def test_can_get_csv_columns(self): with Session.begin() as session: columns = session.query(Sighting).one().csv_columns - self.assertEqual(14, len(columns)) + self.assertEqual(15, len(columns)) self.assertEqual("Black-Headed Gull", columns[0]) self.assertEqual("Birds", columns[1]) self.assertIsNone(columns[2]) @@ -111,3 +113,4 @@ def test_can_get_csv_columns(self): self.assertEqual("United Kingdom", columns[11]) self.assertIsNone(columns[12]) self.assertIsNone(columns[13]) + self.assertEqual("Notes", columns[14])