Skip to content

Commit

Permalink
Address SQLAlchemy deprecation warnings (#1111)
Browse files Browse the repository at this point in the history
## Fixes issue
Part of #1054

## Description of Changes
Address warnings for for `RemovedIn20Warning` and `LegacyAPIWarning`
while using the [`SQLALCHEMY_WARN_20`
flag](https://docs.sqlalchemy.org/en/20/changelog/migration_14.html#sqlalchemy-2-0-deprecations-mode).
If you would like me to do any additional manual checks, etc. to verify
these changes, please don't hesitate to ask.

<details><summary>Unmodified warnings</summary>

```console
=============================================================================================== warnings summary ===============================================================================================
../../local/lib/python3.11/site-packages/flask_wtf/recaptcha/widgets.py:2: 18 warnings
  /usr/local/lib/python3.11/site-packages/flask_wtf/recaptcha/widgets.py:2: DeprecationWarning: 'flask.Markup' is deprecated and will be removed in Flask 2.4. Import 'markupsafe.Markup' instead.
    from flask import Markup

OpenOversight/tests/test_commands.py::test_add_department__success
OpenOversight/tests/test_database_cache.py::test_get_database_cache_entry
OpenOversight/tests/test_utils.py::test_department_filter
OpenOversight/tests/test_models.py::test_department_repr
OpenOversight/tests/test_alembic.py::test_alembic_has_single_head
OpenOversight/tests/routes/test_image_tagging.py::test_routes_ok[/labels]
OpenOversight/tests/test_email_client.py::test_smtp_email_provider_send_email
  /usr/src/app/OpenOversight/tests/conftest.py:678: RemovedIn20Warning: "Incident" object is being merged into a Session along the backref cascade path for relationship "Location.incidents"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    Incident(

OpenOversight/tests/test_commands.py::test_add_department__success
OpenOversight/tests/test_database_cache.py::test_get_database_cache_entry
OpenOversight/tests/test_utils.py::test_department_filter
OpenOversight/tests/test_models.py::test_department_repr
OpenOversight/tests/test_alembic.py::test_alembic_has_single_head
OpenOversight/tests/routes/test_image_tagging.py::test_routes_ok[/labels]
OpenOversight/tests/test_email_client.py::test_smtp_email_provider_send_email
  /usr/src/app/OpenOversight/tests/conftest.py:691: RemovedIn20Warning: "Incident" object is being merged into a Session along the backref cascade path for relationship "Location.incidents"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    Incident(

OpenOversight/tests/test_commands.py::test_add_department__success
OpenOversight/tests/test_database_cache.py::test_get_database_cache_entry
OpenOversight/tests/test_utils.py::test_department_filter
OpenOversight/tests/test_models.py::test_department_repr
OpenOversight/tests/test_alembic.py::test_alembic_has_single_head
OpenOversight/tests/routes/test_image_tagging.py::test_routes_ok[/labels]
OpenOversight/tests/test_email_client.py::test_smtp_email_provider_send_email
  /usr/src/app/OpenOversight/tests/conftest.py:704: RemovedIn20Warning: "Incident" object is being merged into a Session along the backref cascade path for relationship "Location.incidents"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    Incident(

OpenOversight/tests/test_commands.py::test_add_department__success
OpenOversight/tests/test_database_cache.py::test_get_database_cache_entry
OpenOversight/tests/test_utils.py::test_department_filter
OpenOversight/tests/test_models.py::test_department_repr
OpenOversight/tests/test_alembic.py::test_alembic_has_single_head
OpenOversight/tests/routes/test_image_tagging.py::test_routes_ok[/labels]
OpenOversight/tests/test_email_client.py::test_smtp_email_provider_send_email
  /usr/src/app/OpenOversight/tests/conftest.py:725: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    first_officer = Officer.query.get(1)

OpenOversight/tests/test_commands.py::test_add_department__success
OpenOversight/tests/test_database_cache.py::test_get_database_cache_entry
OpenOversight/tests/test_utils.py::test_department_filter
OpenOversight/tests/test_models.py::test_department_repr
OpenOversight/tests/test_alembic.py::test_alembic_has_single_head
OpenOversight/tests/routes/test_image_tagging.py::test_routes_ok[/labels]
OpenOversight/tests/test_email_client.py::test_smtp_email_provider_send_email
  /usr/src/app/OpenOversight/tests/conftest.py:740: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    first_officer = Officer.query.get(1)

OpenOversight/tests/test_commands.py::test_add_department__duplicate
OpenOversight/tests/test_models.py::test__uuid_uniqueness_constraint
OpenOversight/tests/routes/test_singular_redirects.py::test_redirect_add_salary
  /usr/src/app/OpenOversight/tests/conftest.py:325: SAWarning: transaction already deassociated from connection
    transaction.rollback()

OpenOversight/tests/test_commands.py::test_add_job_title__success
OpenOversight/tests/test_commands.py::test_add_job_title__different_departments
  /usr/src/app/OpenOversight/app/commands.py:645: RemovedIn20Warning: "Job" object is being merged into a Session along the backref cascade path for relationship "Department.jobs"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    job = Job(

OpenOversight/tests/test_utils.py::test_filters_do_not_exclude_officers_without_assignments
  /usr/src/app/OpenOversight/tests/test_utils.py:102: RemovedIn20Warning: "Officer" object is being merged into a Session along the backref cascade path for relationship "Department.officers"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    officer = Officer(

OpenOversight/tests/test_models.py::test_salary_repr
  /usr/src/app/OpenOversight/tests/test_models.py:170: SAWarning: Dialect sqlite+pysqlite does *not* support Decimal objects natively, and SQLAlchemy must convert from floating point - rounding errors and other issues may occur. Please consider storing Decimal numbers as strings or integers on this platform for lossless storage.
    salary = Salary.query.first()

OpenOversight/tests/test_commands.py::test_csv_import_new
  /usr/src/app/OpenOversight/tests/conftest.py:855: SAWarning: Dialect sqlite+pysqlite does *not* support Decimal objects natively, and SQLAlchemy must convert from floating point - rounding errors and other issues may occur. Please consider storing Decimal numbers as strings or integers on this platform for lossless storage.
    if len(list(officer.salaries)) > 0:

OpenOversight/tests/test_database_cache.py::test_documented_assignments
OpenOversight/tests/routes/test_image_tagging.py::test_admin_can_delete_tag
OpenOversight/tests/routes/test_descriptions.py::test_officer_descriptions_markdown
OpenOversight/tests/routes/test_notes.py::test_officer_notes_markdown
  /usr/local/lib/python3.11/site-packages/jinja2/environment.py:487: SAWarning: Dialect sqlite+pysqlite does *not* support Decimal objects natively, and SQLAlchemy must convert from floating point - rounding errors and other issues may occur. Please consider storing Decimal numbers as strings or integers on this platform for lossless storage.
    return getattr(obj, attribute)

OpenOversight/tests/test_database_cache.py: 1 warning
OpenOversight/tests/routes/test_incidents.py: 9 warnings
OpenOversight/tests/routes/test_officer_and_department.py: 1 warning
  /usr/src/app/OpenOversight/app/utils/forms.py:203: RemovedIn20Warning: "Incident" object is being merged into a Session along the backref cascade path for relationship "Location.incidents"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    return Incident(

OpenOversight/tests/test_database_cache.py: 2 warnings
OpenOversight/tests/routes/test_descriptions.py: 29 warnings
OpenOversight/tests/routes/test_incidents.py: 34 warnings
OpenOversight/tests/routes/test_notes.py: 29 warnings
OpenOversight/tests/routes/test_singular_redirects.py: 21 warnings
OpenOversight/tests/routes/test_officer_and_department.py: 52 warnings
  /usr/local/lib/python3.11/site-packages/flask_sqlalchemy/query.py:30: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    rv = self.get(ident)

OpenOversight/tests/test_database_cache.py: 1 warning
OpenOversight/tests/routes/test_officer_and_department.py: 11 warnings
  /usr/src/app/OpenOversight/app/utils/forms.py:78: RemovedIn20Warning: "Assignment" object is being merged into a Session along the backref cascade path for relationship "Officer.assignments"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    assignment = Assignment(

OpenOversight/tests/routes/test_image_tagging.py::test_ac_cannot_delete_tag_not_in_their_dept
  /usr/src/app/OpenOversight/tests/routes/test_image_tagging.py:126: RemovedIn20Warning: The ``aliased`` and ``from_joinpoint`` keyword arguments to Query.join() are deprecated and will be removed in SQLAlchemy 2.0. (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    Face.query.join(Face.officer, aliased=True)

OpenOversight/tests/routes/test_image_tagging.py::test_user_is_redirected_to_correct_department_after_tagging
  /usr/src/app/OpenOversight/tests/routes/test_image_tagging.py:285: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    department = Department.query.get(department_id)

OpenOversight/tests/test_commands.py::test_csv_new_salary
  /usr/src/app/OpenOversight/tests/test_commands.py:463: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '123456.78' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.
    df.loc[0, "salary"] = "123456.78"

OpenOversight/tests/test_commands.py::test_bulk_add_officers__success
  /usr/src/app/OpenOversight/tests/test_commands.py:511: RemovedIn20Warning: "Assignment" object is being merged into a Session along the backref cascade path for relationship "Officer.assignments"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    assignment = Assignment(base_officer=first_officer, job_id=job.id)

OpenOversight/tests/test_commands.py::test_bulk_add_officers__success
  /usr/src/app/OpenOversight/tests/test_commands.py:519: RemovedIn20Warning: "Assignment" object is being merged into a Session along the backref cascade path for relationship "Officer.assignments"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    assignment = Assignment(base_officer=different_officer, job=job, created_by=user.id)

OpenOversight/tests/routes/test_incidents.py::test_admins_can_edit_incident_date_and_address
  /usr/src/app/OpenOversight/tests/routes/test_incidents.py:253: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    updated = Incident.query.get(inc_id)

OpenOversight/tests/routes/test_descriptions.py::test_admins_can_delete_descriptions
  /usr/src/app/OpenOversight/tests/routes/test_descriptions.py:293: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    deleted = Description.query.get(description_id)

OpenOversight/tests/routes/test_image_tagging.py::test_ac_cannot_set_featured_tag_not_in_their_dept
  /usr/src/app/OpenOversight/tests/routes/test_image_tagging.py:326: RemovedIn20Warning: The ``aliased`` and ``from_joinpoint`` keyword arguments to Query.join() are deprecated and will be removed in SQLAlchemy 2.0. (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    Face.query.join(Face.officer, aliased=True)

OpenOversight/tests/test_commands.py::test_advanced_csv_import__success
  /usr/src/app/OpenOversight/tests/test_commands.py:889: RemovedIn20Warning: "Incident" object is being merged into a Session along the backref cascade path for relationship "Officer.incidents"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    incident.officers = [officer]

OpenOversight/tests/test_commands.py::test_advanced_csv_import__success
OpenOversight/tests/test_commands.py::test_advanced_csv_import__success
OpenOversight/tests/test_commands.py::test_advanced_csv_import__force_create
  /usr/src/app/OpenOversight/app/models/database_imports.py:308: RemovedIn20Warning: "Incident" object is being merged into a Session along the backref cascade path for relationship "Officer.incidents"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    incident.officers = data.get("officers", [])

OpenOversight/tests/test_commands.py::test_advanced_csv_import__success
  /usr/src/app/OpenOversight/tests/test_commands.py:1012: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    incident3 = Incident.query.get(123456)

OpenOversight/tests/test_commands.py::test_advanced_csv_import__success
  /usr/src/app/OpenOversight/tests/test_commands.py:1035: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    updated_link = Link.query.get(55051)

OpenOversight/tests/routes/test_descriptions.py::test_acs_can_delete_their_descriptions_in_their_department
  /usr/src/app/OpenOversight/tests/routes/test_descriptions.py:322: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    deleted = Description.query.get(description_id)

OpenOversight/tests/test_commands.py::test_advanced_csv_import__force_create
  /usr/src/app/OpenOversight/app/csv_imports.py:560: RemovedIn20Warning: Using plain strings to indicate SQL statements without using the text() construct is  deprecated and will be removed in version 2.0.  Ensure plain SQL statements are passed using the text() construct. (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    db.session.execute(raw_sql)

OpenOversight/tests/test_commands.py::test_advanced_csv_import__force_create
  /usr/src/app/OpenOversight/tests/test_commands.py:1160: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    cop1 = Officer.query.get(99001)

OpenOversight/tests/test_commands.py::test_advanced_csv_import__force_create
  /usr/src/app/OpenOversight/tests/test_commands.py:1163: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    cop2 = Officer.query.get(99002)

OpenOversight/tests/test_commands.py::test_advanced_csv_import__force_create
  /usr/src/app/OpenOversight/tests/test_commands.py:1165: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    assert cop2.assignments[0] == Assignment.query.get(98001)

OpenOversight/tests/test_commands.py::test_advanced_csv_import__force_create
  /usr/src/app/OpenOversight/tests/test_commands.py:1167: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    cop3 = Officer.query.get(99003)

OpenOversight/tests/test_commands.py::test_advanced_csv_import__force_create
  /usr/src/app/OpenOversight/tests/test_commands.py:1169: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    assert cop3.salaries[0] == Salary.query.get(77001)

OpenOversight/tests/test_commands.py::test_advanced_csv_import__force_create
  /usr/src/app/OpenOversight/tests/test_commands.py:1171: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    incident = Incident.query.get(66001)

OpenOversight/tests/test_commands.py::test_advanced_csv_import__force_create
  /usr/src/app/OpenOversight/tests/test_commands.py:1176: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    link = Link.query.get(55001)

OpenOversight/tests/test_commands.py::test_advanced_csv_import__overwrite_assignments
  /usr/src/app/OpenOversight/tests/test_commands.py:1279: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    cop1 = Officer.query.get(cop1_id)

OpenOversight/tests/test_commands.py::test_advanced_csv_import__overwrite_assignments
  /usr/src/app/OpenOversight/tests/test_commands.py:1283: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    cop2 = Officer.query.get(cop2_id)

OpenOversight/tests/test_commands.py::test_advanced_csv_import__overwrite_assignments
  /usr/src/app/OpenOversight/tests/test_commands.py:1285: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    assert cop2.assignments[0] == Assignment.query.get(a2_id)

OpenOversight/tests/routes/test_descriptions.py::test_acs_cannot_delete_descriptions_not_in_their_department
  /usr/src/app/OpenOversight/tests/routes/test_descriptions.py:354: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    not_deleted = Description.query.get(description_id)

OpenOversight/tests/routes/test_incidents.py: 12 warnings
  /usr/src/app/OpenOversight/app/main/forms.py:505: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    officer = Officer.query.get(officer_id)

OpenOversight/tests/routes/test_notes.py::test_admins_can_delete_notes
  /usr/src/app/OpenOversight/tests/routes/test_notes.py:263: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    deleted = Note.query.get(note.id)

OpenOversight/tests/routes/test_notes.py::test_acs_can_delete_their_notes_in_their_department
  /usr/src/app/OpenOversight/tests/routes/test_notes.py:288: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    deleted = Note.query.get(note.id)

OpenOversight/tests/routes/test_notes.py::test_acs_cannot_delete_notes_not_in_their_department
  /usr/src/app/OpenOversight/tests/routes/test_notes.py:317: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    not_deleted = Note.query.get(note.id)

OpenOversight/tests/routes/test_incidents.py::test_admins_can_delete_incidents
  /usr/src/app/OpenOversight/tests/routes/test_incidents.py:683: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    deleted = Incident.query.get(inc_id)

OpenOversight/tests/routes/test_incidents.py::test_acs_can_delete_incidents_in_their_department
  /usr/src/app/OpenOversight/tests/routes/test_incidents.py:697: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    deleted = Incident.query.get(inc_id)

OpenOversight/tests/routes/test_incidents.py::test_acs_cannot_delete_incidents_not_in_their_department
  /usr/src/app/OpenOversight/tests/routes/test_incidents.py:713: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    not_deleted = Incident.query.get(inc_id)

OpenOversight/tests/routes/test_user_api.py: 21 warnings
  /usr/src/app/OpenOversight/app/auth/views.py:295: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    user = User.query.get(user_id)

OpenOversight/tests/routes/test_user_api.py::test_admin_can_delete_user
OpenOversight/tests/routes/test_user_api.py::test_admin_can_delete_user
OpenOversight/tests/routes/test_user_api.py::test_admin_cannot_delete_other_admin
  /usr/src/app/OpenOversight/app/auth/views.py:342: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    user = User.query.get(user_id)

OpenOversight/tests/routes/test_user_api.py::test_admin_can_delete_user
  /usr/src/app/OpenOversight/tests/routes/test_user_api.py:137: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    assert not User.query.get(user.id)

OpenOversight/tests/routes/test_user_api.py::test_admin_cannot_delete_other_admin
  /usr/src/app/OpenOversight/tests/routes/test_user_api.py:153: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    assert User.query.get(user.id) is not None

OpenOversight/tests/routes/test_user_api.py::test_admin_can_disable_user
  /usr/src/app/OpenOversight/tests/routes/test_user_api.py:178: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    user = User.query.get(user.id)

OpenOversight/tests/routes/test_user_api.py::test_admin_cannot_disable_self
  /usr/src/app/OpenOversight/tests/routes/test_user_api.py:201: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    user = User.query.get(user.id)

OpenOversight/tests/routes/test_user_api.py::test_admin_can_enable_user
  /usr/src/app/OpenOversight/tests/routes/test_user_api.py:213: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    user = User.query.get(user.id)

OpenOversight/tests/routes/test_user_api.py::test_admin_can_enable_user
  /usr/src/app/OpenOversight/tests/routes/test_user_api.py:229: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    user = User.query.get(user.id)

OpenOversight/tests/routes/test_user_api.py::test_admin_can_approve_user
  /usr/src/app/OpenOversight/tests/routes/test_user_api.py:296: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    user = User.query.get(user.id)

OpenOversight/tests/routes/test_user_api.py::test_admin_can_approve_user
  /usr/src/app/OpenOversight/tests/routes/test_user_api.py:312: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    user = User.query.get(user.id)

OpenOversight/tests/routes/test_user_api.py::test_admin_approval_sends_confirmation_email[False-False-True-True]
OpenOversight/tests/routes/test_user_api.py::test_admin_approval_sends_confirmation_email[False-False-False-False]
OpenOversight/tests/routes/test_user_api.py::test_admin_approval_sends_confirmation_email[True-False-True-False]
OpenOversight/tests/routes/test_user_api.py::test_admin_approval_sends_confirmation_email[False-True-True-False]
  /usr/src/app/OpenOversight/tests/routes/test_user_api.py:349: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    user = User.query.get(user.id)

OpenOversight/tests/routes/test_user_api.py::test_admin_approval_sends_confirmation_email[False-False-True-True]
OpenOversight/tests/routes/test_user_api.py::test_admin_approval_sends_confirmation_email[False-False-False-False]
OpenOversight/tests/routes/test_user_api.py::test_admin_approval_sends_confirmation_email[True-False-True-False]
OpenOversight/tests/routes/test_user_api.py::test_admin_approval_sends_confirmation_email[False-True-True-False]
  /usr/src/app/OpenOversight/tests/routes/test_user_api.py:366: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    user = User.query.get(user.id)

OpenOversight/tests/routes/test_officer_and_department.py::test_admin_can_add_new_officer
  /usr/src/app/OpenOversight/app/utils/forms.py:97: RemovedIn20Warning: "Note" object is being merged into a Session along the backref cascade path for relationship "Officer.notes"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    new_note = Note(

OpenOversight/tests/routes/test_officer_and_department.py::test_admin_can_add_new_officer
  /usr/src/app/OpenOversight/app/utils/forms.py:108: RemovedIn20Warning: "Description" object is being merged into a Session along the backref cascade path for relationship "Officer.descriptions"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    new_description = Description(

OpenOversight/tests/routes/test_officer_and_department.py::test_admin_can_add_new_officer
  /usr/src/app/OpenOversight/app/utils/forms.py:119: RemovedIn20Warning: "Salary" object is being merged into a Session along the backref cascade path for relationship "Officer.salaries"; in SQLAlchemy 2.0, this reverse cascade will not take place.  Set cascade_backrefs to False in either the relationship() or backref() function for the 2.0 behavior; or to set globally for the whole Session, set the future=True flag (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    new_salary = Salary(

OpenOversight/tests/routes/test_officer_and_department.py: 109 warnings
  /usr/src/app/OpenOversight/tests/routes/test_officer_and_department.py:1777: LegacyAPIWarning: The Query.get() method is considered legacy as of the 1.x series of SQLAlchemy and becomes a legacy construct in 2.0. The method is now available as Session.get() (deprecated since: 1.4) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    assert (

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html

---------- coverage: platform linux, python 3.11.9-final-0 -----------
```
</details>

## Tests and Linting
 - [x] This branch is up-to-date with the `develop` branch.
 - [x] `pytest` passes on my local development environment.
 - [x] `pre-commit` passes on my local development environment.
  • Loading branch information
michplunkett authored Jul 19, 2024
1 parent 727ed97 commit 2b22c1c
Show file tree
Hide file tree
Showing 16 changed files with 117 additions and 76 deletions.
4 changes: 2 additions & 2 deletions OpenOversight/app/auth/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ def get_users():
@auth.route("/users/<int:user_id>", methods=[HTTPMethod.GET, HTTPMethod.POST])
@admin_required
def edit_user(user_id):
user = User.query.get(user_id)
user = db.session.get(User, user_id)
if not user:
return render_template("404.html"), HTTPStatus.NOT_FOUND

Expand Down Expand Up @@ -339,7 +339,7 @@ def edit_user(user_id):
@auth.route("/users/<int:user_id>/delete", methods=[HTTPMethod.GET, HTTPMethod.POST])
@admin_required
def delete_user(user_id):
user = User.query.get(user_id)
user = db.session.get(User, user_id)
if not user or user.is_administrator:
return render_template("403.html"), HTTPStatus.FORBIDDEN
if request.method == HTTPMethod.POST:
Expand Down
3 changes: 2 additions & 1 deletion OpenOversight/app/csv_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from contextlib import contextmanager
from typing import Dict, Optional

from sqlalchemy import sql
from sqlalchemy.exc import SQLAlchemyError

from OpenOversight.app.models.database import (
Expand Down Expand Up @@ -557,7 +558,7 @@ def import_csv_files(
select setval('incidents_id_seq', (select max(id) from incidents));
"""
try:
db.session.execute(raw_sql)
db.session.execute(sql.text(raw_sql))
print("Updated sequences.")
except SQLAlchemyError:
print("Failed to update sequences")
6 changes: 3 additions & 3 deletions OpenOversight/app/main/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from wtforms_sqlalchemy.fields import QuerySelectField

from OpenOversight.app.formfields import TimeField
from OpenOversight.app.models.database import Officer
from OpenOversight.app.models.database import Officer, db
from OpenOversight.app.utils.choices import (
AGE_CHOICES,
DEPARTMENT_STATE_CHOICES,
Expand Down Expand Up @@ -498,11 +498,11 @@ def process_data(self, value):
def validate_oo_id(self, oo_id):
if oo_id.data and isinstance(oo_id.data, str):
if oo_id.data.isnumeric():
officer = Officer.query.get(oo_id.data)
officer = db.session.get(Officer, oo_id.data)
else:
try:
officer_id = oo_id.data.split('value="')[1][:-2]
officer = Officer.query.get(officer_id)
officer = db.session.get(Officer, officer_id)

# Sometimes we get a string in field.data with py.test, this parses it
except IndexError:
Expand Down
6 changes: 3 additions & 3 deletions OpenOversight/app/main/model_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def get(self, obj_id):
url=f"main.{self.model_name}_api",
)
else:
obj = self.model.query.get_or_404(obj_id)
obj = db.get_or_404(self.model, obj_id)
return render_template(
f"{self.model_name}_detail.html",
obj=obj,
Expand Down Expand Up @@ -111,7 +111,7 @@ def new(self, form=None):
@login_required
@ac_or_admin_required
def edit(self, obj_id, form=None):
obj = self.model.query.get_or_404(obj_id)
obj = db.get_or_404(self.model, obj_id)
if self.department_check:
if (
not current_user.is_administrator
Expand Down Expand Up @@ -158,7 +158,7 @@ def edit(self, obj_id, form=None):
@login_required
@ac_or_admin_required
def delete(self, obj_id):
obj = self.model.query.get_or_404(obj_id)
obj = db.get_or_404(self.model, obj_id)
if self.department_check:
if (
not current_user.is_administrator
Expand Down
12 changes: 6 additions & 6 deletions OpenOversight/app/main/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ def redirect_edit_department(department_id: int):
@login_required
@admin_required
def edit_department(department_id: int):
department = Department.query.get_or_404(department_id)
department = db.get_or_404(Department, department_id)
previous_name = department.name
form = EditDepartmentForm(obj=department)
original_ranks = department.jobs
Expand Down Expand Up @@ -1831,7 +1831,7 @@ def redirect_submit_officer_images(officer_id: int):
@login_required
@ac_or_admin_required
def submit_officer_images(officer_id: int):
officer = Officer.query.get_or_404(officer_id)
officer = db.get_or_404(Officer, officer_id)
return render_template("submit_officer_image.html", officer=officer)


Expand Down Expand Up @@ -1953,7 +1953,7 @@ def get(self, obj_id: int):

dept = None
if department_id := request.args.get("department_id"):
dept = Department.query.get_or_404(department_id)
dept = db.get_or_404(Department, department_id)
form.department_id.data = department_id
incidents = incidents.filter_by(department_id=department_id)

Expand Down Expand Up @@ -2141,7 +2141,7 @@ def get_edit_form(self, obj: TextForm):

def dispatch_request(self, *args, **kwargs):
if "officer_id" in kwargs:
officer = Officer.query.get_or_404(kwargs["officer_id"])
officer = db.get_or_404(Officer, kwargs["officer_id"])
self.officer_id = kwargs.pop("officer_id")
self.department_id = officer.department_id
return super(TextApi, self).dispatch_request(*args, **kwargs)
Expand Down Expand Up @@ -2392,7 +2392,7 @@ def new(self, form: FlaskForm = None):
@login_required
@ac_or_admin_required
def delete(self, obj_id: int):
obj = self.model.query.get_or_404(obj_id)
obj = db.get_or_404(self.model, obj_id)
if (
not current_user.is_administrator
and current_user.ac_department_id != self.get_department_id(obj)
Expand Down Expand Up @@ -2435,7 +2435,7 @@ def get_department_id(self, obj):

def dispatch_request(self, *args, **kwargs):
if "officer_id" in kwargs:
officer = Officer.query.get_or_404(kwargs["officer_id"])
officer = db.get_or_404(Officer, kwargs["officer_id"])
self.officer_id = kwargs.pop("officer_id")
self.department_id = officer.department_id
return super(OfficerLinkApi, self).dispatch_request(*args, **kwargs)
Expand Down
73 changes: 55 additions & 18 deletions OpenOversight/app/models/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ class Job(BaseModel, TrackUpdates):
department_id = db.Column(
db.Integer, db.ForeignKey("departments.id", name="jobs_department_id_fkey")
)
department = db.relationship("Department", backref="jobs")
department = db.relationship(
"Department", backref=db.backref("jobs", cascade_backrefs=False)
)

__table_args__ = (
UniqueConstraint(
Expand Down Expand Up @@ -232,27 +234,45 @@ class Officer(BaseModel, TrackUpdates):
gender = db.Column(db.String(5), index=True, unique=False, nullable=True)
employment_date = db.Column(db.Date, index=True, unique=False, nullable=True)
birth_year = db.Column(db.Integer, index=True, unique=False, nullable=True)
assignments = db.relationship("Assignment", back_populates="base_officer")
face = db.relationship("Face", backref="officer")
assignments = db.relationship(
"Assignment", back_populates="base_officer", cascade_backrefs=False
)
face = db.relationship(
"Face", backref=db.backref("officer", cascade_backrefs=False)
)
department_id = db.Column(
db.Integer, db.ForeignKey("departments.id", name="officers_department_id_fkey")
)
department = db.relationship("Department", backref="officers")
department = db.relationship(
"Department", backref=db.backref("officers", cascade_backrefs=False)
)
unique_internal_identifier = db.Column(
db.String(50), index=True, unique=True, nullable=True
)

links = db.relationship(
"Link", secondary=officer_links, backref=db.backref("officers", lazy=True)
"Link",
secondary=officer_links,
backref=db.backref("officers", lazy=True, cascade_backrefs=False),
lazy=True,
)
notes = db.relationship(
"Note", back_populates="officer", order_by="Note.created_at"
"Note",
back_populates="officer",
cascade_backrefs=False,
order_by="Note.created_at",
)
descriptions = db.relationship(
"Description", back_populates="officer", order_by="Description.created_at"
"Description",
back_populates="officer",
cascade_backrefs=False,
order_by="Description.created_at",
)
salaries = db.relationship(
"Salary", back_populates="officer", order_by="Salary.year.desc()"
"Salary",
back_populates="officer",
cascade_backrefs=False,
order_by="Salary.year.desc()",
)

__table_args__ = (
Expand Down Expand Up @@ -407,7 +427,9 @@ class Unit(BaseModel, TrackUpdates):
db.ForeignKey("departments.id", name="unit_types_department_id_fkey"),
)
department = db.relationship(
"Department", backref="unit_types", order_by="Unit.description.asc()"
"Department",
backref=db.backref("unit_types", cascade_backrefs=False),
order_by="Unit.description.asc()",
)

def __repr__(self):
Expand Down Expand Up @@ -445,9 +467,16 @@ class Face(BaseModel, TrackUpdates):
face_position_y = db.Column(db.Integer, unique=False)
face_width = db.Column(db.Integer, unique=False)
face_height = db.Column(db.Integer, unique=False)
image = db.relationship("Image", backref="faces", foreign_keys=[img_id])
image = db.relationship(
"Image",
backref=db.backref("faces", cascade_backrefs=False),
foreign_keys=[img_id],
)
original_image = db.relationship(
"Image", backref="tags", foreign_keys=[original_image_id], lazy=True
"Image",
backref=db.backref("tags", cascade_backrefs=False),
foreign_keys=[original_image_id],
lazy=True,
)
featured = db.Column(
db.Boolean, nullable=False, default=False, server_default="false"
Expand Down Expand Up @@ -478,7 +507,9 @@ class Image(BaseModel, TrackUpdates):
db.Integer,
db.ForeignKey("departments.id", name="raw_images_department_id_fkey"),
)
department = db.relationship("Department", backref="raw_images")
department = db.relationship(
"Department", backref=db.backref("raw_images", cascade_backrefs=False)
)

def __repr__(self):
return f"<Image ID {self.id}: {self.filepath}>"
Expand Down Expand Up @@ -641,29 +672,33 @@ class Incident(BaseModel, TrackUpdates):
address_id = db.Column(
db.Integer, db.ForeignKey("locations.id", name="incidents_address_id_fkey")
)
address = db.relationship("Location", backref="incidents")
address = db.relationship(
"Location", backref=db.backref("incidents", cascade_backrefs=False)
)
license_plates = db.relationship(
"LicensePlate",
secondary=incident_license_plates,
lazy="subquery",
backref=db.backref("incidents", lazy=True),
backref=db.backref("incidents", cascade_backrefs=False, lazy=True),
)
links = db.relationship(
"Link",
secondary=incident_links,
lazy="subquery",
backref=db.backref("incidents", lazy=True),
backref=db.backref("incidents", cascade_backrefs=False, lazy=True),
)
officers = db.relationship(
"Officer",
secondary=officer_incidents,
lazy="subquery",
backref=db.backref("incidents"),
backref=db.backref("incidents", cascade_backrefs=False),
)
department_id = db.Column(
db.Integer, db.ForeignKey("departments.id", name="incidents_department_id_fkey")
)
department = db.relationship("Department", backref="incidents", lazy=True)
department = db.relationship(
"Department", backref=db.backref("incidents", cascade_backrefs=False), lazy=True
)


class User(UserMixin, BaseModel):
Expand All @@ -690,7 +725,9 @@ class User(UserMixin, BaseModel):
db.Integer, db.ForeignKey("departments.id", name="users_ac_department_id_fkey")
)
ac_department = db.relationship(
"Department", backref="coordinators", foreign_keys=[ac_department_id]
"Department",
backref=db.backref("coordinators", cascade_backrefs=False),
foreign_keys=[ac_department_id],
)
is_administrator = db.Column(db.Boolean, default=False)
is_disabled = db.Column(db.Boolean, default=False)
Expand Down
4 changes: 2 additions & 2 deletions OpenOversight/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ def add_mockdata(session):
users_that_can_create_notes = [test_admin, test_area_coordinator]

# for testing routes
first_officer = Officer.query.get(1)
first_officer = session.get(Officer, 1)
note = build_note(
first_officer, test_admin, "### A markdown note\nA **test** note!"
)
Expand All @@ -737,7 +737,7 @@ def add_mockdata(session):
users_that_can_create_descriptions = [test_admin, test_area_coordinator]

# for testing routes
first_officer = Officer.query.get(1)
first_officer = session.get(Officer, 1)
description = build_description(
first_officer, test_admin, "### A markdown description\nA **test** description!"
)
Expand Down
6 changes: 3 additions & 3 deletions OpenOversight/tests/routes/test_descriptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ def test_admins_can_delete_descriptions(mockdata, client, session):
follow_redirects=True,
)
assert rv.status_code == HTTPStatus.OK
deleted = Description.query.get(description_id)
deleted = session.get(Description, description_id)
assert deleted is None


Expand Down Expand Up @@ -319,7 +319,7 @@ def test_acs_can_delete_their_descriptions_in_their_department(
follow_redirects=True,
)
assert rv.status_code == HTTPStatus.OK
deleted = Description.query.get(description_id)
deleted = session.get(Description, description_id)
assert deleted is None


Expand Down Expand Up @@ -351,7 +351,7 @@ def test_acs_cannot_delete_descriptions_not_in_their_department(
)

assert rv.status_code == HTTPStatus.FORBIDDEN
not_deleted = Description.query.get(description_id)
not_deleted = session.get(Description, description_id)
assert not_deleted is not None


Expand Down
6 changes: 3 additions & 3 deletions OpenOversight/tests/routes/test_image_tagging.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def test_ac_cannot_delete_tag_not_in_their_dept(mockdata, client, session):
login_ac(client)

tag = (
Face.query.join(Face.officer, aliased=True)
Face.query.join(Face.officer)
.except_(Face.query.filter(Face.officer.has(department_id=AC_DEPT)))
.first()
)
Expand Down Expand Up @@ -282,7 +282,7 @@ def test_user_is_redirected_to_correct_department_after_tagging(
),
follow_redirects=True,
)
department = Department.query.get(department_id)
department = session.get(Department, department_id)

assert rv.status_code == HTTPStatus.OK
assert department.name in rv.data.decode(ENCODING_UTF_8)
Expand Down Expand Up @@ -323,7 +323,7 @@ def test_ac_cannot_set_featured_tag_not_in_their_dept(mockdata, client, session)
login_ac(client)

tag = (
Face.query.join(Face.officer, aliased=True)
Face.query.join(Face.officer)
.except_(Face.query.filter(Face.officer.has(department_id=AC_DEPT)))
.first()
)
Expand Down
Loading

0 comments on commit 2b22c1c

Please sign in to comment.