mesh-sandbox 1.0.10__py3-none-any.whl → 1.0.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. mesh_sandbox/__init__.py +1 -1
  2. mesh_sandbox/api.py +0 -1
  3. mesh_sandbox/common/__init__.py +1 -3
  4. mesh_sandbox/common/messaging.py +20 -32
  5. mesh_sandbox/common/mex_headers.py +0 -1
  6. mesh_sandbox/conftest.py +2 -6
  7. mesh_sandbox/dependencies.py +5 -6
  8. mesh_sandbox/handlers/admin.py +0 -2
  9. mesh_sandbox/handlers/handshake.py +0 -2
  10. mesh_sandbox/handlers/inbox.py +1 -10
  11. mesh_sandbox/handlers/lookup.py +0 -2
  12. mesh_sandbox/handlers/outbox.py +4 -8
  13. mesh_sandbox/handlers/tracking.py +0 -2
  14. mesh_sandbox/models/mailbox.py +0 -2
  15. mesh_sandbox/models/message.py +2 -5
  16. mesh_sandbox/models/workflow.py +0 -2
  17. mesh_sandbox/routers/inbox.py +5 -5
  18. mesh_sandbox/routers/inbox_count.py +2 -2
  19. mesh_sandbox/routers/lookup.py +3 -4
  20. mesh_sandbox/routers/outbox.py +3 -3
  21. mesh_sandbox/routers/tracking.py +2 -2
  22. mesh_sandbox/store/base.py +0 -1
  23. mesh_sandbox/store/canned_store.py +9 -15
  24. mesh_sandbox/store/file_store.py +0 -1
  25. mesh_sandbox/store/serialisation.py +2 -3
  26. mesh_sandbox/test_plugin/example_plugin.py +3 -4
  27. mesh_sandbox/tests/admin.py +0 -26
  28. mesh_sandbox/tests/docker_tests.py +0 -2
  29. mesh_sandbox/tests/exceptions.py +0 -1
  30. mesh_sandbox/tests/handshake.py +3 -11
  31. mesh_sandbox/tests/helpers.py +0 -3
  32. mesh_sandbox/tests/inbox.py +0 -13
  33. mesh_sandbox/tests/java_client_tests.py +1 -6
  34. mesh_sandbox/tests/lookup.py +2 -4
  35. mesh_sandbox/tests/mesh_api_helpers.py +1 -8
  36. mesh_sandbox/tests/mesh_client_tests.py +7 -12
  37. mesh_sandbox/tests/messaging_tests.py +13 -23
  38. mesh_sandbox/tests/outbox.py +1 -15
  39. mesh_sandbox/tests/serialisation.py +0 -1
  40. mesh_sandbox/views/error.py +3 -7
  41. mesh_sandbox/views/inbox.py +4 -7
  42. mesh_sandbox/views/lookup.py +6 -6
  43. mesh_sandbox/views/outbox.py +21 -26
  44. mesh_sandbox/views/tracking.py +0 -4
  45. {mesh_sandbox-1.0.10.dist-info → mesh_sandbox-1.0.12.dist-info}/METADATA +16 -41
  46. mesh_sandbox-1.0.12.dist-info/RECORD +76 -0
  47. mesh_sandbox-1.0.10.dist-info/RECORD +0 -76
  48. {mesh_sandbox-1.0.10.dist-info → mesh_sandbox-1.0.12.dist-info}/LICENSE +0 -0
  49. {mesh_sandbox-1.0.10.dist-info → mesh_sandbox-1.0.12.dist-info}/WHEEL +0 -0
