dbos 0.22.0a1__py3-none-any.whl → 0.22.0a2__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.

Potentially problematic release.


This version of dbos might be problematic. Click here for more details.

dbos/_core.py CHANGED
@@ -63,6 +63,7 @@ from ._registrations import (
63
63
  get_or_create_func_info,
64
64
  get_temp_workflow_type,
65
65
  set_dbos_func_name,
66
+ set_func_info,
66
67
  set_temp_workflow_type,
67
68
  )
68
69
  from ._roles import check_required_roles
@@ -286,6 +287,7 @@ def execute_workflow_by_id(
286
287
  ctx.request = (
287
288
  _serialization.deserialize(request) if request is not None else None
288
289
  )
290
+ # If this function belongs to a configured class, add that class instance as its first argument
289
291
  if status["config_name"] is not None:
290
292
  config_name = status["config_name"]
291
293
  class_name = status["class_name"]
@@ -295,28 +297,9 @@ def execute_workflow_by_id(
295
297
  workflow_id,
296
298
  f"Cannot execute workflow because instance '{iname}' is not registered",
297
299
  )
298
-
299
- if startNew:
300
- return start_workflow(
301
- dbos,
302
- wf_func,
303
- status["queue_name"],
304
- True,
305
- dbos._registry.instance_info_map[iname],
306
- *inputs["args"],
307
- **inputs["kwargs"],
308
- )
309
- else:
310
- with SetWorkflowID(workflow_id):
311
- return start_workflow(
312
- dbos,
313
- wf_func,
314
- status["queue_name"],
315
- True,
316
- dbos._registry.instance_info_map[iname],
317
- *inputs["args"],
318
- **inputs["kwargs"],
319
- )
300
+ class_instance = dbos._registry.instance_info_map[iname]
301
+ inputs["args"] = (class_instance,) + inputs["args"]
302
+ # If this function is a class method, add that class object as its first argument
320
303
  elif status["class_name"] is not None:
321
304
  class_name = status["class_name"]
322
305
  if class_name not in dbos._registry.class_info_map:
@@ -324,30 +307,20 @@ def execute_workflow_by_id(
324
307
  workflow_id,
325
308
  f"Cannot execute workflow because class '{class_name}' is not registered",
326
309
  )
310
+ class_object = dbos._registry.class_info_map[class_name]
311
+ inputs["args"] = (class_object,) + inputs["args"]
327
312
 
328
- if startNew:
329
- return start_workflow(
330
- dbos,
331
- wf_func,
332
- status["queue_name"],
333
- True,
334
- dbos._registry.class_info_map[class_name],
335
- *inputs["args"],
336
- **inputs["kwargs"],
337
- )
338
- else:
339
- with SetWorkflowID(workflow_id):
340
- return start_workflow(
341
- dbos,
342
- wf_func,
343
- status["queue_name"],
344
- True,
345
- dbos._registry.class_info_map[class_name],
346
- *inputs["args"],
347
- **inputs["kwargs"],
348
- )
313
+ if startNew:
314
+ return start_workflow(
315
+ dbos,
316
+ wf_func,
317
+ status["queue_name"],
318
+ True,
319
+ *inputs["args"],
320
+ **inputs["kwargs"],
321
+ )
349
322
  else:
350
- if startNew:
323
+ with SetWorkflowID(workflow_id):
351
324
  return start_workflow(
352
325
  dbos,
353
326
  wf_func,
@@ -356,16 +329,6 @@ def execute_workflow_by_id(
356
329
  *inputs["args"],
357
330
  **inputs["kwargs"],
358
331
  )
359
- else:
360
- with SetWorkflowID(workflow_id):
361
- return start_workflow(
362
- dbos,
363
- wf_func,
364
- status["queue_name"],
365
- True,
366
- *inputs["args"],
367
- **inputs["kwargs"],
368
- )
369
332
 
370
333
 
371
334
  @overload
@@ -398,9 +361,12 @@ def start_workflow(
398
361
  *args: P.args,
399
362
  **kwargs: P.kwargs,
400
363
  ) -> "WorkflowHandle[R]":
364
+ # If the function has a class, add the class object as its first argument
401
365
  fself: Optional[object] = None
402
366
  if hasattr(func, "__self__"):
403
367
  fself = func.__self__
368
+ if fself is not None:
369
+ args = (fself,) + args # type: ignore
404
370
 
405
371
  fi = get_func_info(func)
406
372
  if fi is None:
@@ -436,17 +402,13 @@ def start_workflow(
436
402
  new_wf_ctx.id_assigned_for_next_workflow = new_wf_ctx.assign_workflow_id()
437
403
  new_wf_id = new_wf_ctx.id_assigned_for_next_workflow
438
404
 
439
- gin_args: Tuple[Any, ...] = args
440
- if fself is not None:
441
- gin_args = (fself,)
442
-
443
405
  status = _init_workflow(
444
406
  dbos,
445
407
  new_wf_ctx,
446
408
  inputs=inputs,
447
409
  wf_name=get_dbos_func_name(func),
448
- class_name=get_dbos_class_name(fi, func, gin_args),
449
- config_name=get_config_name(fi, func, gin_args),
410
+ class_name=get_dbos_class_name(fi, func, args),
411
+ config_name=get_config_name(fi, func, args),
450
412
  temp_wf_type=get_temp_workflow_type(func),
451
413
  queue=queue_name,
452
414
  max_recovery_attempts=fi.max_recovery_attempts,
@@ -464,27 +426,15 @@ def start_workflow(
464
426
  )
465
427
  return WorkflowHandlePolling(new_wf_id, dbos)
466
428
 
467
- if fself is not None:
468
- future = dbos._executor.submit(
469
- cast(Callable[..., R], _execute_workflow_wthread),
470
- dbos,
471
- status,
472
- func,
473
- new_wf_ctx,
474
- fself,
475
- *args,
476
- **kwargs,
477
- )
478
- else:
479
- future = dbos._executor.submit(
480
- cast(Callable[..., R], _execute_workflow_wthread),
481
- dbos,
482
- status,
483
- func,
484
- new_wf_ctx,
485
- *args,
486
- **kwargs,
487
- )
429
+ future = dbos._executor.submit(
430
+ cast(Callable[..., R], _execute_workflow_wthread),
431
+ dbos,
432
+ status,
433
+ func,
434
+ new_wf_ctx,
435
+ *args,
436
+ **kwargs,
437
+ )
488
438
  return WorkflowHandleFuture(new_wf_id, future, dbos)
489
439
 
490
440
 
@@ -516,6 +466,8 @@ def workflow_wrapper(
516
466
 
517
467
  @wraps(func)
518
468
  def wrapper(*args: Any, **kwargs: Any) -> R:
469
+ fi = get_func_info(func)
470
+ assert fi is not None
519
471
  if dbosreg.dbos is None:
520
472
  raise DBOSException(
521
473
  f"Function {func.__name__} invoked before DBOS initialized"
@@ -726,6 +678,8 @@ def decorate_transaction(
726
678
  set_temp_workflow_type(temp_wf, "transaction")
727
679
  dbosreg.register_wf_function(get_dbos_func_name(temp_wf), wrapped_wf)
728
680
  wrapper.__orig_func = temp_wf # type: ignore
681
+ set_func_info(wrapped_wf, get_or_create_func_info(func))
682
+ set_func_info(temp_wf, get_or_create_func_info(func))
729
683
 
730
684
  return cast(F, wrapper)
731
685
 
@@ -875,6 +829,8 @@ def decorate_step(
875
829
  set_temp_workflow_type(temp_wf, "step")
876
830
  dbosreg.register_wf_function(get_dbos_func_name(temp_wf), wrapped_wf)
877
831
  wrapper.__orig_func = temp_wf # type: ignore
832
+ set_func_info(wrapped_wf, get_or_create_func_info(func))
833
+ set_func_info(temp_wf, get_or_create_func_info(func))
878
834
 
879
835
  return cast(Callable[P, R], wrapper)
880
836
 
dbos/_registrations.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import inspect
2
+ from dataclasses import dataclass
2
3
  from enum import Enum
3
4
  from types import FunctionType
4
5
  from typing import Any, Callable, List, Literal, Optional, Tuple, Type, cast
@@ -31,9 +32,9 @@ def set_temp_workflow_type(f: Any, name: TempWorkflowType) -> None:
31
32
  setattr(f, "dbos_temp_workflow_type", name)
32
33
 
33
34
 
35
+ @dataclass
34
36
  class DBOSClassInfo:
35
- def __init__(self) -> None:
36
- self.def_required_roles: Optional[List[str]] = None
37
+ def_required_roles: Optional[List[str]] = None
37
38
 
38
39
 
39
40
  class DBOSFuncType(Enum):
@@ -44,12 +45,12 @@ class DBOSFuncType(Enum):
44
45
  Instance = 4
45
46
 
46
47
 
48
+ @dataclass
47
49
  class DBOSFuncInfo:
48
- def __init__(self) -> None:
49
- self.class_info: Optional[DBOSClassInfo] = None
50
- self.func_type: DBOSFuncType = DBOSFuncType.Unknown
51
- self.required_roles: Optional[List[str]] = None
52
- self.max_recovery_attempts = DEFAULT_MAX_RECOVERY_ATTEMPTS
50
+ class_info: Optional[DBOSClassInfo] = None
51
+ func_type: DBOSFuncType = DBOSFuncType.Unknown
52
+ required_roles: Optional[List[str]] = None
53
+ max_recovery_attempts: int = DEFAULT_MAX_RECOVERY_ATTEMPTS
53
54
 
54
55
 
55
56
  def get_or_create_class_info(cls: Type[Any]) -> DBOSClassInfo:
@@ -110,6 +111,10 @@ def get_or_create_func_info(func: Callable[..., Any]) -> DBOSFuncInfo:
110
111
  return fi
111
112
 
112
113
 
114
+ def set_func_info(func: Callable[..., Any], fi: DBOSFuncInfo) -> None:
115
+ setattr(func, "dbos_func_decorator_info", fi)
116
+
117
+
113
118
  def get_class_info(cls: Type[Any]) -> Optional[DBOSClassInfo]:
114
119
  if hasattr(cls, "dbos_class_decorator_info"):
115
120
  ci: DBOSClassInfo = getattr(cls, "dbos_class_decorator_info")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dbos
3
- Version: 0.22.0a1
3
+ Version: 0.22.0a2
4
4
  Summary: Ultra-lightweight durable execution in Python
5
5
  Author-Email: "DBOS, Inc." <contact@dbos.dev>
6
6
  License: MIT
@@ -1,7 +1,7 @@
1
- dbos-0.22.0a1.dist-info/METADATA,sha256=DBJiSN2oOdnkb8P0DBogQjH4Wjh79UQ9gI6bDVdbbP8,5309
2
- dbos-0.22.0a1.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
- dbos-0.22.0a1.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
4
- dbos-0.22.0a1.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
1
+ dbos-0.22.0a2.dist-info/METADATA,sha256=WWwhiPH-2zKnFO--GclmHu2CfPaIBZkEBs6DsFHYSMY,5309
2
+ dbos-0.22.0a2.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
+ dbos-0.22.0a2.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
4
+ dbos-0.22.0a2.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
5
5
  dbos/__init__.py,sha256=CxRHBHEthPL4PZoLbZhp3rdm44-KkRTT2-7DkK9d4QQ,724
6
6
  dbos/_admin_server.py,sha256=PJgneZG9-64TapZrPeJtt73puAswRImCE5uce2k2PKU,4750
7
7
  dbos/_app_db.py,sha256=_tv2vmPjjiaikwgxH3mqxgJ4nUUcG2-0uMXKWCqVu1c,5509
@@ -10,7 +10,7 @@ dbos/_cloudutils/authentication.py,sha256=V0fCWQN9stCkhbuuxgPTGpvuQcDqfU3KAxPAh0
10
10
  dbos/_cloudutils/cloudutils.py,sha256=5e3CW1deSW-dI5G3QN0XbiVsBhyqT8wu7fuV2f8wtGU,7688
11
11
  dbos/_cloudutils/databases.py,sha256=x4187Djsyoa-QaG3Kog8JT2_GERsnqa93LIVanmVUmg,8393
12
12
  dbos/_context.py,sha256=FHB_fpE4fQt4fIJvAmMMsbY4xHwH77gsW01cFsRZjsE,17779
13
- dbos/_core.py,sha256=nGiXyYgV8H5TRRZG0e8HCd5IZimufYQLmKNr7nBbwbo,36564
13
+ dbos/_core.py,sha256=PvII-lcUgii0WqaDb9-56gfQ_69VoWthKAkKexRebuk,35461
14
14
  dbos/_croniter.py,sha256=hbhgfsHBqclUS8VeLnJ9PSE9Z54z6mi4nnrr1aUXn0k,47561
15
15
  dbos/_db_wizard.py,sha256=xgKLna0_6Xi50F3o8msRosXba8NScHlpJR5ICVCkHDQ,7534
16
16
  dbos/_dbos.py,sha256=wAjdlUgDSIC_Q8D_GZYDoiKaxjtr6KNHeq6DDuUh9do,36340
@@ -33,7 +33,7 @@ dbos/_migrations/versions/eab0cc1d9a14_job_queue.py,sha256=uvhFOtqbBreCePhAxZfIT
33
33
  dbos/_outcome.py,sha256=FDMgWVjZ06vm9xO-38H17mTqBImUYQxgKs_bDCSIAhE,6648
34
34
  dbos/_queue.py,sha256=o_aczwualJTMoXb0XXL-Y5QH77OEukWzuerogbWi2ho,2779
35
35
  dbos/_recovery.py,sha256=rek9rm2CaENbbl_vu3To-BdXop7tMEyGvtoNiJLVxjQ,2772
36
- dbos/_registrations.py,sha256=mei6q6_3R5uei8i_Wo_TqGZs85s10shOekDX41sFYD0,6642
36
+ dbos/_registrations.py,sha256=_zy6k944Ll8QwqU12Kr3OP23ukVtm8axPNN1TS_kJRc,6717
37
37
  dbos/_request.py,sha256=cX1B3Atlh160phgS35gF1VEEV4pD126c9F3BDgBmxZU,929
38
38
  dbos/_roles.py,sha256=iOsgmIAf1XVzxs3gYWdGRe1B880YfOw5fpU7Jwx8_A8,2271
39
39
  dbos/_scheduler.py,sha256=0I3e8Y-OIBG3wiUCIskShd-Sk_eUFCFyRB5u4L7IHXI,1940
@@ -60,4 +60,4 @@ dbos/cli/cli.py,sha256=_tXw2IQrWW7fV_h51f_R99vEBSi6aMLz-vCOxKaENiQ,14155
60
60
  dbos/dbos-config.schema.json,sha256=X5TpXNcARGceX0zQs0fVgtZW_Xj9uBbY5afPt9Rz9yk,5741
61
61
  dbos/py.typed,sha256=QfzXT1Ktfk3Rj84akygc7_42z0lRpCq0Ilh8OXI6Zas,44
62
62
  version/__init__.py,sha256=L4sNxecRuqdtSFdpUGX3TtBi9KL3k7YsZVIvv-fv9-A,1678
63
- dbos-0.22.0a1.dist-info/RECORD,,
63
+ dbos-0.22.0a2.dist-info/RECORD,,