mesh-sandbox 1.0.5__py3-none-any.whl → 1.0.6__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.
mesh_sandbox/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "1.0.5"
1
+ __version__ = "1.0.6"
@@ -5,6 +5,7 @@ from fastapi import BackgroundTasks, Depends, HTTPException, status
5
5
 
6
6
  from ..common.messaging import Messaging
7
7
  from ..dependencies import get_messaging
8
+ from ..models.mailbox import Mailbox
8
9
  from ..models.message import (
9
10
  Message,
10
11
  MessageEvent,
@@ -13,7 +14,7 @@ from ..models.message import (
13
14
  MessageStatus,
14
15
  MessageType,
15
16
  )
16
- from ..views.admin import AddMessageEventRequest, CreateReportRequest
17
+ from ..views.admin import AddMessageEventRequest, CreateReportRequest, MailboxDetails
17
18
 
18
19
 
19
20
  class AdminHandler:
@@ -106,3 +107,10 @@ class AdminHandler:
106
107
  message = await self.messaging.add_message_event(message, event, background_tasks)
107
108
 
108
109
  return message
110
+
111
+ async def get_mailbox_details(self, mailbox_id: str) -> MailboxDetails:
112
+ mailbox: Optional[Mailbox] = await self.messaging.get_mailbox(mailbox_id)
113
+ if not mailbox:
114
+ raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
115
+
116
+ return MailboxDetails.from_mailbox(mailbox)
@@ -13,6 +13,7 @@ class Mailbox:
13
13
  org_code: str = field(default="")
14
14
  org_name: str = field(default="")
15
15
  password: str = field(default="")
16
+ active: bool = field(default=True)
16
17
 
17
18
  _last_accessed: Optional[datetime] = None
18
19
  _inbox_count: Optional[int] = None
@@ -1,4 +1,4 @@
1
- from fastapi import APIRouter, BackgroundTasks, Depends, Response, status
1
+ from fastapi import APIRouter, BackgroundTasks, Depends, Path, Response, status
2
2
 
3
3
  from ..dependencies import (
4
4
  EnvConfig,
@@ -7,7 +7,7 @@ from ..dependencies import (
7
7
  normalise_message_id_path,
8
8
  )
9
9
  from ..handlers.admin import AdminHandler
10
- from ..views.admin import AddMessageEventRequest, CreateReportRequest
10
+ from ..views.admin import AddMessageEventRequest, CreateReportRequest, MailboxDetails
11
11
  from .request_logging import RequestLoggingRoute
12
12
 
13
13
  router = APIRouter(
@@ -42,7 +42,7 @@ async def ping(config: EnvConfig = Depends(get_env_config)):
42
42
  response_model_exclude_none=True,
43
43
  )
44
44
  @router.delete(
45
- "/messageexchange/reset",
45
+ "/messageexchange/admin/reset",
46
46
  status_code=status.HTTP_200_OK,
47
47
  include_in_schema=False,
48
48
  response_model_exclude_none=True,
@@ -61,7 +61,7 @@ async def reset(
61
61
  response_model_exclude_none=True,
62
62
  )
63
63
  @router.delete(
64
- "/messageexchange/reset/{mailbox_id}",
64
+ "/messageexchange/admin/reset/{mailbox_id}",
65
65
  status_code=status.HTTP_200_OK,
66
66
  include_in_schema=False,
67
67
  response_model_exclude_none=True,
@@ -75,7 +75,7 @@ async def reset_mailbox(
75
75
 
76
76
 
77
77
  @router.post(
78
- "/messageexchange/report",
78
+ "/messageexchange/admin/report",
79
79
  summary=f"Put a report messages into a particular inbox. {TESTING_ONLY}",
80
80
  status_code=status.HTTP_200_OK,
81
81
  response_model_exclude_none=True,
@@ -96,7 +96,7 @@ async def create_report(
96
96
  response_model_exclude_none=True,
97
97
  )
98
98
  @router.post(
99
- "/messageexchange/message/{message_id}/event",
99
+ "/messageexchange/admin/message/{message_id}/event",
100
100
  summary=f"appends a status event to a given message, if exists. {TESTING_ONLY}",
101
101
  status_code=status.HTTP_200_OK,
102
102
  response_model_exclude_none=True,
@@ -109,3 +109,23 @@ async def add_message_event(
109
109
  ):
110
110
  await handler.add_message_event(message_id, new_event, background_tasks)
111
111
  return Response()
112
+
113
+
114
+ @router.get(
115
+ "/admin/mailbox/{mailbox_id}",
116
+ summary=f"Get mailbox details. {TESTING_ONLY}",
117
+ status_code=status.HTTP_200_OK,
118
+ response_model_exclude_none=True,
119
+ )
120
+ @router.get(
121
+ "/messageexchange/admin/mailbox/{mailbox_id}",
122
+ summary=f"Get mailbox details. {TESTING_ONLY}",
123
+ status_code=status.HTTP_200_OK,
124
+ response_model_exclude_none=True,
125
+ )
126
+ async def get_mailbox_details(
127
+ mailbox_id: str = Path(..., title="mailbox_id", description="The Mailbox ID of the mailbox to retrieve"),
128
+ handler: AdminHandler = Depends(AdminHandler),
129
+ ) -> MailboxDetails:
130
+ mailbox = await handler.get_mailbox_details(mailbox_id)
131
+ return mailbox
@@ -25,7 +25,7 @@ def test_reset_canned_store_should_return_bad_request(app: TestClient):
25
25
 
26
26
  with temp_env_vars(STORE_MODE="canned"):
27
27
 
28
- res = app.delete("/messageexchange/reset")
28
+ res = app.delete("/messageexchange/admin/reset")
29
29
  assert res.status_code == status.HTTP_405_METHOD_NOT_ALLOWED
30
30
 
31
31
 
@@ -33,7 +33,7 @@ def test_reset_canned_store_with_valid_mailbox_id_should_return_bad_request(app:
33
33
 
34
34
  with temp_env_vars(STORE_MODE="canned"):
35
35
 
36
- res = app.delete(f"/messageexchange/reset/{_CANNED_MAILBOX1}")
36
+ res = app.delete(f"/messageexchange/admin/reset/{_CANNED_MAILBOX1}")
37
37
  assert res.status_code == status.HTTP_405_METHOD_NOT_ALLOWED
38
38
 
39
39
 
@@ -41,7 +41,7 @@ def test_reset_memory_store_with_invalid_mailbox_id_should_return_bad_request(ap
41
41
 
42
42
  with temp_env_vars(STORE_MODE="memory"):
43
43
 
44
- res = app.delete(f"/messageexchange/reset/{uuid4().hex}")
44
+ res = app.delete(f"/messageexchange/admin/reset/{uuid4().hex}")
45
45
  assert res.status_code == status.HTTP_404_NOT_FOUND
46
46
 
47
47
 
@@ -49,7 +49,7 @@ def test_reset_file_store_with_invalid_mailbox_id_should_return_bad_request(app:
49
49
 
50
50
  with temp_env_vars(STORE_MODE="file"):
51
51
 
52
- res = app.delete(f"/messageexchange/reset/{uuid4().hex}")
52
+ res = app.delete(f"/messageexchange/admin/reset/{uuid4().hex}")
53
53
  assert res.status_code == status.HTTP_404_NOT_FOUND
54
54
 
55
55
 
@@ -63,7 +63,7 @@ def test_reset_memory_store_should_clear_all_mailboxes(app: TestClient):
63
63
  msg_2to1_id = mesh_api_send_message_and_return_message_id(app, _CANNED_MAILBOX2, _CANNED_MAILBOX1)
64
64
  assert mesh_api_get_inbox_size(app, _CANNED_MAILBOX1) == 1
65
65
 
66
- res = app.delete("/messageexchange/reset")
66
+ res = app.delete("/messageexchange/admin/reset")
67
67
  assert res.status_code == status.HTTP_200_OK
68
68
 
69
69
  assert mesh_api_get_inbox_size(app, _CANNED_MAILBOX1) == 0
@@ -114,7 +114,7 @@ def test_reset_memory_store_should_clear_specified_mailbox_only(app: TestClient)
114
114
  assert len(messages) == 1
115
115
 
116
116
  # RESET mailbox 2
117
- res = app.delete(f"/messageexchange/reset/{_CANNED_MAILBOX2}")
117
+ res = app.delete(f"/messageexchange/admin/reset/{_CANNED_MAILBOX2}")
118
118
  assert res.status_code == status.HTTP_200_OK
119
119
 
120
120
  assert mesh_api_get_inbox_size(app, _CANNED_MAILBOX1) == 1
@@ -170,7 +170,7 @@ def test_reset_file_store_should_clear_all_mailboxes_and_maybe_files(app: TestCl
170
170
  shutil.rmtree(inbox_folder1)
171
171
  shutil.rmtree(inbox_folder2)
172
172
 
173
- res = app.delete("/messageexchange/reset")
173
+ res = app.delete("/messageexchange/admin/reset")
174
174
  assert res.status_code == status.HTTP_200_OK
175
175
 
176
176
  assert mesh_api_get_inbox_size(app, _CANNED_MAILBOX1) == 0
@@ -210,7 +210,7 @@ def test_reset_file_store_should_clear_specified_mailbox_only_and_maybe_files(ap
210
210
  assert len(messages) == 1
211
211
  assert messages[0] == msg_1to2_id
212
212
 
213
- res = app.delete(f"/messageexchange/reset/{_CANNED_MAILBOX2}")
213
+ res = app.delete(f"/messageexchange/admin/reset/{_CANNED_MAILBOX2}")
214
214
  assert res.status_code == status.HTTP_200_OK
215
215
 
216
216
  assert mesh_api_get_inbox_size(app, _CANNED_MAILBOX1) == 1
@@ -231,7 +231,7 @@ def test_reset_file_store_should_not_error_if_folder_does_not_exist_yet(
231
231
  assert not os.path.exists(inbox_folder)
232
232
 
233
233
  clear_disk_param = "" if clear_disk is None else f"?clear_disk={clear_disk}"
234
- res = app.delete(f"/messageexchange/reset/{_CANNED_MAILBOX2}{clear_disk_param}")
234
+ res = app.delete(f"/messageexchange/admin/reset/{_CANNED_MAILBOX2}{clear_disk_param}")
235
235
  assert res.status_code == status.HTTP_200_OK
236
236
 
237
237
 
@@ -253,7 +253,7 @@ def test_put_report_in_inbox(app: TestClient, tmp_path: str):
253
253
  linked_message_id=uuid4().hex,
254
254
  )
255
255
 
256
- res = app.post("/messageexchange/report", json=request.dict())
256
+ res = app.post("/messageexchange/admin/report", json=request.dict())
257
257
  assert res.status_code == status.HTTP_200_OK
258
258
 
259
259
  result = res.json()
@@ -318,7 +318,7 @@ def test_add_message_event(app: TestClient, tmp_path: str):
318
318
  linked_message_id=uuid4().hex,
319
319
  )
320
320
 
321
- res = app.post("/messageexchange/report", json=create_report_request.dict())
321
+ res = app.post("/messageexchange/admin/report", json=create_report_request.dict())
322
322
  assert res.status_code == status.HTTP_200_OK
323
323
 
324
324
  result = res.json()
@@ -350,7 +350,7 @@ def test_add_message_event(app: TestClient, tmp_path: str):
350
350
  # move the message to accepted again
351
351
  add_event_request = AddMessageEventRequest(status=MessageStatus.ACCEPTED)
352
352
 
353
- res = app.post(f"/messageexchange/message/{message_id}/event", json=add_event_request.dict())
353
+ res = app.post(f"/messageexchange/admin/message/{message_id}/event", json=add_event_request.dict())
354
354
  assert res.status_code == status.HTTP_200_OK
355
355
 
356
356
  res = app.get(
@@ -359,3 +359,32 @@ def test_add_message_event(app: TestClient, tmp_path: str):
359
359
  )
360
360
  messages = res.json().get("messages", [])
361
361
  assert messages == [message_id]
362
+
363
+
364
+ @pytest.mark.parametrize("root_path", ["/admin/mailbox", "/messageexchange/admin/mailbox"])
365
+ def test_get_mailbox_invalid_mailbox_returns_404(app: TestClient, root_path: str):
366
+
367
+ with temp_env_vars(STORE_MODE="canned"):
368
+
369
+ res = app.get(f"{root_path}/NotAMailboxId")
370
+ assert res.status_code == status.HTTP_404_NOT_FOUND
371
+
372
+
373
+ @pytest.mark.parametrize("root_path", ["/admin/mailbox", "/messageexchange/admin/mailbox"])
374
+ def test_get_mailbox_happy_path(app: TestClient, root_path: str):
375
+
376
+ with temp_env_vars(STORE_MODE="canned"):
377
+
378
+ res = app.get(f"{root_path}/{_CANNED_MAILBOX1}")
379
+ assert res.status_code == status.HTTP_200_OK
380
+
381
+ get_mailbox = res.json()
382
+ assert len(get_mailbox) == 7
383
+
384
+ assert get_mailbox["mailbox_id"] == _CANNED_MAILBOX1
385
+ assert get_mailbox["mailbox_name"] == "TESTMB1"
386
+ assert get_mailbox["billing_entity"] == "England"
387
+ assert get_mailbox["ods_code"] == "X26"
388
+ assert get_mailbox["org_code"] == "X26"
389
+ assert get_mailbox["org_name"] == ""
390
+ assert get_mailbox["active"] is True
@@ -1,7 +1,10 @@
1
+ from __future__ import annotations
2
+
1
3
  from typing import Optional
2
4
 
3
5
  from pydantic import BaseModel, Field # pylint: disable=no-name-in-module
4
6
 
7
+ from mesh_sandbox.models.mailbox import Mailbox
5
8
  from mesh_sandbox.models.message import MessageStatus
6
9
 
7
10
 
@@ -23,3 +26,25 @@ class AddMessageEventRequest(BaseModel):
23
26
  event: str = Field(description="error event (SEND/TRANSFER) etc)", default=None)
24
27
  description: str = Field(description="error description", default=None)
25
28
  linked_message_id: Optional[str] = Field(description="linked message id", default=None)
29
+
30
+
31
+ class MailboxDetails(BaseModel):
32
+ mailbox_id: str = Field(description="mailbox id")
33
+ mailbox_name: str = Field(description="mailbox name")
34
+ billing_entity: Optional[str] = Field(default=None, description="billing entity")
35
+ ods_code: str = Field(default="", description="ODS code")
36
+ org_code: str = Field(default="", description="Organisation code")
37
+ org_name: str = Field(default="", description="Organisation name")
38
+ active: bool = Field(default=True, description="Mailbox active flag")
39
+
40
+ @classmethod
41
+ def from_mailbox(cls, mailbox: Mailbox) -> MailboxDetails:
42
+ return cls(
43
+ mailbox_id=mailbox.mailbox_id,
44
+ mailbox_name=mailbox.mailbox_name,
45
+ billing_entity=mailbox.billing_entity,
46
+ ods_code=mailbox.ods_code,
47
+ org_code=mailbox.org_code,
48
+ org_name=mailbox.org_name,
49
+ active=mailbox.active,
50
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mesh-sandbox
3
- Version: 1.0.5
3
+ Version: 1.0.6
4
4
  Summary: NHSDigital mesh sandbox, a locally testable version of the MESH api
5
5
  License: MIT
6
6
  Author: spinecore
@@ -1,4 +1,4 @@
1
- mesh_sandbox/__init__.py,sha256=B9kKWJLln1i8LjtkcYecvNWGLTrez4gCUOHtnPlInFo,22
1
+ mesh_sandbox/__init__.py,sha256=mqMuQB3aqJVPrHHqJMLjqiMKUiJjozc7EPLcX5DpKHg,22
2
2
  mesh_sandbox/api.py,sha256=F2KUKENAsSe6NAGG0wzHA2jebGF6mWFgta1q55oqacU,3925
3
3
  mesh_sandbox/common/__init__.py,sha256=MwKS4FixADUGgN49MQJI7vW0Wx6mnf9SBOPbgE4RddM,3403
4
4
  mesh_sandbox/common/constants.py,sha256=_hnaHDkAQGHWLF7n_WfC5ZHIY5D-fUbOdpSqLusUMNY,6504
@@ -10,19 +10,19 @@ mesh_sandbox/common/mex_headers.py,sha256=Eu-ixdVml2obROXggYyUyiS4QZHUA1JUgF7gO4
10
10
  mesh_sandbox/conftest.py,sha256=IXrb8Y8Hi4-0ZxDNfTDFI0L1uG1Iz9FBQdNBZtPMsEw,2233
11
11
  mesh_sandbox/dependencies.py,sha256=Crl7yEUED-XYl_odMenpvMJoYeIVDROWfvcrfvV85fc,4089
12
12
  mesh_sandbox/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- mesh_sandbox/handlers/admin.py,sha256=JwPqeN3LHpau0pk7QOEFVrKZ9DV_896j0L_eSZxHIX4,3783
13
+ mesh_sandbox/handlers/admin.py,sha256=5-vdKhx-zDyzu9r0VsXtZucfK0K8bYlBibyj5xYHkEc,4143
14
14
  mesh_sandbox/handlers/handshake.py,sha256=p3_NveSscNBgCdIIJhBza34b0WreqgBxZwI2sw7ZMTk,605
15
15
  mesh_sandbox/handlers/inbox.py,sha256=J20JUX1dHlS2We2UIDQa1MMoVN_QsRoP0tC-3zKAlD8,15450
16
16
  mesh_sandbox/handlers/lookup.py,sha256=p_xmnCJi6BoNqRaQjRAGeQthL5EohQfZ_LA1h0QU36Q,1392
17
17
  mesh_sandbox/handlers/outbox.py,sha256=XrLOGhw0QqMTfMFevrh-_Z-EyFSEAQLO1BcmbL1bR0Y,10045
18
18
  mesh_sandbox/handlers/tracking.py,sha256=nmn5JexFhAvzFmj9C5l0w4sq8sNz3x-mMd3CsGVrEM4,2356
19
19
  mesh_sandbox/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- mesh_sandbox/models/mailbox.py,sha256=W1b1R1XjhyiCp30LvTLtQVlxagfxXH8eb0XnNj3D4Dw,993
20
+ mesh_sandbox/models/mailbox.py,sha256=58R6TyH8Qn3k_V3XzWIf5vAseGCmXqQQWFJ8-Tyv2yg,1032
21
21
  mesh_sandbox/models/message.py,sha256=ze-IPbCg6XlKZtOL1RWQvMnu04AzrGppwdk2mTyVAfU,4926
22
22
  mesh_sandbox/models/workflow.py,sha256=T8A1Q729TOUaz1MOa1Ly8oZs_G4769xMZpTYGF0TlO8,518
23
23
  mesh_sandbox/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  mesh_sandbox/routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
- mesh_sandbox/routers/admin.py,sha256=pJ9rPF-JDWs1dbVbQVqW8uKQrX3yh4oUxswBOnO5zR8,3852
25
+ mesh_sandbox/routers/admin.py,sha256=ZMa6LfdUidHXkNMTtHsWnRvGYAoJ-ac0BKWYbA1AeFY,4560
26
26
  mesh_sandbox/routers/handshake.py,sha256=5TVyQ5OrHIe6W3UVpbap-hc5ia669Of6w6F1vgcYjm4,2693
27
27
  mesh_sandbox/routers/inbox.py,sha256=EkOmL9pxE6pYPBTzGU1CZJLu80ZR2EnKg9fe7DDMLLQ,8898
28
28
  mesh_sandbox/routers/inbox_count.py,sha256=hY88h7dBa6asnvYEP9mmx6CEBw5ZyRO7gz6lHg4Yj3c,1521
@@ -50,7 +50,7 @@ mesh_sandbox/test_plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
50
50
  mesh_sandbox/test_plugin/example_plugin.py,sha256=MnNpyyWKziqvOr89LeIxOwqskwHcrSsh_te67SeNJr4,967
51
51
  mesh_sandbox/test_plugin/example_plugin.txt,sha256=aUePU6UUVhpxeP37Pdz5Zxyn_nxI6HCY3qtQBo1iUEI,24
52
52
  mesh_sandbox/tests/__init__.py,sha256=wPjH0Ka1334a0OR9VMUfeYxsr03JqWjHTBnAH_1SB7I,106
53
- mesh_sandbox/tests/admin.py,sha256=Y_nzBhqSGPCTjG3EczSHClA-mVALGNBd-iOShoYh8WU,14549
53
+ mesh_sandbox/tests/admin.py,sha256=yVD3LRWaLzQMzXysu2GKrO1ZSmwjdIhiVCpCo6xb4oQ,15707
54
54
  mesh_sandbox/tests/docker_tests.py,sha256=-dLCnAdgZkpU6tkgO4FwO7Sjvt5zZe45ewBSXo5afT0,1598
55
55
  mesh_sandbox/tests/exceptions.py,sha256=j_jKskVzLAYpyu4qNAEY5ahkbk8Uh2Nc_CGpnpdXjnI,740
56
56
  mesh_sandbox/tests/handshake.py,sha256=X-fCbwaEAc8cAvvnniCvt4W4DAV9ItPq7tpIpZkfj6M,6259
@@ -64,13 +64,13 @@ mesh_sandbox/tests/messaging_tests.py,sha256=Bup6aJsiJ0xdtg0Ab37ME0VHI6HFJA-0ATm
64
64
  mesh_sandbox/tests/outbox.py,sha256=AbQR8vgRy8KAG0RMCU0jYFUXSCPQMrLRJMJTU3PGQhI,20061
65
65
  mesh_sandbox/tests/serialisation.py,sha256=kRSMZLDHlX6oRK6c2OCZL0XQoUCKQxqcYXrJWbc9VkA,663
66
66
  mesh_sandbox/views/__init__.py,sha256=nZkb6_1S8jz8Xl_AayfwjgEZG0JD2dfulfGxjJ5W9Ec,1237
67
- mesh_sandbox/views/admin.py,sha256=2YGslfDyC0QKoq3WTGXBicqrOMR9UmQYocP3R0qTbAY,1315
67
+ mesh_sandbox/views/admin.py,sha256=gisfIpNezpnabbs-0jXDLGTdzetq8Age6KsK8dxOkCQ,2314
68
68
  mesh_sandbox/views/error.py,sha256=9lnUr3P93Vm-nOrBTEuAD6nrSBUvpI6-XqXzILWjgGk,3885
69
69
  mesh_sandbox/views/inbox.py,sha256=gnaD9Csx5BqilVRefQQ_tXmeq80lwcLJfepW005GrkU,5662
70
70
  mesh_sandbox/views/lookup.py,sha256=HHUqZ-Iy22ysC3qaO8Bl5GBQqf_7IiBbe5acyxqS78M,2775
71
71
  mesh_sandbox/views/outbox.py,sha256=jxYiHylEdpljZ6Wl45Ke3aaH5rEKb-kzUuCNEKDS3So,4932
72
72
  mesh_sandbox/views/tracking.py,sha256=1H7Ghcvqkmx__KS1Y-lm105EVx_Z1eJo3oMDh8pzRMQ,8918
73
- mesh_sandbox-1.0.5.dist-info/LICENSE,sha256=usgzIvDUpVX5pYZepJTRXQJqIaz0mdd32GuS5a3PFlY,1051
74
- mesh_sandbox-1.0.5.dist-info/METADATA,sha256=yP1kTIaacLRi87NEWBDfZKAM_dENdkCnBobL57T2QWE,2388
75
- mesh_sandbox-1.0.5.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
76
- mesh_sandbox-1.0.5.dist-info/RECORD,,
73
+ mesh_sandbox-1.0.6.dist-info/LICENSE,sha256=usgzIvDUpVX5pYZepJTRXQJqIaz0mdd32GuS5a3PFlY,1051
74
+ mesh_sandbox-1.0.6.dist-info/METADATA,sha256=ZkSLOqdSsSUAond5nH90Bqz2X_EFaGnd8Ahp83igHlk,2388
75
+ mesh_sandbox-1.0.6.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
76
+ mesh_sandbox-1.0.6.dist-info/RECORD,,