datashare-python 0.10.1__tar.gz → 0.10.4__tar.gz

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 (29) hide show
  1. {datashare_python-0.10.1 → datashare_python-0.10.4}/PKG-INFO +2 -2
  2. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/interceptors.py +26 -3
  3. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/objects.py +11 -1
  4. datashare_python-0.10.4/datashare_python/worker-template.tar.gz +0 -0
  5. {datashare_python-0.10.1 → datashare_python-0.10.4}/pyproject.toml +1 -1
  6. datashare_python-0.10.1/datashare_python/worker-template.tar.gz +0 -0
  7. {datashare_python-0.10.1 → datashare_python-0.10.4}/.gitignore +0 -0
  8. {datashare_python-0.10.1 → datashare_python-0.10.4}/README.md +0 -0
  9. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/.gitignore +0 -0
  10. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/__init__.py +0 -0
  11. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/__main__.py +0 -0
  12. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/cli/__init__.py +0 -0
  13. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/cli/project.py +0 -0
  14. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/cli/task.py +0 -0
  15. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/cli/utils.py +0 -0
  16. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/cli/worker.py +0 -0
  17. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/config.py +0 -0
  18. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/conftest.py +0 -0
  19. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/constants.py +0 -0
  20. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/dependencies.py +0 -0
  21. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/discovery.py +0 -0
  22. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/exceptions.py +0 -0
  23. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/logging_.py +0 -0
  24. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/mimetypes_.py +0 -0
  25. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/task_client.py +0 -0
  26. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/template.py +0 -0
  27. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/types_.py +0 -0
  28. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/utils.py +0 -0
  29. {datashare_python-0.10.1 → datashare_python-0.10.4}/datashare_python/worker.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: datashare-python
3
- Version: 0.10.1
3
+ Version: 0.10.4
4
4
  Summary: Manage Python tasks and local resources in Datashare
5
5
  Project-URL: Homepage, https://icij.github.io/datashare-python/
6
6
  Project-URL: Documentation, https://icij.github.io/datashare-python/
@@ -1,6 +1,7 @@
1
1
  import asyncio
2
2
  import dataclasses
3
3
  import datetime
4
+ import logging
4
5
  import secrets
5
6
  from collections.abc import Callable, Generator, Mapping
6
7
  from contextlib import contextmanager
@@ -66,6 +67,8 @@ from .utils import (
66
67
  ProgressSignal,
67
68
  )
68
69
 
70
+ logger = logging.getLogger(__name__)
71
+
69
72
  _TRACEPARENT = "traceparent"
70
73
  _DEFAULT_PAYLOAD_CONVERTER = DataConverter.default.payload_converter
71
74
  _PROGRESS_TYPES = {
@@ -190,6 +193,8 @@ class _TraceContextWorkflowOutboundInterceptor(WorkflowOutboundInterceptor):
190
193
 
191
194
  class _TraceContextActivityInboundInterceptor(ActivityInboundInterceptor):
192
195
  async def execute_activity(self, input: ExecuteActivityInput) -> Any: # noqa: A002
196
+ info = activity.info()
197
+ logger.info("start executing activity: %s", info.activity_id)
193
198
  with _trace_context(input.headers):
194
199
  return await super().execute_activity(input)
195
200
 
@@ -431,9 +436,10 @@ class _HeartbeatInboundInterceptor(ActivityInboundInterceptor):
431
436
  heartbeat_task = None
432
437
  if heartbeat_timeout:
433
438
  period = heartbeat_timeout.total_seconds() / self._n_missed_before_timeout
434
- heartbeat_task = asyncio.create_task(
435
- _heartbeat_every(self._outbound.heartbeat, period)
436
- )
439
+ # We don't want a failing hearbeat to fail the worker task so we just
440
+ # ignore any exception
441
+ heartbeat_fn = _fail_safe(self._outbound.heartbeat)
442
+ heartbeat_task = asyncio.create_task(_heartbeat_every(heartbeat_fn, period))
437
443
  try:
438
444
  activity.heartbeat()
439
445
  return await super().execute_activity(input)
@@ -443,6 +449,23 @@ class _HeartbeatInboundInterceptor(ActivityInboundInterceptor):
443
449
  await asyncio.wait([heartbeat_task])
444
450
 
445
451
 
452
+ def _fail_safe(
453
+ fn: Callable[[Any], None], excs: tuple[type[Exception]] | None = None
454
+ ) -> Callable[[Any], None]:
455
+ if excs is None:
456
+ excs = (Exception,)
457
+
458
+ @wraps(fn)
459
+ def wrapper(*args, **kwargs) -> None:
460
+ try:
461
+ fn(*args, **kwargs)
462
+ except excs as exc:
463
+ msg = f"failed to heartbeat due to {exc}"
464
+ logger.exception(msg)
465
+
466
+ return wrapper
467
+
468
+
446
469
  def _sync_progress(
447
470
  progress_handler: AsyncProgressRateHandler,
448
471
  ) -> SyncProgressRateHandler:
@@ -14,7 +14,7 @@ from icij_common.registrable import Registrable
14
14
  from pydantic_core import PydanticCustomError, ValidationError, core_schema
15
15
  from pydantic_core.core_schema import PlainValidatorFunctionSchema
16
16
  from pydantic_extra_types.language_code import LanguageName
17
- from temporalio import workflow
17
+ from temporalio import activity, workflow
18
18
 
19
19
  from .constants import TIKA_METADATA_RESOURCENAME
20
20
 
@@ -325,6 +325,8 @@ A = TypeVar("A", bound=TaskArgs)
325
325
 
326
326
  class ManifestEntry[A](DatashareModel, ABC):
327
327
  status: ManifestEntryStatus
328
+ # TODO: make this one non optional in the next major !
329
+ task_id: str | None
328
330
  label: str | None = None
329
331
  input: Annotated[
330
332
  dict[str, Any] | None,
@@ -336,7 +338,11 @@ class ManifestEntry[A](DatashareModel, ABC):
336
338
 
337
339
  @classmethod
338
340
  def complete(cls, args: A, label: str | None = None, **kwargs) -> Self:
341
+ task_id = None
342
+ if activity.in_activity():
343
+ task_id = activity.info().workflow_id
339
344
  return cls(
345
+ task_id=task_id,
340
346
  input=args.as_manifest_task_input(),
341
347
  label=label,
342
348
  status=ManifestEntryStatus.COMPLETE,
@@ -345,7 +351,11 @@ class ManifestEntry[A](DatashareModel, ABC):
345
351
 
346
352
  @classmethod
347
353
  def partial(cls, args: A, label: str | None = None, **kwargs) -> Self:
354
+ task_id = None
355
+ if activity.in_activity():
356
+ task_id = activity.info().workflow_id
348
357
  return cls(
358
+ task_id=task_id,
349
359
  input=args.as_manifest_task_input(),
350
360
  label=label,
351
361
  status=ManifestEntryStatus.PARTIAL,
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "datashare-python"
3
- version = "0.10.1"
3
+ version = "0.10.4"
4
4
  description = "Manage Python tasks and local resources in Datashare"
5
5
  authors = [
6
6
  { name = "Clément Doumouro", email = "cdoumouro@icij.org" },