@@ -41,36 +41,32 @@ def _mesh_client_track_message_by_message_id(base_uri: str, sender_mailbox_id: s
41
41
  with MeshClient(
42
42
  url=base_uri, mailbox=sender_mailbox_id, password=_PASSWORD, shared_key=_SHARED_KEY, max_chunk_size=100
43
43
  ) as sender:
44
- tracking = sender.track_by_message_id(message_id)
44
+ tracking = sender.track_message(message_id)
45
45
  assert tracking
46
46
  return tracking
47
47
 
48
48
 
49
49
  def test_app_health(base_uri: str):
50
-
51
50
  with httpx.Client(base_url=base_uri) as client:
52
51
  res = client.get("/health")
53
52
  assert res.status_code == status.HTTP_200_OK
54
53
 
55
54
 
56
55
  def test_handshake(base_uri: str):
57
-
58
56
  with MeshClient(url=base_uri, mailbox=_CANNED_MAILBOX1, password=_PASSWORD, shared_key=_SHARED_KEY) as client:
59
57
  res = client.handshake()
60
58
  assert res == b"hello"
61
59
 
62
60
 
63
61
  def test_handshake_bad_password(base_uri: str):
64
-
65
62
  with MeshClient(url=base_uri, mailbox=_CANNED_MAILBOX1, password="BAD", shared_key=_SHARED_KEY) as client:
66
-
67
63
  with pytest.raises(HTTPError) as err:
68
64
  client.handshake()
65
+ assert err.value.response is not None
69
66
  assert err.value.response.status_code == status.HTTP_403_FORBIDDEN
70
67
 
71
68
 
72
69
  def test_send_receive_chunked_message(base_uri: str):
73
-
74
70
  workflow_id = uuid4().hex
75
71
  sent_payload = b"a" * 1000
76
72
  message_id = _mesh_client_send_message(base_uri, _CANNED_MAILBOX1, _CANNED_MAILBOX2, workflow_id, sent_payload)
@@ -90,16 +86,15 @@ def test_send_receive_chunked_message(base_uri: str):
90
86
 
91
87
 
92
88
  def test_track_message_by_message_id(base_uri: str):
93
-
94
89
  workflow_id = uuid4().hex
95
90
  sent_payload = b"a" * 1000
96
91
  message_id = _mesh_client_send_message(base_uri, _CANNED_MAILBOX1, _CANNED_MAILBOX2, workflow_id, sent_payload)
97
92
  assert _mesh_client_get_inbox_count(base_uri, _CANNED_MAILBOX2) == 1
98
93
 
99
94
  tracking = _mesh_client_track_message_by_message_id(base_uri, _CANNED_MAILBOX1, message_id)
100
- assert tracking["messageId"] == message_id
101
- assert tracking["status"] == "Accepted"
102
- assert tracking["sender"] == _CANNED_MAILBOX1
95
+ assert tracking["message_id"] == message_id
96
+ assert tracking["status"] == "accepted"
97
+ # assert tracking["sender"] == _CANNED_MAILBOX1
103
98
  assert tracking["recipient"] == _CANNED_MAILBOX2
104
99
 
105
100
  with MeshClient(url=base_uri, mailbox=_CANNED_MAILBOX2, password=_PASSWORD, shared_key=_SHARED_KEY) as recipient:
@@ -107,5 +102,5 @@ def test_track_message_by_message_id(base_uri: str):
107
102
  message.acknowledge()
108
103
 
109
104
  tracking = _mesh_client_track_message_by_message_id(base_uri, _CANNED_MAILBOX1, message_id)
110
- assert tracking["messageId"] == message_id
111
- assert tracking["status"] == "Acknowledged"
105
+ assert tracking["message_id"] == message_id
106
+ assert tracking["status"] == "acknowledged"
@@ -1,4 +1,4 @@
1
- from typing import Any, Optional
1
+ from typing import Any, ClassVar, Optional
2
2
  from uuid import uuid4
3
3
 
4
4
  import pytest
@@ -17,8 +17,8 @@ from ..models.message import (
17
17
  from .helpers import temp_env_vars
18
18
 
19
19
 
20
- @pytest.fixture(name="message", scope="function")
21
- def _create_message() -> Message:
20
+ @pytest.fixture(name="message")
21
+ def create_message() -> Message:
22
22
  message = Message(
23
23
  message_id=uuid4().hex.upper(),
24
24
  workflow_id=uuid4().hex.upper(),
@@ -30,26 +30,24 @@ def _create_message() -> Message:
30
30
  return message
31
31
 
32
32
 
33
- @pytest.fixture(name="background_tasks", scope="function")
34
- def _background_tasks() -> BackgroundTasks:
33
+ @pytest.fixture(name="background_tasks")
34
+ def background_tasks() -> BackgroundTasks:
35
35
  return BackgroundTasks()
36
36
 
37
37
 
38
38
  async def test_canned_store_raises_for_save_message(message: Message):
39
+ with temp_env_vars(STORE_MODE="canned"):
40
+ store = get_store()
39
41
 
40
- with pytest.raises(NotImplementedError):
41
- with temp_env_vars(STORE_MODE="canned"):
42
- store = get_store()
42
+ with pytest.raises(NotImplementedError):
43
43
  await store.save_message(message)
44
44
 
45
45
 
46
46
  async def test_canned_messaging_does_not_raise_no_bgt(message: Message):
47
-
48
47
  calls = []
49
48
 
50
49
  class TestPlugin:
51
-
52
- triggers = ["before_save_message", "after_save_message", "save_message_error"]
50
+ triggers: ClassVar[list[str]] = ["before_save_message", "after_save_message", "save_message_error"]
53
51
 
54
52
  async def on_event(self, event: str, args: dict[str, Any], exception: Optional[Exception] = None):
55
53
  calls.append((event, args, exception))
@@ -64,12 +62,10 @@ async def test_canned_messaging_does_not_raise_no_bgt(message: Message):
64
62
 
65
63
 
66
64
  async def test_canned_messaging_does_not_raise_with_bgt(message: Message, background_tasks: BackgroundTasks):
67
-
68
65
  calls = []
69
66
 
70
67
  class Test2Plugin:
71
-
72
- triggers = ["before_save_message", "after_save_message", "save_message_error"]
68
+ triggers: ClassVar[list[str]] = ["before_save_message", "after_save_message", "save_message_error"]
73
69
 
74
70
  async def on_event(self, event: str, args: dict[str, Any], exception: Optional[Exception] = None):
75
71
  calls.append((event, args, exception))
@@ -87,12 +83,10 @@ async def test_canned_messaging_does_not_raise_with_bgt(message: Message, backgr
87
83
 
88
84
 
89
85
  async def test_messaging_does_not_raise_with_bgt(message: Message, background_tasks: BackgroundTasks):
90
-
91
86
  calls = []
92
87
 
93
88
  class Test2Plugin:
94
-
95
- triggers = ["before_save_message", "after_save_message", "save_message_error"]
89
+ triggers: ClassVar[list[str]] = ["before_save_message", "after_save_message", "save_message_error"]
96
90
 
97
91
  async def on_event(self, event: str, args: dict[str, Any], exception: Optional[Exception] = None):
98
92
  calls.append((event, args, exception))
@@ -110,12 +104,10 @@ async def test_messaging_does_not_raise_with_bgt(message: Message, background_ta
110
104
 
111
105
 
112
106
  async def test_error_events_raised_with_bgt(message: Message, background_tasks: BackgroundTasks):
113
-
114
107
  calls = []
115
108
 
116
109
  class Test2Plugin:
117
-
118
- triggers = ["before_save_message", "after_save_message", "save_message_error"]
110
+ triggers: ClassVar[list[str]] = ["before_save_message", "after_save_message", "save_message_error"]
119
111
 
120
112
  async def on_event(self, event: str, args: dict[str, Any], exception: Optional[Exception] = None):
121
113
  calls.append((event, args, exception))
@@ -133,15 +125,13 @@ async def test_error_events_raised_with_bgt(message: Message, background_tasks:
133
125
 
134
126
 
135
127
  class TestDiscoveredPlugin:
136
-
137
- triggers = ["before_accept_message"]
128
+ triggers: ClassVar[list[str]] = ["before_accept_message"]
138
129
 
139
130
  async def on_event(self, event: str, args: dict[str, Any], err: Optional[Exception] = None):
140
131
  pass
141
132
 
142
133
 
143
134
  async def test_plugin_discovery(monkeypatch):
144
-
145
135
  messaging = Messaging(store=get_store(), plugins_module=tests_module)
146
136
 
147
137
  calls = []
@@ -18,7 +18,6 @@ _CANNED_MAILBOX2 = "X26ABC2"
18
18
 
19
19
  @pytest.mark.parametrize("accept", [APP_V1_JSON, APP_V2_JSON])
20
20
  def test_memory_send_message_with_local_id(app: TestClient, accept: str):
21
-
22
21
  sender = _CANNED_MAILBOX1
23
22
  recipient = _CANNED_MAILBOX2
24
23
 
@@ -130,12 +129,10 @@ def test_memory_send_message_with_local_id(app: TestClient, accept: str):
130
129
 
131
130
  @pytest.mark.parametrize("accept", [APP_V1_JSON, APP_V2_JSON])
132
131
  def test_file_send_message_with_local_id(app: TestClient, accept: str, tmp_path: str):
133
-
134
132
  sender = _CANNED_MAILBOX1
135
133
  recipient = _CANNED_MAILBOX2
136
134
 
137
135
  with temp_env_vars(STORE_MODE="file", MAILBOXES_DATA_DIR=tmp_path):
138
-
139
136
  res = app.get(
140
137
  f"/messageexchange/{recipient}/inbox",
141
138
  headers={Headers.Authorization: generate_auth_token(recipient), Headers.Accept: accept},
@@ -193,7 +190,6 @@ def test_file_send_message_with_local_id(app: TestClient, accept: str, tmp_path:
193
190
 
194
191
  @pytest.mark.parametrize("accept", [APP_V1_JSON, APP_V2_JSON])
195
192
  def test_memory_send_chunked_message(app: TestClient, accept: str):
196
-
197
193
  sender = _CANNED_MAILBOX1
198
194
  recipient = _CANNED_MAILBOX2
199
195
 
@@ -313,12 +309,10 @@ def test_memory_send_chunked_message(app: TestClient, accept: str):
313
309
 
314
310
  @pytest.mark.parametrize("accept", [APP_V1_JSON, APP_V2_JSON])
315
311
  def test_file_send_chunked_message(app: TestClient, accept: str, tmp_path: str): # pylint: disable=too-many-statements
316
-
317
312
  sender = _CANNED_MAILBOX1
318
313
  recipient = _CANNED_MAILBOX2
319
314
 
320
315
  with temp_env_vars(STORE_MODE="file", MAILBOXES_DATA_DIR=tmp_path):
321
-
322
316
  res = app.get(
323
317
  f"/messageexchange/{recipient}/inbox",
324
318
  headers={Headers.Authorization: generate_auth_token(recipient), Headers.Accept: accept},
@@ -462,7 +456,6 @@ def test_file_send_chunked_message(app: TestClient, accept: str, tmp_path: str):
462
456
  ],
463
457
  )
464
458
  def test_mex_content_compress_validation(app: TestClient, value: str):
465
-
466
459
  sender = _CANNED_MAILBOX1
467
460
  recipient = _CANNED_MAILBOX2
468
461
 
@@ -500,7 +493,6 @@ def test_mex_content_compress_validation(app: TestClient, value: str):
500
493
  ],
501
494
  )
502
495
  def test_mex_content_encrypted_validation(app: TestClient, value: str):
503
-
504
496
  sender = _CANNED_MAILBOX1
505
497
  recipient = _CANNED_MAILBOX2
506
498
 
@@ -538,7 +530,6 @@ def test_mex_content_encrypted_validation(app: TestClient, value: str):
538
530
  ],
539
531
  )
540
532
  def test_mex_content_compressed_validation(app: TestClient, value: str):
541
-
542
533
  sender = _CANNED_MAILBOX1
543
534
  recipient = _CANNED_MAILBOX2
544
535
 
@@ -547,7 +538,7 @@ def test_mex_content_compressed_validation(app: TestClient, value: str):
547
538
 
548
539
 
549
540
  @pytest.mark.parametrize(
550
- "mex_content_checksum, expected_response_status",
541
+ ("mex_content_checksum", "expected_response_status"),
551
542
  [
552
543
  ("", status.HTTP_202_ACCEPTED),
553
544
  ("b10a8db164e0754105b7a99be72e3fe5", status.HTTP_202_ACCEPTED),
@@ -559,7 +550,6 @@ def test_mex_content_compressed_validation(app: TestClient, value: str):
559
550
  ],
560
551
  )
561
552
  def test_mex_content_checksum_validation(app: TestClient, mex_content_checksum: str, expected_response_status: int):
562
-
563
553
  sender = _CANNED_MAILBOX1
564
554
  recipient = _CANNED_MAILBOX2
565
555
 
@@ -571,7 +561,6 @@ def test_mex_content_checksum_validation(app: TestClient, mex_content_checksum:
571
561
 
572
562
 
573
563
  def test_mex_local_id_validation(app: TestClient):
574
-
575
564
  sender = _CANNED_MAILBOX1
576
565
  recipient = _CANNED_MAILBOX2
577
566
 
@@ -584,7 +573,6 @@ def test_mex_local_id_validation(app: TestClient):
584
573
 
585
574
  @pytest.mark.parametrize("accept", [APP_V1_JSON, APP_V2_JSON])
586
575
  def test_checksum_is_returned(app: TestClient, accept: str):
587
-
588
576
  sender = _CANNED_MAILBOX1
589
577
  recipient = _CANNED_MAILBOX2
590
578
  checksum = uuid4().hex
@@ -614,7 +602,6 @@ def test_checksum_is_returned(app: TestClient, accept: str):
614
602
 
615
603
 
616
604
  def test_rich_outbox_returns_most_recent_messages(app: TestClient):
617
-
618
605
  sender = _CANNED_MAILBOX1
619
606
  recipient = _CANNED_MAILBOX2
620
607
  total_messages = 105
@@ -627,7 +614,6 @@ def test_rich_outbox_returns_most_recent_messages(app: TestClient):
627
614
 
628
615
  message_ids = {}
629
616
  for index in range(total_messages):
630
-
631
617
  resp = mesh_api_send_message(
632
618
  app,
633
619
  sender_mailbox_id=sender,
@@ -6,7 +6,6 @@ from ..store.serialisation import deserialise_model, serialise_model
6
6
 
7
7
 
8
8
  def test_serialise_deserialise_message():
9
-
10
9
  message = Message(
11
10
  message_id=uuid4().hex,
12
11
  metadata=MessageMetadata(local_id=uuid4().hex),
@@ -12,7 +12,6 @@ from ..dependencies import parse_accept_header
12
12
 
13
13
 
14
14
  class MeshErrorV1(BaseModel):
15
-
16
15
  messageID: Optional[str] = Field(description="message_id associated with the error", default=None)
17
16
  errorEvent: Optional[str] = Field(description="message error phase", default="")
18
17
  errorCode: Optional[str] = Field(description="message error code", default="")
@@ -20,7 +19,7 @@ class MeshErrorV1(BaseModel):
20
19
 
21
20
  class Config:
22
21
  title = "mesh_error_v1"
23
- schema_extra = {
22
+ json_schema_extra = {
24
23
  "example": {
25
24
  "messageID": "20220228174323222_ABCDEF",
26
25
  "errorEvent": "SEND",
@@ -31,14 +30,13 @@ class MeshErrorV1(BaseModel):
31
30
 
32
31
 
33
32
  class MeshErrorV2(BaseModel):
34
-
35
33
  message_id: Optional[str] = Field(description="message id associated with the error", default=None)
36
34
  internal_id: Optional[str] = Field(description="internal id associated with the error", default=None)
37
35
  detail: list[dict] = Field(description="error detail", default_factory=list)
38
36
 
39
37
  class Config:
40
38
  title = "mesh_error_v2"
41
- schema_extra = {
39
+ json_schema_extra = {
42
40
  "example": {
43
41
  "message_id": "20220228174323222_ABCDEF",
44
42
  "internal_id": "20220228174323222_ABCDEF",
@@ -48,7 +46,6 @@ class MeshErrorV2(BaseModel):
48
46
 
49
47
 
50
48
  def get_validation_error_response(_request: Request, exc: RequestValidationError) -> Response:
51
-
52
49
  for err in exc.errors():
53
50
  if err["loc"][0] == "header" and cast(str, err["loc"][1]).lower() == Headers.Authorization.lower():
54
51
  return Response(status_code=status.HTTP_403_FORBIDDEN)
@@ -67,9 +64,8 @@ def get_error_response(
67
64
  status_code: int,
68
65
  detail: Union[str, dict, None] = None,
69
66
  message_id: Optional[str] = None,
70
- headers: dict = None, # type: ignore[assignment]
67
+ headers: Optional[dict] = None, # type: ignore[assignment]
71
68
  ) -> JSONResponse:
72
-
73
69
  internal_id = None
74
70
  if hasattr(request.state, "internal_id"):
75
71
  internal_id = request.state.internal_id
@@ -10,16 +10,14 @@ from . import RichMessageV1
10
10
 
11
11
 
12
12
  class InboxV1(BaseModel):
13
-
14
13
  messages: list[str] = Field(description="list of message ids in the inbox, up to 'max_results'")
15
14
 
16
15
  class Config:
17
16
  title = "inbox_v1"
18
- schema_extra = {"example": {"messages": ["20220228174323222_ABCDEF", "20220228174323333_ABCDEF"]}}
17
+ json_schema_extra = {"example": {"messages": ["20220228174323222_ABCDEF", "20220228174323333_ABCDEF"]}}
19
18
 
20
19
 
21
20
  class InboxV2(BaseModel):
22
-
23
21
  messages: list[str] = Field(description="list of message ids in the inbox, up to 'max_results'")
24
22
  links: Optional[dict[str, str]] = Field(description="map of links, e.g. links.next if more results exist")
25
23
  approx_inbox_count: Optional[int] = Field(
@@ -31,7 +29,7 @@ class InboxV2(BaseModel):
31
29
 
32
30
  class Config:
33
31
  title = "inbox_v2"
34
- schema_extra = {
32
+ json_schema_extra = {
35
33
  "example": {
36
34
  "messages": ["20220228174323222_ABCDEF", "20220228174323333_ABCDEF"],
37
35
  "links": {
@@ -45,12 +43,11 @@ class InboxV2(BaseModel):
45
43
 
46
44
 
47
45
  class AcknowledgeV1(BaseModel):
48
-
49
46
  messageId: str = Field(description="message_id as passed in on the url")
50
47
 
51
48
  class Config:
52
49
  title = "acknowledge_message"
53
- schema_extra = {"example": {"messageId": ["20220228174323222_ABCDEF"]}}
50
+ json_schema_extra = {"example": {"messageId": ["20220228174323222_ABCDEF"]}}
54
51
 
55
52
 
56
53
  class InboxMessageV1(RichMessageV1):
@@ -94,7 +91,7 @@ class RichInboxView(BaseModel):
94
91
 
95
92
  class Config:
96
93
  title = "rich_inbox"
97
- schema_extra = {
94
+ json_schema_extra = {
98
95
  "example": {
99
96
  "valid_at": "2021-11-22T14:35:52.29Z",
100
97
  "messages": [
@@ -13,7 +13,7 @@ class EndpointLookupItemV1(BaseModel):
13
13
 
14
14
  class Config:
15
15
  title = "endpoint_lookup_item_v1"
16
- schema_extra = {
16
+ json_schema_extra = {
17
17
  "example": {"address": "X2612345", "description": "this is a test mailbox", "endpoint_type": "MESH"}
18
18
  }
19
19
 
@@ -24,7 +24,7 @@ class EndpointLookupV1(BaseModel):
24
24
 
25
25
  class Config:
26
26
  title = "endpoint_lookup_v1"
27
- schema_extra = {
27
+ json_schema_extra = {
28
28
  "example": {
29
29
  "query_id": "20220228174323222_ABCDEF",
30
30
  "results": {"address": "X2612345", "description": "this is a test mailbox", "endpoint_type": "MESH"},
@@ -38,7 +38,7 @@ class MailboxLookupItem(BaseModel):
38
38
 
39
39
  class Config:
40
40
  title = "lookup_item_v2"
41
- schema_extra = {"example": {"mailbox_id": "X2612345", "mailbox_name": "this is a test mailbox"}}
41
+ json_schema_extra = {"example": {"mailbox_id": "X2612345", "mailbox_name": "this is a test mailbox"}}
42
42
 
43
43
 
44
44
  class MailboxLookupV2(BaseModel):
@@ -46,13 +46,14 @@ class MailboxLookupV2(BaseModel):
46
46
 
47
47
  class Config:
48
48
  title = "lookup_v2"
49
- schema_extra = {"example": {"results": {"mailbox_id": "X2612345", "mailbox_name": "this is a test mailbox"}}}
49
+ json_schema_extra = {
50
+ "example": {"results": {"mailbox_id": "X2612345", "mailbox_name": "this is a test mailbox"}}
51
+ }
50
52
 
51
53
 
52
54
  def endpoint_lookup_response(
53
55
  mailboxes: list[Mailbox], model_version: int = 1
54
56
  ) -> Union[EndpointLookupV1, MailboxLookupV2]:
55
-
56
57
  if model_version < 2:
57
58
  return EndpointLookupV1(
58
59
  query_id=uuid4().hex,
@@ -75,7 +76,6 @@ def endpoint_lookup_response(
75
76
 
76
77
  # pylint: disable=unused-argument
77
78
  def workflow_search_response(mailboxes: list[Mailbox], model_version: int = 1) -> MailboxLookupV2:
78
-
79
79
  return MailboxLookupV2(
80
80
  results=[
81
81
  MailboxLookupItem(
@@ -14,7 +14,7 @@ class SendMessageV1(BaseModel):
14
14
 
15
15
  class Config:
16
16
  title = "send_message"
17
- schema_extra = {"example": {"messageID": "20220228174323222_ABCDEF"}}
17
+ json_schema_extra = {"example": {"messageID": "20220228174323222_ABCDEF"}}
18
18
 
19
19
 
20
20
  class SendMessageV2(BaseModel):
@@ -22,7 +22,7 @@ class SendMessageV2(BaseModel):
22
22
 
23
23
  class Config:
24
24
  title = "send_message"
25
- schema_extra = {"example": {"message_id": "20220228174323222_ABCDEF"}}
25
+ json_schema_extra = {"example": {"message_id": "20220228174323222_ABCDEF"}}
26
26
 
27
27
 
28
28
  class UploadChunkV1(BaseModel):
@@ -31,11 +31,10 @@ class UploadChunkV1(BaseModel):
31
31
 
32
32
  class Config:
33
33
  title = "upload_chunk"
34
- schema_extra = {"example": {"messageID": "20220228174323222_ABCDEF", "blockID": 3}}
34
+ json_schema_extra = {"example": {"messageID": "20220228174323222_ABCDEF", "blockID": 3}}
35
35
 
36
36
 
37
37
  class OutboxMessageV1(RichMessageV1):
38
-
39
38
  # pylint: disable=E0213
40
39
  class Config:
41
40
  validate_assignment = True
@@ -53,7 +52,7 @@ class RichOutboxView(BaseModel):
53
52
  class Config:
54
53
  validate_assignment = True
55
54
  title = "rich_outbox"
56
- schema_extra = {
55
+ json_schema_extra = {
57
56
  "example": {
58
57
  "valid_at": "2021-11-22T14:35:52.29Z",
59
58
  "messages": [
@@ -85,26 +84,24 @@ class RichOutboxView(BaseModel):
85
84
 
86
85
 
87
86
  def map_to_outbox_message(messages: list[Message]) -> list[OutboxMessageV1]:
88
- return list(
89
- map(
90
- lambda msg: OutboxMessageV1(
91
- message_id=msg.message_id,
92
- expiry_timestamp=msg.inbox_expiry_timestamp,
93
- local_id=msg.metadata.local_id,
94
- message_type=msg.message_type,
95
- recipient=msg.recipient.mailbox_id,
96
- recipient_name=msg.recipient.mailbox_name,
97
- sender=msg.sender.mailbox_id,
98
- sender_name=msg.sender.mailbox_name,
99
- sent_date=msg.created_timestamp,
100
- status=msg.status,
101
- status_code=msg.last_event.code,
102
- workflow_id=msg.workflow_id,
103
- total_chunks=msg.total_chunks or 0,
104
- ),
105
- messages,
87
+ return [
88
+ OutboxMessageV1(
89
+ message_id=msg.message_id,
90
+ expiry_timestamp=msg.inbox_expiry_timestamp,
91
+ local_id=msg.metadata.local_id,
92
+ message_type=msg.message_type,
93
+ recipient=msg.recipient.mailbox_id,
94
+ recipient_name=msg.recipient.mailbox_name,
95
+ sender=msg.sender.mailbox_id,
96
+ sender_name=msg.sender.mailbox_name,
97
+ sent_date=msg.created_timestamp,
98
+ status=msg.status,
99
+ status_code=msg.last_event.code,
100
+ workflow_id=msg.workflow_id,
101
+ total_chunks=msg.total_chunks or 0,
106
102
  )
107
- )
103
+ for msg in messages
104
+ ]
108
105
 
109
106
 
110
107
  def get_rich_outbox_view(messages: list[Message], links: dict[str, str]) -> JSONResponse:
@@ -121,7 +118,6 @@ def get_rich_outbox_view(messages: list[Message], links: dict[str, str]) -> JSON
121
118
 
122
119
 
123
120
  def send_message_response(message: Message, model_version: int = 1) -> Union[SendMessageV1, SendMessageV2]:
124
-
125
121
  if model_version < 2:
126
122
  return SendMessageV1(messageID=message.message_id)
127
123
 
@@ -129,7 +125,6 @@ def send_message_response(message: Message, model_version: int = 1) -> Union[Sen
129
125
 
130
126
 
131
127
  def upload_chunk_response(message: Message, chunk_number: int, model_version: int = 1) -> Optional[UploadChunkV1]:
132
-
133
128
  if model_version < 2:
134
129
  return UploadChunkV1(messageID=message.message_id, blockID=chunk_number)
135
130
 
@@ -9,7 +9,6 @@ _EMPTY: Final[str] = ""
9
9
 
10
10
 
11
11
  class TrackingV1(BaseModel):
12
-
13
12
  addressType: Optional[str] = "ALL"
14
13
  checksum: Optional[str] = Field(description="message status e.g. 'accepted' 'acknowledged'")
15
14
  chunkCount: Optional[int] = Field(description="number of message chunks")
@@ -62,7 +61,6 @@ class TrackingV1(BaseModel):
62
61
 
63
62
 
64
63
  class TrackingV2(BaseModel):
65
-
66
64
  message_id: str = Field(description="message identifier")
67
65
  local_id: Optional[str] = Field(description="local identifier supplied by sender")
68
66
  workflow_id: Optional[str] = Field(description="message workflow identifier")
@@ -98,7 +96,6 @@ def _format_timestamp(timestamp: Optional[datetime]) -> str:
98
96
 
99
97
 
100
98
  def create_tracking_response(message: Message, model_version: int = 1) -> Union[TrackingV1, TrackingV2]:
101
-
102
99
  error_event = message.error_event
103
100
 
104
101
  successful = bool(message.message_type == MessageType.DATA and not error_event)
@@ -123,7 +120,6 @@ def create_tracking_response(message: Message, model_version: int = 1) -> Union[
123
120
  status_timestamp_string = _format_timestamp(status_timestamp)
124
121
 
125
122
  if model_version < 2:
126
-
127
123
  return TrackingV1(
128
124
  checksum=message.metadata.checksum or _EMPTY,
129
125
  chunkCount=message.total_chunks,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mesh-sandbox
3
- Version: 1.0.10
3
+ Version: 1.0.12
4
4
  Summary: NHSDigital mesh sandbox, a locally testable version of the MESH api
5
5
  License: MIT
6
6
  Author: spinecore
@@ -10,12 +10,12 @@ Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Programming Language :: Python :: 3.9
11
11
  Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
- Requires-Dist: cryptography (>=39.0.1,<42.0.0)
14
- Requires-Dist: fastapi (>=0.94,<0.101)
15
- Requires-Dist: gunicorn (>=20.1.0,<21.0.0)
13
+ Requires-Dist: cryptography (>=41.0.4,<42.0.0)
14
+ Requires-Dist: fastapi (>=0.103.1,<0.104.0)
15
+ Requires-Dist: gunicorn (>=21.2.0,<22.0.0)
16
16
  Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)
17
17
  Requires-Dist: types-python-dateutil (>=2.8.9,<3.0.0)
18
- Requires-Dist: uvicorn (>=0.21,<0.23)
18
+ Requires-Dist: uvicorn (>=0.23.2,<0.24.0)
19
19
  Description-Content-Type: text/markdown
20
20
 
21
21
  MESH Sandbox
@@ -51,57 +51,32 @@ services:
51
51
  build:
52
52
  context: https://github.com/NHSDigital/mesh-sandbox.git#refs/tags/v1.0.4
53
53
  ports:
54
- - "8700:80"
54
+ - "8700:443"
55
55
  deploy:
56
56
  restart_policy:
57
57
  condition: on-failure
58
58
  max_attempts: 3
59
59
  healthcheck:
60
- test: curl -sf http://localhost:80/health || exit 1
60
+ test: curl -ksf https://localhost/health || exit 1
61
61
  interval: 3s
62
62
  timeout: 10s
63
63
  environment:
64
64
  - SHARED_KEY=TestKey
65
+ - SSL=yes
66
+ # - STORE_MODE=file # store mode file will persist data to disk
65
67
  volumes:
66
68
  # mount a different mailboxes.jsonl to pre created mailboxes
67
69
  - ./src/mesh_sandbox/store/data/mailboxes.jsonl:/app/mesh_sandbox/store/data/mailboxes.jsonl:ro
68
- # the mesh sandbox supports injecting a plugin to support test hooks
69
- # - ./my_test_plugin.py:/app/mesh_sandbox/plugin/my_test_plygin.py:ro
70
+ - ./src/mesh_sandbox/test_plugin:/app/mesh_sandbox/plugins:ro
71
+ # you can mount a directory if you want access the stored messages
72
+ # - ./messages:/tmp/mesh_store
73
+ # you can also mount different server cert and key if using ssl and you need a trusted certificate
74
+ # - ./mycert.pem:/tmp/server-cert.pem:ro
75
+ # - ./mycert.key:/tmp/server-cert.key:ro
70
76
 
71
77
  ```
72
78
 
73
79
  Guidance for contributors
74
80
  -------------------------
75
-
76
- this project uses
77
-
78
- - python 3.9
79
- - java coretto11
80
- - poetry > 1.2
81
-
82
- Setup
83
- -----
84
-
85
- using asdf
86
- [install asdf](https://asdf-vm.com/guide/getting-started.html#_3-install-asdf)
87
-
88
- get the required plugins
89
-
90
- ```bash
91
- asdf plugin add python
92
- asdf plugin add java
93
- asdf plugin add poetry
94
- ```
95
-
96
- install the tools
97
-
98
- ```bash
99
- asdf install
100
- ```
101
-
102
- install the dependencies
103
-
104
- ```bash
105
- make install
106
- ```
81
+ [contributing](CONTRIBUTING.md)
107
82