Compare commits

..

39 Commits

Author SHA1 Message Date
dependabot[bot]
dac09809f5 Bump marshmallow from 3.26.1 to 4.0.0
Bumps [marshmallow](https://github.com/marshmallow-code/marshmallow) from 3.26.1 to 4.0.0.
- [Changelog](https://github.com/marshmallow-code/marshmallow/blob/dev/CHANGELOG.rst)
- [Commits](https://github.com/marshmallow-code/marshmallow/compare/3.26.1...4.0.0)

---
updated-dependencies:
- dependency-name: marshmallow
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-24 15:48:13 +00:00
Andrew Shumway
9f0b6b0ca1 Merge pull request #1664 from GSA/dependabot/pip/packaging-25.0
Bump packaging from 24.2 to 25.0
2025-04-24 09:46:03 -06:00
dependabot[bot]
7dd1751556 Bump packaging from 24.2 to 25.0
Bumps [packaging](https://github.com/pypa/packaging) from 24.2 to 25.0.
- [Release notes](https://github.com/pypa/packaging/releases)
- [Changelog](https://github.com/pypa/packaging/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pypa/packaging/compare/24.2...25.0)

---
updated-dependencies:
- dependency-name: packaging
  dependency-version: '25.0'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-24 15:25:37 +00:00
Andrew Shumway
3ae7749d0b Merge pull request #1663 from GSA/dependabot/pip/python-json-logger-3.3.0
Bump python-json-logger from 2.0.7 to 3.3.0
2025-04-24 09:23:24 -06:00
dependabot[bot]
f6cc4afab7 Bump python-json-logger from 2.0.7 to 3.3.0
Bumps [python-json-logger](https://github.com/nhairs/python-json-logger) from 2.0.7 to 3.3.0.
- [Release notes](https://github.com/nhairs/python-json-logger/releases)
- [Changelog](https://github.com/nhairs/python-json-logger/blob/main/docs/changelog.md)
- [Commits](https://github.com/nhairs/python-json-logger/compare/v2.0.7...v3.3.0)

---
updated-dependencies:
- dependency-name: python-json-logger
  dependency-version: 3.3.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-24 15:11:34 +00:00
Andrew Shumway
6325849855 Merge pull request #1662 from GSA/dependabot/pip/flask-migrate-4.1.0
Bump flask-migrate from 4.0.7 to 4.1.0
2025-04-24 09:09:24 -06:00
dependabot[bot]
b564a8800e Bump flask-migrate from 4.0.7 to 4.1.0
Bumps [flask-migrate](https://github.com/miguelgrinberg/flask-migrate) from 4.0.7 to 4.1.0.
- [Release notes](https://github.com/miguelgrinberg/flask-migrate/releases)
- [Changelog](https://github.com/miguelgrinberg/Flask-Migrate/blob/main/CHANGES.md)
- [Commits](https://github.com/miguelgrinberg/flask-migrate/compare/v4.0.7...v4.1.0)

---
updated-dependencies:
- dependency-name: flask-migrate
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-23 22:08:21 +00:00
Andrew Shumway
43247e81bb Merge pull request #1657 from GSA/dependabot/pip/click-8.1.8
Bump click from 8.1.7 to 8.1.8
2025-04-23 16:06:10 -06:00
dependabot[bot]
7f2325ea5e Bump click from 8.1.7 to 8.1.8
Bumps [click](https://github.com/pallets/click) from 8.1.7 to 8.1.8.
- [Release notes](https://github.com/pallets/click/releases)
- [Changelog](https://github.com/pallets/click/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/click/compare/8.1.7...8.1.8)

---
updated-dependencies:
- dependency-name: click
  dependency-version: 8.1.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-23 21:55:43 +00:00
Andrew Shumway
bcd18ac936 Merge pull request #1658 from GSA/dependabot/pip/moto-5.1.4
Bump moto from 5.1.0 to 5.1.4
2025-04-23 15:53:36 -06:00
dependabot[bot]
7fc65dd4f5 Bump moto from 5.1.0 to 5.1.4
Bumps [moto](https://github.com/getmoto/moto) from 5.1.0 to 5.1.4.
- [Release notes](https://github.com/getmoto/moto/releases)
- [Changelog](https://github.com/getmoto/moto/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getmoto/moto/compare/5.1.0...5.1.4)

---
updated-dependencies:
- dependency-name: moto
  dependency-version: 5.1.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-23 21:39:23 +00:00
Andrew Shumway
276446c57e Merge pull request #1659 from GSA/dependabot/pip/numpy-2.2.5
Bump numpy from 2.2.4 to 2.2.5
2025-04-23 15:37:08 -06:00
dependabot[bot]
bc26231164 Bump numpy from 2.2.4 to 2.2.5
Bumps [numpy](https://github.com/numpy/numpy) from 2.2.4 to 2.2.5.
- [Release notes](https://github.com/numpy/numpy/releases)
- [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst)
- [Commits](https://github.com/numpy/numpy/compare/v2.2.4...v2.2.5)

---
updated-dependencies:
- dependency-name: numpy
  dependency-version: 2.2.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-23 21:29:37 +00:00
Andrew Shumway
8c80f2a462 Merge pull request #1660 from GSA/dependabot/pip/eventlet-0.39.1
Bump eventlet from 0.36.1 to 0.39.1
2025-04-23 15:27:25 -06:00
dependabot[bot]
4ccfc82c8c Bump eventlet from 0.36.1 to 0.39.1
Bumps [eventlet](https://github.com/eventlet/eventlet) from 0.36.1 to 0.39.1.
- [Changelog](https://github.com/eventlet/eventlet/blob/master/NEWS)
- [Commits](https://github.com/eventlet/eventlet/compare/0.36.1...0.39.1)

---
updated-dependencies:
- dependency-name: eventlet
  dependency-version: 0.39.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-22 21:28:21 +00:00
Cliff Hill
ebd0ed9365 Merge pull request #1634 from GSA/2401-add-in-flask-socketio-for-api-calls-rather-than-using-ajax
2401 add in flask socketio for api calls rather than using ajax
2025-04-21 16:33:47 -04:00
Beverly Nguyen
02becbd1e5 removing run.py and unnecessary logs 2025-04-18 11:48:26 -07:00
Carlo Costino
419d6cee69 Update the flask-socketio config to play more nicely:
* Reverts run commands to what they previously were
* Addresses some outstanding linting/formatting
* Accounts for proper config initialization (CORS, Redis)
* Updates dependencies and pulls in latest changes from main

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2025-04-16 17:43:10 -04:00
Carlo Costino
71e8f20b04 Merge branch 'main' into 2401-add-in-flask-socketio-for-api-calls-rather-than-using-ajax 2025-04-16 10:55:16 -04:00
Kenneth Kehl
db90cecd65 Merge pull request #1655 from GSA/intl_nums
fix default case for US numbers
2025-04-15 11:44:44 -07:00
Kenneth Kehl
e93e3f3690 cleanup 2025-04-15 11:36:09 -07:00
Kenneth Kehl
d1fab496f4 pull from main 2025-04-15 11:33:25 -07:00
Kenneth Kehl
1f4b408d1d fix phone number check 2025-04-15 11:13:26 -07:00
Kenneth Kehl
f15d6128dc fix default case for US numbers 2025-04-15 10:44:30 -07:00
Beverly Nguyen
3ad7a3b2fd Merge pull request #1648 from GSA/update-makefile
Update Makefile to handle pre-existing git hooks
2025-04-14 13:29:01 -07:00
ccostino
aea7249124 Merge pull request #1644 from GSA/dependabot/pip/numpy-2.2.4
Bump numpy from 2.2.3 to 2.2.4
2025-04-14 16:20:07 -04:00
Carlo Costino
bf3897729c Create new command instead of trying to be fancy
Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2025-04-14 16:16:56 -04:00
Carlo Costino
8181eda049 Update Makefile to handle pre-existing git hooks
This changeset adds a bit of extra support to the bootstrap command to make sure that pre-existing git hooks do not interfere with the installation of the pre-commit git hooks.

Signed-off-by: Carlo Costino <carlo.costino@gsa.gov>
2025-04-14 15:45:03 -04:00
dependabot[bot]
e3d2e75182 Bump numpy from 2.2.3 to 2.2.4
Bumps [numpy](https://github.com/numpy/numpy) from 2.2.3 to 2.2.4.
- [Release notes](https://github.com/numpy/numpy/releases)
- [Changelog](https://github.com/numpy/numpy/blob/main/doc/RELEASE_WALKTHROUGH.rst)
- [Commits](https://github.com/numpy/numpy/compare/v2.2.3...v2.2.4)

---
updated-dependencies:
- dependency-name: numpy
  dependency-version: 2.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 18:56:13 +00:00
ccostino
22085aa334 Merge pull request #1645 from GSA/dependabot/pip/regex-2024.11.6
Bump regex from 2024.9.11 to 2024.11.6
2025-04-14 14:53:50 -04:00
dependabot[bot]
a236df97bf Bump regex from 2024.9.11 to 2024.11.6
Bumps [regex](https://github.com/mrabarnett/mrab-regex) from 2024.9.11 to 2024.11.6.
- [Changelog](https://github.com/mrabarnett/mrab-regex/blob/hg/changelog.txt)
- [Commits](https://github.com/mrabarnett/mrab-regex/compare/2024.9.11...2024.11.6)

---
updated-dependencies:
- dependency-name: regex
  dependency-version: 2024.11.6
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 15:30:44 +00:00
Beverly Nguyen
9e36418271 poetry 2025-04-10 17:47:38 -07:00
Beverly Nguyen
6f524cc907 Merge branch 'main' into 2401-add-in-flask-socketio-for-api-calls-rather-than-using-ajax 2025-04-10 17:44:09 -07:00
Beverly Nguyen
b37c803edc fix testing 2025-04-10 17:36:56 -07:00
Beverly Nguyen
1cc1d9a58d poetry add flask-socketio 2025-04-09 17:08:33 -07:00
Beverly Nguyen
9174978e3e merge main 2025-04-09 17:01:34 -07:00
Beverly Nguyen
f8726ca6b7 socket io setup 2025-04-09 16:56:42 -07:00
Beverly Nguyen
0792ea123f Merge branch 'main' into 2401-add-in-flask-socketio-for-api-calls-rather-than-using-ajax 2025-04-03 15:30:54 -07:00
Beverly Nguyen
16c68e06b9 initial test socket io setup 2025-03-27 09:51:22 -07:00
13 changed files with 2361 additions and 1561 deletions

View File

@@ -5,7 +5,8 @@ DATE = $(shell date +%Y-%m-%d:%H:%M:%S)
APP_VERSION_FILE = app/version.py
GIT_BRANCH ?= $(shell git symbolic-ref --short HEAD 2> /dev/null || echo "detached")
GIT_COMMIT ?= $(shell git rev-parse HEAD)
GIT_COMMIT ?= $(shell git rev-parse HEAD 2> /dev/null || echo "")
GIT_HOOKS_PATH ?= $(shell git config --global core.hooksPath || echo "")
## DEVELOPMENT
@@ -23,6 +24,19 @@ bootstrap: ## Set up everything to run the app
createdb test_notification_api || true
(poetry run flask db upgrade) || true
.PHONY: bootstrap-with-git-hooks
bootstrap-with-git-hooks: ## Sets everything up and accounts for pre-existing git hooks
make generate-version-file
poetry self add poetry-dotenv-plugin
poetry lock --no-update
poetry install --sync --no-root
git config --global --unset-all core.hooksPath
poetry run pre-commit install
git config --global core.hookspath "${GIT_HOOKS_PATH}"
createdb notification_api || true
createdb test_notification_api || true
(poetry run flask db upgrade) || true
.PHONY: bootstrap-with-docker
bootstrap-with-docker: ## Build the image to run the app in Docker
docker build -f docker/Dockerfile -t notifications-api .
@@ -50,7 +64,7 @@ too-complex:
poetry run radon cc ./app -a -nc
.PHONY: run-flask
run-flask: ## Run flask
run-flask:
poetry run newrelic-admin run-program flask run -p 6011 --host=0.0.0.0
.PHONY: run-celery

View File

@@ -13,6 +13,7 @@ from flask import current_app, g, has_request_context, jsonify, make_response, r
from flask.ctx import has_app_context
from flask_marshmallow import Marshmallow
from flask_migrate import Migrate
from flask_socketio import SocketIO
from flask_sqlalchemy import SQLAlchemy as _SQLAlchemy
from sqlalchemy import event
from werkzeug.exceptions import HTTPException as WerkzeugHTTPException
@@ -94,6 +95,14 @@ zendesk_client = ZendeskClient()
redis_store = RedisClient()
document_download_client = DocumentDownloadClient()
socketio = SocketIO(
cors_allowed_origins=[
config.Config.ADMIN_BASE_URL,
],
message_queue=config.Config.REDIS_URL,
logger=True,
engineio_logger=True,
)
notification_provider_clients = NotificationProviderClients()
@@ -111,6 +120,11 @@ def create_app(application):
application.config["NOTIFY_APP_NAME"] = application.name
init_app(application)
socketio.init_app(application)
from app.socket_handlers import register_socket_handlers
register_socket_handlers(socketio)
request_helper.init_app(application)
db.init_app(application)
migrate.init_app(application, db=db)

View File

@@ -179,6 +179,7 @@ class Config(object):
S3_RESOURCE = session.resource("s3", config=AWS_CLIENT_CONFIG)
CELERY = {
"broker_connection_retry_on_startup": True,
"worker_max_tasks_per_child": 500,
"task_ignore_result": True,
"result_persistent": False,

View File

@@ -26,9 +26,11 @@ from werkzeug.datastructures import MultiDict
from app import create_uuid, db
from app.dao.dao_utils import autocommit
from app.dao.inbound_sms_dao import Pagination
from app.dao.jobs_dao import dao_get_job_by_id
from app.enums import KeyType, NotificationStatus, NotificationType
from app.models import FactNotificationStatus, Notification, NotificationHistory
from app.utils import (
emit_job_update_summary,
escape_special_characters,
get_midnight_in_utc,
midnight_n_days_ago,
@@ -895,6 +897,19 @@ def dao_update_delivery_receipts(receipts, delivered):
f"#loadtestperformance batch update query time: \
updated {len(receipts)} notification in {elapsed_time} ms"
)
job_ids = (
db.session.execute(
select(Notification.job_id).where(
Notification.message_id.in_(id_to_carrier.keys())
)
)
.scalars()
.all()
)
for job_id in set(job_ids):
job = dao_get_job_by_id(job_id)
emit_job_update_summary(job)
def dao_close_out_delivery_receipts():

View File

@@ -105,6 +105,17 @@ def send_sms_to_provider(notification):
# The future home of the validation is TBD
_experimentally_validate_phone_numbers(recipient)
# TODO current we allow US phone numbers to be uploaded without the country code (1)
# This will break certain international phone numbers (Norway, Denmark, East Timor)
# When we officially announce support for international numbers, US numbers must contain
# their country code.
recipient = str(recipient)
if len(recipient) == 10:
if os.getenv("NOTIFY_ENVIRONMENT") not in [
"test"
]: # we want to test intl support
recipient = f"1{recipient}"
sender_numbers = get_sender_numbers(notification)
if notification.reply_to_text not in sender_numbers:
raise ValueError(

16
app/socket_handlers.py Normal file
View File

@@ -0,0 +1,16 @@
from flask import current_app, request
from flask_socketio import join_room, leave_room
def register_socket_handlers(socketio):
@socketio.on("join")
def on_join(data): # noqa: F401
room = data.get("room")
join_room(room)
current_app.logger.info(f"Socket {request.sid} joined room {room}")
@socketio.on("leave")
def on_leave(data): # noqa: F401
room = data.get("room")
leave_room(room)
current_app.logger.info(f"Socket {request.sid} left room {room}")

View File

@@ -1,4 +1,4 @@
from flask import Blueprint, jsonify, make_response, request
from flask import Blueprint, jsonify, request
from sqlalchemy import text
from app import db, version
@@ -14,7 +14,7 @@ def show_status():
if request.args.get("simple", None):
return jsonify(status="ok"), 200
else:
response = make_response(
return (
jsonify(
status="ok", # This should be considered part of the public API
git_commit=version.__git_commit__,
@@ -23,21 +23,17 @@ def show_status():
),
200,
)
response.headers["Content-Type"] = "application/json"
return response
@status.route("/_status/live-service-and-organization-counts")
def live_service_and_organization_counts():
response = make_response(
return (
jsonify(
organizations=dao_count_organizations_with_live_services(),
services=dao_count_live_services(),
),
200,
)
response.headers["Content-Type"] = "application/json"
return response
def get_db_version():

View File

@@ -131,3 +131,18 @@ def utc_now():
def debug_not_production(msg):
if os.getenv("NOTIFY_ENVIRONMENT") not in ["production"]:
current_app.logger.info(msg)
def emit_job_update_summary(job):
from app import socketio
current_app.logger.info(f"Emitting summary for job {job.id}")
socketio.emit(
"job_updated",
{
"job_id": str(job.id),
"job_status": job.job_status,
"notification_count": job.notification_count,
},
room=f"job-{job.id}",
)

120
package-lock.json generated Normal file
View File

@@ -0,0 +1,120 @@
{
"name": "notifications-api",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"socket.io-client": "^4.8.1"
}
},
"node_modules/@socket.io/component-emitter": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
"license": "MIT"
},
"node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/engine.io-client": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
"integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.17.1",
"xmlhttprequest-ssl": "~2.1.1"
}
},
"node_modules/engine.io-parser": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
"integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/socket.io-client": {
"version": "4.8.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
"integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.6.1",
"socket.io-parser": "~4.2.4"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/ws": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/xmlhttprequest-ssl": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
"integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==",
"engines": {
"node": ">=0.4.0"
}
}
}
}

5
package.json Normal file
View File

@@ -0,0 +1,5 @@
{
"dependencies": {
"socket.io-client": "^4.8.1"
}
}

3663
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -18,30 +18,30 @@ celery = {version = "==5.4.0", extras = ["redis"]}
certifi = ">=2022.12.7"
cffi = "==1.17.1"
charset-normalizer = "^3.4.1"
click = "==8.1.7"
click = "==8.1.8"
click-datetime = "==0.4.0"
click-didyoumean = "==0.3.1"
click-plugins = "==1.1.1"
click-repl = "==0.3.0"
deprecated = "==1.2.14"
eventlet = "==0.36.1"
eventlet = "==0.39.1"
expiringdict = "==1.2.2"
flask = "~=3.0"
flask-bcrypt = "==1.0.1"
flask-marshmallow = "==1.2.1"
flask-migrate = "==4.0.7"
flask-migrate = "==4.1.0"
flask-redis = "==0.4.0"
flask-sqlalchemy = "==3.1.1"
gunicorn = {version = "==23.0.0", extras = ["eventlet"]}
iso8601 = "==2.1.0"
jsonschema = {version = "==4.23.0", extras = ["format"]}
lxml = "==5.3.1"
marshmallow = "==3.26.1"
marshmallow = "==4.0.0"
marshmallow-sqlalchemy = "==1.0.0"
newrelic = "*"
notifications-python-client = "==10.0.0"
oscrypto = { git = "https://github.com/wbond/oscrypto.git", rev = "1547f53" }
packaging = "==24.2"
packaging = "==25.0"
poetry-dotenv-plugin = "==0.2.0"
psycopg2-binary = "==2.9.9"
pyjwt = "==2.10.1"
@@ -52,11 +52,11 @@ faker = "^26.0.0"
async-timeout = "^5.0.1"
bleach = "^6.1.0"
geojson = "^3.2.0"
numpy = "^2.2.3"
numpy = "^2.2.5"
ordered-set = "^4.1.0"
phonenumbers = "^8.13.42"
python-json-logger = "^2.0.7"
regex = "^2024.7.24"
python-json-logger = "^3.3.0"
regex = "^2024.11.6"
shapely = "^2.0.5"
smartypants = "^2.0.1"
mistune = "^3.1.3"
@@ -76,6 +76,7 @@ itsdangerous = "^2.2.0"
jinja2 = "^3.1.6"
redis = "^5.0.8"
requests = "^2.32.3"
flask-socketio = "^5.5.1"
[tool.poetry.group.dev.dependencies]
@@ -90,7 +91,7 @@ freezegun = "^1.5.1"
honcho = "*"
isort = "^5.13.2"
jinja2-cli = {version = "==0.8.2", extras = ["yaml"]}
moto = "==5.1.0"
moto = "==5.1.4"
pip-audit = "*"
pre-commit = "^4.2.0"
pytest = "^8.3.2"

View File

@@ -2029,12 +2029,23 @@ def test_update_delivery_receipts(mocker):
mock_update.where.return_value = mock_where
mock_where.values.return_value = mock_values
mock_session.execute.return_value = None
FakeJob = type(
"FakeJob",
(object,),
{"id": "job-123", "notification_count": 5, "job_status": "delivered"},
)
fake_result = MagicMock()
fake_result.scalars.return_value.all.return_value = ["job-1", "job-2"]
fake_result.scalars.return_value.one.return_value = FakeJob()
mock_session.execute.side_effect = lambda *args, **kwargs: fake_result
with patch("app.dao.notifications_dao.update", return_value=mock_update):
dao_update_delivery_receipts(receipts, delivered)
mock_update.where.assert_called_once()
mock_where.values.assert_called_once()
mock_session.execute.assert_called_once_with(mock_values)
mock_session.execute.assert_any_call(mock_values)
assert mock_session.execute.call_count == 4
mock_session.commit.assert_called_once()
args, kwargs = mock_where.values.call_args