nucliadb 6.3.1.post3590__py3-none-any.whl → 6.3.1.post3598__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.
@@ -170,7 +170,7 @@ async def backup_resource_with_binaries(
170
170
  """
171
171
  nonlocal total_size
172
172
 
173
- for cloud_file in get_cloud_files(bm):
173
+ for index, cloud_file in enumerate(get_cloud_files(bm)):
174
174
  if not await exists_cf(context, cloud_file):
175
175
  logger.warning(
176
176
  "Cloud file not found in storage, skipping",
@@ -184,13 +184,13 @@ async def backup_resource_with_binaries(
184
184
  yield serialized_cf
185
185
 
186
186
  async for chunk in to_tar(
187
- name=f"cloud-files/{cloud_file.uri}", size=len(serialized_cf), chunks=cf_iterator()
187
+ name=f"cloud-files/{index}", size=len(serialized_cf), chunks=cf_iterator()
188
188
  ):
189
189
  yield chunk
190
190
  total_size += len(chunk)
191
191
 
192
192
  async for chunk in to_tar(
193
- name=f"binaries/{cloud_file.uri}",
193
+ name=f"binaries/{index}",
194
194
  size=cloud_file.size,
195
195
  chunks=download_binary(context, cloud_file),
196
196
  ):
@@ -31,7 +31,7 @@ from nucliadb.backups.settings import settings
31
31
  from nucliadb.common.context import ApplicationContext
32
32
  from nucliadb.export_import.utils import (
33
33
  import_binary,
34
- import_broker_message,
34
+ restore_broker_message,
35
35
  set_entities_groups,
36
36
  set_labels,
37
37
  )
@@ -69,11 +69,11 @@ async def restore_kb(context: ApplicationContext, kbid: str, backup_id: str):
69
69
  await restore_resources(context, kbid, backup_id)
70
70
  await restore_labels(context, kbid, backup_id)
71
71
  await restore_entities(context, kbid, backup_id)
72
- await delete_last_restored_resource_key(context, kbid, backup_id)
72
+ await delete_last_restored(context, kbid, backup_id)
73
73
 
74
74
 
75
75
  async def restore_resources(context: ApplicationContext, kbid: str, backup_id: str):
76
- last_restored = await get_last_restored_resource_key(context, kbid, backup_id)
76
+ last_restored = await get_last_restored(context, kbid, backup_id)
77
77
  tasks = []
78
78
  async for object_info in context.blob_storage.iterate_objects(
79
79
  bucket=settings.backups_bucket,
@@ -81,21 +81,19 @@ async def restore_resources(context: ApplicationContext, kbid: str, backup_id: s
81
81
  start=last_restored,
82
82
  ):
83
83
  key = object_info.name
84
- resource_id = key.split("/")[-1].rstrip(".tar")
84
+ resource_id = key.split("/")[-1].split(".tar")[0]
85
85
  tasks.append(asyncio.create_task(restore_resource(context, kbid, backup_id, resource_id)))
86
86
  if len(tasks) > settings.restore_resources_concurrency:
87
87
  await asyncio.gather(*tasks)
88
88
  tasks = []
89
- await set_last_restored_resource_key(context, kbid, backup_id, key)
89
+ await set_last_restored(context, kbid, backup_id, key)
90
90
  if len(tasks) > 0:
91
91
  await asyncio.gather(*tasks)
92
92
  tasks = []
93
- await set_last_restored_resource_key(context, kbid, backup_id, key)
93
+ await set_last_restored(context, kbid, backup_id, key)
94
94
 
95
95
 
96
- async def get_last_restored_resource_key(
97
- context: ApplicationContext, kbid: str, backup_id: str
98
- ) -> Optional[str]:
96
+ async def get_last_restored(context: ApplicationContext, kbid: str, backup_id: str) -> Optional[str]:
99
97
  key = MaindbKeys.LAST_RESTORED.format(kbid=kbid, backup_id=backup_id)
100
98
  async with context.kv_driver.transaction(read_only=True) as txn:
101
99
  raw = await txn.get(key)
@@ -104,16 +102,14 @@ async def get_last_restored_resource_key(
104
102
  return raw.decode()
105
103
 
106
104
 
107
- async def set_last_restored_resource_key(
108
- context: ApplicationContext, kbid: str, backup_id: str, resource_id: str
109
- ):
105
+ async def set_last_restored(context: ApplicationContext, kbid: str, backup_id: str, resource_id: str):
110
106
  key = MaindbKeys.LAST_RESTORED.format(kbid=kbid, backup_id=backup_id)
111
107
  async with context.kv_driver.transaction() as txn:
112
108
  await txn.set(key, resource_id.encode())
113
109
  await txn.commit()
114
110
 
115
111
 
116
- async def delete_last_restored_resource_key(context: ApplicationContext, kbid: str, backup_id: str):
112
+ async def delete_last_restored(context: ApplicationContext, kbid: str, backup_id: str):
117
113
  key = MaindbKeys.LAST_RESTORED.format(kbid=kbid, backup_id=backup_id)
118
114
  async with context.kv_driver.transaction() as txn:
119
115
  await txn.delete(key)
@@ -134,6 +130,7 @@ class ResourceBackupReader:
134
130
  def __init__(self, download_stream: AsyncIterator[bytes]):
135
131
  self.download_stream = download_stream
136
132
  self.buffer = b""
133
+ self.cloud_files: dict[int, CloudFile] = {}
137
134
 
138
135
  async def read(self, size: int) -> bytes:
139
136
  while len(self.buffer) < size:
@@ -194,15 +191,18 @@ class ResourceBackupReader:
194
191
  bm.ParseFromString(raw_bm)
195
192
  return bm
196
193
  elif tarinfo.name.startswith("cloud-files"):
194
+ cf_index = int(tarinfo.name.split("cloud-files/")[-1])
197
195
  raw_cf = await self.read_data(tarinfo)
198
196
  cf = CloudFile()
199
197
  cf.ParseFromString(raw_cf)
198
+ self.cloud_files[cf_index] = cf
200
199
  return cf
201
200
  elif tarinfo.name.startswith("binaries"):
202
- uri = tarinfo.name.lstrip("binaries/")
201
+ bin_index = int(tarinfo.name.split("binaries/")[-1])
203
202
  size = tarinfo.size
204
203
  download_stream = functools.partial(self.iter_data, size)
205
- return CloudFileBinary(uri, download_stream)
204
+ cf = self.cloud_files[bin_index]
205
+ return CloudFileBinary(cf.uri, download_stream)
206
206
  else: # pragma: no cover
207
207
  raise ValueError(f"Unknown tar entry: {tarinfo.name}")
208
208
 
@@ -235,8 +235,8 @@ async def restore_resource(context: ApplicationContext, kbid: str, backup_id: st
235
235
  extra={"item_type": type(item), kbid: kbid, resource_id: resource_id},
236
236
  )
237
237
  continue
238
-
239
- await import_broker_message(context, kbid, bm)
238
+ if bm is not None:
239
+ await restore_broker_message(context, kbid, bm)
240
240
 
241
241
 
242
242
  async def restore_labels(context: ApplicationContext, kbid: str, backup_id: str):
@@ -39,6 +39,7 @@ from nucliadb_protos import knowledgebox_pb2 as kb_pb2
39
39
  from nucliadb_protos import resources_pb2, writer_pb2
40
40
  from nucliadb_utils.const import Streams
41
41
  from nucliadb_utils.transaction import MaxTransactionSizeExceededError
42
+ from nucliadb_utils.utilities import get_ingest
42
43
 
43
44
  BinaryStream = AsyncIterator[bytes]
44
45
  BinaryStreamGenerator = Callable[[int], BinaryStream]
@@ -72,6 +73,24 @@ async def import_broker_message(
72
73
  await transaction_commit(context, pb, partition)
73
74
 
74
75
 
76
+ async def restore_broker_message(
77
+ context: ApplicationContext, kbid: str, bm: writer_pb2.BrokerMessage
78
+ ) -> None:
79
+ bm.kbid = kbid
80
+
81
+ # First, ingest the broker message writer part synchronously
82
+ async def ingest_request_stream() -> AsyncIterator[writer_pb2.BrokerMessage]:
83
+ yield get_writer_bm(bm)
84
+
85
+ response = await get_ingest().ProcessMessage(ingest_request_stream()) # type: ignore
86
+ assert response.status == writer_pb2.OpStatusWriter.Status.OK, "Failed to process broker message"
87
+
88
+ # Then enqueue the processor part asynchronously
89
+ processor_bm = get_processor_bm(bm)
90
+ partition = context.partitioning.generate_partition(kbid, bm.uuid)
91
+ await transaction_commit(context, processor_bm, partition)
92
+
93
+
75
94
  async def transaction_commit(
76
95
  context: ApplicationContext, bm: writer_pb2.BrokerMessage, partition: int
77
96
  ) -> None:
@@ -202,9 +202,9 @@ class WriterServicer(writer_pb2_grpc.WriterServicer):
202
202
  return DeleteKnowledgeBoxResponse(status=KnowledgeBoxResponseStatus.ERROR)
203
203
  return DeleteKnowledgeBoxResponse(status=KnowledgeBoxResponseStatus.OK)
204
204
 
205
- async def ProcessMessage( # type: ignore
205
+ async def ProcessMessage(
206
206
  self, request_stream: AsyncIterator[BrokerMessage], context=None
207
- ):
207
+ ) -> OpStatusWriter:
208
208
  response = OpStatusWriter()
209
209
  async for message in request_stream:
210
210
  try:
@@ -22,6 +22,7 @@ from contextlib import asynccontextmanager
22
22
  from fastapi import FastAPI
23
23
 
24
24
  from nucliadb.common.cluster.utils import setup_cluster, teardown_cluster
25
+ from nucliadb.common.context.fastapi import inject_app_context
25
26
  from nucliadb.common.maindb.utils import setup_driver
26
27
  from nucliadb.common.nidx import start_nidx_utility
27
28
  from nucliadb.ingest.utils import start_ingest, stop_ingest
@@ -51,7 +52,8 @@ async def lifespan(app: FastAPI):
51
52
 
52
53
  await start_audit_utility(SERVICE_NAME)
53
54
 
54
- yield
55
+ async with inject_app_context(app):
56
+ yield
55
57
 
56
58
  await stop_ingest()
57
59
  if get_utility(Utility.PARTITION):
@@ -105,7 +105,7 @@ class NatsTaskConsumer(Generic[MsgType]):
105
105
 
106
106
  async def _subscription_worker_as_task(self, msg: Msg):
107
107
  seqid = int(msg.reply.split(".")[5])
108
- task_name = f"NatsTaskConsumer({self.name}, msg={seqid})"
108
+ task_name = f"NatsTaskConsumer({self.name}, stream={self.stream.name}, subject={self.consumer.subject}, seqid={seqid})"
109
109
  task = asyncio.create_task(self.subscription_worker(msg), name=task_name)
110
110
  task.add_done_callback(self._running_tasks_remove)
111
111
  self.running_tasks.append(task)
@@ -22,6 +22,7 @@ from contextlib import asynccontextmanager
22
22
 
23
23
  from fastapi import FastAPI
24
24
 
25
+ from nucliadb.common.context.fastapi import inject_app_context
25
26
  from nucliadb.common.nidx import start_nidx_utility, stop_nidx_utility
26
27
  from nucliadb.train import SERVICE_NAME
27
28
  from nucliadb.train.utils import (
@@ -42,7 +43,8 @@ async def lifespan(app: FastAPI):
42
43
  await start_train_grpc(SERVICE_NAME)
43
44
  await start_audit_utility(SERVICE_NAME)
44
45
 
45
- yield
46
+ async with inject_app_context(app):
47
+ yield
46
48
 
47
49
  await stop_audit_utility()
48
50
  await stop_train_grpc()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: nucliadb
3
- Version: 6.3.1.post3590
3
+ Version: 6.3.1.post3598
4
4
  Summary: NucliaDB
5
5
  Author-email: Nuclia <nucliadb@nuclia.com>
6
6
  License: AGPL
@@ -20,11 +20,11 @@ Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Programming Language :: Python :: 3 :: Only
21
21
  Requires-Python: <4,>=3.9
22
22
  Description-Content-Type: text/markdown
23
- Requires-Dist: nucliadb-telemetry[all]>=6.3.1.post3590
24
- Requires-Dist: nucliadb-utils[cache,fastapi,storages]>=6.3.1.post3590
25
- Requires-Dist: nucliadb-protos>=6.3.1.post3590
26
- Requires-Dist: nucliadb-models>=6.3.1.post3590
27
- Requires-Dist: nidx-protos>=6.3.1.post3590
23
+ Requires-Dist: nucliadb-telemetry[all]>=6.3.1.post3598
24
+ Requires-Dist: nucliadb-utils[cache,fastapi,storages]>=6.3.1.post3598
25
+ Requires-Dist: nucliadb-protos>=6.3.1.post3598
26
+ Requires-Dist: nucliadb-models>=6.3.1.post3598
27
+ Requires-Dist: nidx-protos>=6.3.1.post3598
28
28
  Requires-Dist: nucliadb-admin-assets>=1.0.0.post1224
29
29
  Requires-Dist: nuclia-models>=0.24.2
30
30
  Requires-Dist: uvicorn
@@ -41,10 +41,10 @@ nucliadb/openapi.py,sha256=wDiw0dVEvTpJvbatkJ0JZLkKm9RItZT5PWRHjqRfqTA,2272
41
41
  nucliadb/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
42
  nucliadb/backups/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
43
43
  nucliadb/backups/const.py,sha256=9vPAhLxQO_gNAjSdPxWuv3V66s9WcdpjOQ89CZlfmuk,1894
44
- nucliadb/backups/create.py,sha256=w6KpjkTOpIoPVrtOZrxB99oMdWp6jYkyIJ1-qo_k4Mw,11230
44
+ nucliadb/backups/create.py,sha256=x5Ezd1p8qqlcn-srbE_iFxTwEEjycKWhTezUIkXL-oo,11230
45
45
  nucliadb/backups/delete.py,sha256=1rnBhVUGYYZJXSZUrrgYMDZ5NyswEWkIA-G-crRCyHk,2404
46
46
  nucliadb/backups/models.py,sha256=-hITU4Mv6AxePu12toBu_fjpEv6vVGcwNVxV22O9jQA,1273
47
- nucliadb/backups/restore.py,sha256=wepEgv4vBN5yeiZU-f17PbuFV4xT4_SVKplNr8xSJrE,10001
47
+ nucliadb/backups/restore.py,sha256=YD3Bbo9ry4YLMM6imB-DXbOAMXfGxVzJtTAAUFDvB0I,10153
48
48
  nucliadb/backups/settings.py,sha256=SyzsInj1BRbBI0atg5IXWbMbOZ_eVg4eSQ3IcnUhCxQ,1357
49
49
  nucliadb/backups/tasks.py,sha256=4_kOVJ2yCwMvDEpzJgTuTt75TNlpq5woyw9sTAcaSkw,4194
50
50
  nucliadb/backups/utils.py,sha256=_Vogjqcru5oqNZM-bZ0q7Ju79Bv1PD-LVFEa7Z-Q13I,1261
@@ -109,7 +109,7 @@ nucliadb/export_import/exporter.py,sha256=k2QVx1EjqFlDYiggriWiEJzwtMXzHbldsqWdpG
109
109
  nucliadb/export_import/importer.py,sha256=v5cq9Nn8c2zrY_K_00mydR52f8mdFxR7tLdtNLQ0qvk,4229
110
110
  nucliadb/export_import/models.py,sha256=dbjScNkiMRv4X3Ktudy1JRliD25bfoDTy3JmEZgQSCc,2121
111
111
  nucliadb/export_import/tasks.py,sha256=DWbdqY97ffoyfipelGXz3Jqz1iam6JCjQSh367Fc3NA,2947
112
- nucliadb/export_import/utils.py,sha256=iAQAjYuNx0dhM2b5-1A0NEs8tSRsznuT-izysUrTwS0,19986
112
+ nucliadb/export_import/utils.py,sha256=DlGUHaqT43b3jG9U-vZ48GpC4O2OgD2WSP_0-hrYW9k,20774
113
113
  nucliadb/ingest/__init__.py,sha256=fsw3C38VP50km3R-nHL775LNGPpJ4JxqXJ2Ib1f5SqE,1011
114
114
  nucliadb/ingest/app.py,sha256=rX1KE5vsAzG9hlArBk8WE2SOlvdYylcb-jNkMQNPJdQ,7407
115
115
  nucliadb/ingest/partitions.py,sha256=2NIhMYbNT0TNBL6bX1UMSi7vxFGICstCKEqsB0TXHOE,2410
@@ -152,7 +152,7 @@ nucliadb/ingest/orm/processor/processor.py,sha256=wjZmfJumypdGoKVB0BEJ51ha3xNRs1
152
152
  nucliadb/ingest/orm/processor/sequence_manager.py,sha256=uqEphtI1Ir_yk9jRl2gPf7BlzzXWovbARY5MNZSBI_8,1704
153
153
  nucliadb/ingest/service/__init__.py,sha256=MME_G_ERxzJR6JW_hfE2qcfXpmpH1kdG-S0a-M0qRm8,2043
154
154
  nucliadb/ingest/service/exceptions.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
155
- nucliadb/ingest/service/writer.py,sha256=8oHJru1Yc8e05MXKmdQMbcNOzLHFFbWmHlJXIMjJcnY,22315
155
+ nucliadb/ingest/service/writer.py,sha256=duFp2EOA52Mkz8kJcV1apCDgsUmkwpwGuubVra5Aa7o,22317
156
156
  nucliadb/middleware/__init__.py,sha256=A8NBlBuEkunCFMKpR9gnfNELsVn0Plc55BIQMbWDM8Q,2202
157
157
  nucliadb/migrator/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
158
158
  nucliadb/migrator/command.py,sha256=dKbJ1tAmP6X4lMVRSSlz351euaqs2wBPpOczLjATUes,2089
@@ -188,7 +188,7 @@ nucliadb/reader/reader/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXM
188
188
  nucliadb/reader/reader/notifications.py,sha256=HVZNUlfbSuoZ9BsSs8wmzPeYurl0U0O2ooVlR9KSM3U,7792
189
189
  nucliadb/search/__init__.py,sha256=tnypbqcH4nBHbGpkINudhKgdLKpwXQCvDtPchUlsyY4,1511
190
190
  nucliadb/search/app.py,sha256=-WEX1AZRA8R_9aeOo9ovOTwjXW_7VfwWN7N2ccSoqXg,3387
191
- nucliadb/search/lifecycle.py,sha256=DW8v4WUi4rZqc7xTOi3rE67W7877WG7fH9oTZbolHdE,2099
191
+ nucliadb/search/lifecycle.py,sha256=V_Pj5PRP0yyDY8d5LytO4X8p9HhN7UomqRG6Ri0UaFA,2206
192
192
  nucliadb/search/openapi.py,sha256=t3Wo_4baTrfPftg2BHsyLWNZ1MYn7ZRdW7ht-wFOgRs,1016
193
193
  nucliadb/search/predict.py,sha256=z2-RkhMkH-5T6PtFkfESxNof07XiS5FxicLHPRyCUXc,22284
194
194
  nucliadb/search/predict_models.py,sha256=ZAe0dneUsPmV9uBar57cCFADCGOrYDsJHuqKlA5zWag,5937
@@ -272,7 +272,7 @@ nucliadb/standalone/static/favicon.ico,sha256=96pKGp6Sx457JkTfjy1dtApMhkitixfU6i
272
272
  nucliadb/standalone/static/index.html,sha256=PEZfuEQFYnYACAL1ceN8xC0im8lBrUx838RkE8tbvgA,3833
273
273
  nucliadb/standalone/static/logo.svg,sha256=-wQqSvPGTdlKjUP6pHE6kiq005pgYjDzp9nPl0X71Mk,2639
274
274
  nucliadb/tasks/__init__.py,sha256=oFJ3A8HD7w11mBu-IixYE_KxA7juMGlYQb7YD_y6WPM,975
275
- nucliadb/tasks/consumer.py,sha256=xc0Ql3N1Iq52dJ3t4YYGJFj1NCQAly0J5W_brfLa_F8,6894
275
+ nucliadb/tasks/consumer.py,sha256=4CWfBdXVr2a25n7seldbQ0PaK0FcxJZuWgosU6aODS8,6956
276
276
  nucliadb/tasks/logger.py,sha256=C7keOEO_mjLVp5VbqAZ2QXfqVB2Hot7NgBlUP_SDSMw,924
277
277
  nucliadb/tasks/models.py,sha256=qrZKi5DNDQ07waMsp5L4_Fi7WRs57YiO-kmXlrBzEAA,1168
278
278
  nucliadb/tasks/producer.py,sha256=UnpJAzhj_GElsCoO5G6T4m6MshsgOaqR2tVzJmEta64,2625
@@ -284,7 +284,7 @@ nucliadb/tests/vectors.py,sha256=CcNKx-E8LPpyvRyljbmb-Tn_wST9Juw2CBoogWrKiTk,628
284
284
  nucliadb/train/__init__.py,sha256=NVwe5yULoHXb80itIJT8YJYEz2xbiOPQ7_OMys6XJw8,1301
285
285
  nucliadb/train/app.py,sha256=TiRttTvekLuZdIvi46E4HyuumDTkR4G4Luqq3fEdjes,2824
286
286
  nucliadb/train/generator.py,sha256=0_zqWsLUHmJZl0lXhGorO5CWSkl42-k78dqb1slZ5h0,3904
287
- nucliadb/train/lifecycle.py,sha256=7rW2Be9cMUg7-fY9JhC5krXBB7MDOM4BpfNRRO5IAec,1713
287
+ nucliadb/train/lifecycle.py,sha256=a96KuAVZ0sf9TVVW6v6szVXn2eGBaboszwnv_HdWiZk,1820
288
288
  nucliadb/train/models.py,sha256=BmgmMjDsu_1Ih5JDAqo6whhume90q0ASJcDP9dkMQm8,1198
289
289
  nucliadb/train/nodes.py,sha256=HROQMRw2g5sJTnuBagh3B0id3iWonRJ68tg3skOme9k,5748
290
290
  nucliadb/train/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -351,8 +351,8 @@ nucliadb/writer/tus/local.py,sha256=7jYa_w9b-N90jWgN2sQKkNcomqn6JMVBOVeDOVYJHto,
351
351
  nucliadb/writer/tus/s3.py,sha256=vF0NkFTXiXhXq3bCVXXVV-ED38ECVoUeeYViP8uMqcU,8357
352
352
  nucliadb/writer/tus/storage.py,sha256=ToqwjoYnjI4oIcwzkhha_MPxi-k4Jk3Lt55zRwaC1SM,2903
353
353
  nucliadb/writer/tus/utils.py,sha256=MSdVbRsRSZVdkaum69_0wku7X3p5wlZf4nr6E0GMKbw,2556
354
- nucliadb-6.3.1.post3590.dist-info/METADATA,sha256=cnyGLiXObJPzQkmY-I7Ilyq2TvPG9l48K1TrnPhqreQ,4291
355
- nucliadb-6.3.1.post3590.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
356
- nucliadb-6.3.1.post3590.dist-info/entry_points.txt,sha256=XqGfgFDuY3zXQc8ewXM2TRVjTModIq851zOsgrmaXx4,1268
357
- nucliadb-6.3.1.post3590.dist-info/top_level.txt,sha256=hwYhTVnX7jkQ9gJCkVrbqEG1M4lT2F_iPQND1fCzF80,20
358
- nucliadb-6.3.1.post3590.dist-info/RECORD,,
354
+ nucliadb-6.3.1.post3598.dist-info/METADATA,sha256=66igSpA2Xq5tC8ibQhQSNAKLryF2gO_ZZxpOXHbET3I,4291
355
+ nucliadb-6.3.1.post3598.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
356
+ nucliadb-6.3.1.post3598.dist-info/entry_points.txt,sha256=XqGfgFDuY3zXQc8ewXM2TRVjTModIq851zOsgrmaXx4,1268
357
+ nucliadb-6.3.1.post3598.dist-info/top_level.txt,sha256=hwYhTVnX7jkQ9gJCkVrbqEG1M4lT2F_iPQND1fCzF80,20
358
+ nucliadb-6.3.1.post3598.dist-info/RECORD,,