dbos 0.20.0a2__py3-none-any.whl → 0.20.0a5__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
@@ -488,6 +488,22 @@ def start_workflow(
488
488
  return WorkflowHandleFuture(new_wf_id, future, dbos)
489
489
 
490
490
 
491
+ if sys.version_info < (3, 12):
492
+
493
+ def _mark_coroutine(func: Callable[P, R]) -> Callable[P, R]:
494
+ @wraps(func)
495
+ async def async_wrapper(*args: Any, **kwargs: Any) -> R:
496
+ return await func(*args, **kwargs) # type: ignore
497
+
498
+ return async_wrapper # type: ignore
499
+
500
+ else:
501
+
502
+ def _mark_coroutine(func: Callable[P, R]) -> Callable[P, R]:
503
+ inspect.markcoroutinefunction(func)
504
+ return func
505
+
506
+
491
507
  def workflow_wrapper(
492
508
  dbosreg: "DBOSRegistry",
493
509
  func: Callable[P, R],
@@ -548,7 +564,7 @@ def workflow_wrapper(
548
564
  )
549
565
  return outcome() # type: ignore
550
566
 
551
- return wrapper
567
+ return _mark_coroutine(wrapper) if inspect.iscoroutinefunction(func) else wrapper
552
568
 
553
569
 
554
570
  def decorate_workflow(
@@ -838,6 +854,10 @@ def decorate_step(
838
854
  assert tempwf
839
855
  return tempwf(*args, **kwargs)
840
856
 
857
+ wrapper = (
858
+ _mark_coroutine(wrapper) if inspect.iscoroutinefunction(func) else wrapper # type: ignore
859
+ )
860
+
841
861
  def temp_wf_sync(*args: Any, **kwargs: Any) -> Any:
842
862
  return wrapper(*args, **kwargs)
843
863
 
dbos/_fastapi.py CHANGED
@@ -1,10 +1,10 @@
1
1
  import uuid
2
- from typing import Any, Callable, cast
2
+ from typing import Any, Callable, MutableMapping, cast
3
3
 
4
4
  from fastapi import FastAPI
5
5
  from fastapi import Request as FastAPIRequest
6
6
  from fastapi.responses import JSONResponse
7
- from starlette.types import ASGIApp, Message, Receive, Scope, Send
7
+ from starlette.types import ASGIApp, Receive, Scope, Send
8
8
 
9
9
  from . import DBOS
10
10
  from ._context import (
@@ -61,15 +61,16 @@ class LifespanMiddleware:
61
61
 
62
62
  async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
63
63
  if scope["type"] == "lifespan":
64
- while True:
65
- message = await receive()
66
- if message["type"] == "lifespan.startup":
64
+
65
+ async def wrapped_send(message: MutableMapping[str, Any]) -> None:
66
+ if message["type"] == "lifespan.startup.complete":
67
67
  self.dbos._launch()
68
- await send({"type": "lifespan.startup.complete"})
69
- elif message["type"] == "lifespan.shutdown":
68
+ elif message["type"] == "lifespan.shutdown.complete":
70
69
  self.dbos._destroy()
71
- await send({"type": "lifespan.shutdown.complete"})
72
- break
70
+ await send(message)
71
+
72
+ # Call the original app with our wrapped functions
73
+ await self.app(scope, receive, wrapped_send)
73
74
  else:
74
75
  await self.app(scope, receive, send)
75
76
 
@@ -0,0 +1,107 @@
1
+ import os
2
+ from base64 import b64decode
3
+ from typing import List, TypedDict
4
+
5
+ import requests
6
+
7
+ DEMO_REPO_API = "https://api.github.com/repos/dbos-inc/dbos-demo-apps"
8
+ PY_DEMO_PATH = "python/"
9
+ BRANCH = "main"
10
+
11
+
12
+ class GitHubTreeItem(TypedDict):
13
+ path: str
14
+ mode: str
15
+ type: str
16
+ sha: str
17
+ url: str
18
+ size: int
19
+
20
+
21
+ class GitHubTree(TypedDict):
22
+ sha: str
23
+ url: str
24
+ tree: List[GitHubTreeItem]
25
+ truncated: bool
26
+
27
+
28
+ class GitHubItem(TypedDict):
29
+ sha: str
30
+ node_id: str
31
+ url: str
32
+ content: str
33
+ encoding: str
34
+ size: int
35
+
36
+
37
+ def _fetch_github(url: str) -> requests.Response:
38
+ headers = {}
39
+ github_token = os.getenv("GITHUB_TOKEN")
40
+ if github_token:
41
+ headers["Authorization"] = f"Bearer {github_token}"
42
+
43
+ response = requests.get(url, headers=headers)
44
+
45
+ if not response.ok:
46
+ if response.headers.get("x-ratelimit-remaining") == "0":
47
+ raise Exception(
48
+ "Error fetching from GitHub API: rate limit exceeded.\n"
49
+ "Please wait a few minutes and try again.\n"
50
+ "To increase the limit, you can create a personal access token and set it in the GITHUB_TOKEN environment variable.\n"
51
+ "Details: https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api"
52
+ )
53
+ elif response.status_code == 401:
54
+ raise Exception(
55
+ f"Error fetching content from GitHub {url}: {response.status_code} {response.reason}.\n"
56
+ "Please ensure your GITHUB_TOKEN environment variable is set to a valid personal access token."
57
+ )
58
+ raise Exception(
59
+ f"Error fetching content from GitHub {url}: {response.status_code} {response.reason}"
60
+ )
61
+
62
+ return response
63
+
64
+
65
+ def _fetch_github_tree(tag: str) -> List[GitHubTreeItem]:
66
+ response = _fetch_github(f"{DEMO_REPO_API}/git/trees/{tag}?recursive=1")
67
+ tree_data: GitHubTree = response.json()
68
+ return tree_data["tree"]
69
+
70
+
71
+ def _fetch_github_item(url: str) -> str:
72
+ response = _fetch_github(url)
73
+ item: GitHubItem = response.json()
74
+ return b64decode(item["content"]).decode("utf-8")
75
+
76
+
77
+ def create_template_from_github(app_name: str, template_name: str) -> None:
78
+ print(
79
+ f"Creating a new application named {app_name} from the template {template_name}"
80
+ )
81
+
82
+ tree = _fetch_github_tree(BRANCH)
83
+ template_path = f"{PY_DEMO_PATH}{template_name}/"
84
+
85
+ files_to_download = [
86
+ item
87
+ for item in tree
88
+ if item["path"].startswith(template_path) and item["type"] == "blob"
89
+ ]
90
+
91
+ # Download every file from the template
92
+ for item in files_to_download:
93
+ raw_content = _fetch_github_item(item["url"])
94
+ file_path = item["path"].replace(template_path, "")
95
+ target_path = os.path.join(".", file_path)
96
+
97
+ # Create directory if it doesn't exist
98
+ os.makedirs(os.path.dirname(target_path), exist_ok=True)
99
+
100
+ # Write file with proper permissions
101
+ with open(target_path, "w", encoding="utf-8") as f:
102
+ f.write(raw_content)
103
+ os.chmod(target_path, int(item["mode"], 8))
104
+
105
+ print(
106
+ f"Downloaded {len(files_to_download)} files from the template GitHub repository"
107
+ )
@@ -0,0 +1,98 @@
1
+ import os
2
+ import shutil
3
+ import typing
4
+ from os import path
5
+ from typing import Any
6
+
7
+ import tomlkit
8
+ from rich import print
9
+
10
+
11
+ def get_templates_directory() -> str:
12
+ import dbos
13
+
14
+ package_dir = path.abspath(path.dirname(dbos.__file__))
15
+ return path.join(package_dir, "_templates")
16
+
17
+
18
+ def _copy_dbos_template(src: str, dst: str, ctx: dict[str, str]) -> None:
19
+ with open(src, "r") as f:
20
+ content = f.read()
21
+
22
+ for key, value in ctx.items():
23
+ content = content.replace(f"${{{key}}}", value)
24
+
25
+ with open(dst, "w") as f:
26
+ f.write(content)
27
+
28
+
29
+ def _copy_template_dir(src_dir: str, dst_dir: str, ctx: dict[str, str]) -> None:
30
+
31
+ for root, dirs, files in os.walk(src_dir, topdown=True):
32
+ dirs[:] = [d for d in dirs if d != "__package"]
33
+
34
+ dst_root = path.join(dst_dir, path.relpath(root, src_dir))
35
+ if len(dirs) == 0:
36
+ os.makedirs(dst_root, exist_ok=True)
37
+ else:
38
+ for dir in dirs:
39
+ os.makedirs(path.join(dst_root, dir), exist_ok=True)
40
+
41
+ for file in files:
42
+ src = path.join(root, file)
43
+ base, ext = path.splitext(file)
44
+
45
+ dst = path.join(dst_root, base if ext == ".dbos" else file)
46
+ if path.exists(dst):
47
+ print(f"[yellow]File {dst} already exists, skipping[/yellow]")
48
+ continue
49
+
50
+ if ext == ".dbos":
51
+ _copy_dbos_template(src, dst, ctx)
52
+ else:
53
+ shutil.copy(src, dst)
54
+
55
+
56
+ def copy_template(src_dir: str, project_name: str, config_mode: bool) -> None:
57
+
58
+ dst_dir = path.abspath(".")
59
+
60
+ package_name = project_name.replace("-", "_")
61
+ ctx = {
62
+ "project_name": project_name,
63
+ "package_name": package_name,
64
+ "migration_command": "alembic upgrade head",
65
+ }
66
+
67
+ if config_mode:
68
+ ctx["package_name"] = "."
69
+ ctx["migration_command"] = "echo 'No migrations specified'"
70
+ _copy_dbos_template(
71
+ os.path.join(src_dir, "dbos-config.yaml.dbos"),
72
+ os.path.join(dst_dir, "dbos-config.yaml"),
73
+ ctx,
74
+ )
75
+ else:
76
+ _copy_template_dir(src_dir, dst_dir, ctx)
77
+ _copy_template_dir(
78
+ path.join(src_dir, "__package"), path.join(dst_dir, package_name), ctx
79
+ )
80
+
81
+
82
+ def get_project_name() -> typing.Union[str, None]:
83
+ name = None
84
+ try:
85
+ with open("pyproject.toml", "rb") as file:
86
+ pyproj = typing.cast(dict[str, Any], tomlkit.load(file))
87
+ name = typing.cast(str, pyproj["project"]["name"])
88
+ except:
89
+ pass
90
+
91
+ if name == None:
92
+ try:
93
+ _, parent = path.split(path.abspath("."))
94
+ name = parent
95
+ except:
96
+ pass
97
+
98
+ return name
@@ -1,6 +1,5 @@
1
1
  import os
2
2
  import platform
3
- import shutil
4
3
  import signal
5
4
  import subprocess
6
5
  import time
@@ -11,19 +10,19 @@ from typing import Any
11
10
  import jsonpickle # type: ignore
12
11
  import requests
13
12
  import sqlalchemy as sa
14
- import tomlkit
15
13
  import typer
16
14
  from rich import print
17
- from rich.prompt import Prompt
15
+ from rich.prompt import IntPrompt
18
16
  from typing_extensions import Annotated
19
17
 
20
- from dbos._schemas.system_database import SystemSchema
21
-
22
- from . import _serialization, load_config
23
- from ._app_db import ApplicationDatabase
24
- from ._dbos_config import _is_valid_app_name
25
- from ._sys_db import SystemDatabase
26
- from ._workflow_commands import _cancel_workflow, _get_workflow, _list_workflows
18
+ from .. import load_config
19
+ from .._app_db import ApplicationDatabase
20
+ from .._dbos_config import _is_valid_app_name
21
+ from .._schemas.system_database import SystemSchema
22
+ from .._sys_db import SystemDatabase
23
+ from .._workflow_commands import _cancel_workflow, _get_workflow, _list_workflows
24
+ from ..cli._github_init import create_template_from_github
25
+ from ._template_init import copy_template, get_project_name, get_templates_directory
27
26
 
28
27
  app = typer.Typer()
29
28
  workflow = typer.Typer()
@@ -86,96 +85,6 @@ def start() -> None:
86
85
  process.wait()
87
86
 
88
87
 
89
- def _get_templates_directory() -> str:
90
- import dbos
91
-
92
- package_dir = path.abspath(path.dirname(dbos.__file__))
93
- return path.join(package_dir, "_templates")
94
-
95
-
96
- def _copy_dbos_template(src: str, dst: str, ctx: dict[str, str]) -> None:
97
- with open(src, "r") as f:
98
- content = f.read()
99
-
100
- for key, value in ctx.items():
101
- content = content.replace(f"${{{key}}}", value)
102
-
103
- with open(dst, "w") as f:
104
- f.write(content)
105
-
106
-
107
- def _copy_template_dir(src_dir: str, dst_dir: str, ctx: dict[str, str]) -> None:
108
-
109
- for root, dirs, files in os.walk(src_dir, topdown=True):
110
- dirs[:] = [d for d in dirs if d != "__package"]
111
-
112
- dst_root = path.join(dst_dir, path.relpath(root, src_dir))
113
- if len(dirs) == 0:
114
- os.makedirs(dst_root, exist_ok=True)
115
- else:
116
- for dir in dirs:
117
- os.makedirs(path.join(dst_root, dir), exist_ok=True)
118
-
119
- for file in files:
120
- src = path.join(root, file)
121
- base, ext = path.splitext(file)
122
-
123
- dst = path.join(dst_root, base if ext == ".dbos" else file)
124
- if path.exists(dst):
125
- print(f"[yellow]File {dst} already exists, skipping[/yellow]")
126
- continue
127
-
128
- if ext == ".dbos":
129
- _copy_dbos_template(src, dst, ctx)
130
- else:
131
- shutil.copy(src, dst)
132
-
133
-
134
- def _copy_template(src_dir: str, project_name: str, config_mode: bool) -> None:
135
-
136
- dst_dir = path.abspath(".")
137
-
138
- package_name = project_name.replace("-", "_")
139
- ctx = {
140
- "project_name": project_name,
141
- "package_name": package_name,
142
- "migration_command": "alembic upgrade head",
143
- }
144
-
145
- if config_mode:
146
- ctx["package_name"] = "."
147
- ctx["migration_command"] = "echo 'No migrations specified'"
148
- _copy_dbos_template(
149
- os.path.join(src_dir, "dbos-config.yaml.dbos"),
150
- os.path.join(dst_dir, "dbos-config.yaml"),
151
- ctx,
152
- )
153
- else:
154
- _copy_template_dir(src_dir, dst_dir, ctx)
155
- _copy_template_dir(
156
- path.join(src_dir, "__package"), path.join(dst_dir, package_name), ctx
157
- )
158
-
159
-
160
- def _get_project_name() -> typing.Union[str, None]:
161
- name = None
162
- try:
163
- with open("pyproject.toml", "rb") as file:
164
- pyproj = typing.cast(dict[str, Any], tomlkit.load(file))
165
- name = typing.cast(str, pyproj["project"]["name"])
166
- except:
167
- pass
168
-
169
- if name == None:
170
- try:
171
- _, parent = path.split(path.abspath("."))
172
- name = parent
173
- except:
174
- pass
175
-
176
- return name
177
-
178
-
179
88
  @app.command(help="Initialize a new DBOS application from a template")
180
89
  def init(
181
90
  project_name: Annotated[
@@ -191,35 +100,60 @@ def init(
191
100
  ] = False,
192
101
  ) -> None:
193
102
  try:
194
- if project_name is None:
195
- project_name = typing.cast(
196
- str, typer.prompt("What is your project's name?", _get_project_name())
197
- )
103
+ git_templates = ["dbos-app-starter", "dbos-cron-starter"]
104
+ templates_dir = get_templates_directory()
105
+ templates = git_templates + [
106
+ x.name for x in os.scandir(templates_dir) if x.is_dir()
107
+ ]
108
+ if len(templates) == 0:
109
+ raise Exception(f"no DBOS templates found in {templates_dir} ")
110
+
111
+ if template:
112
+ if template not in templates:
113
+ raise Exception(f"Template {template} not found in {templates_dir}")
114
+ else:
115
+ print("\n[bold]Available templates:[/bold]")
116
+ for idx, template_name in enumerate(templates, 1):
117
+ print(f" {idx}. {template_name}")
118
+ while True:
119
+ try:
120
+ choice = IntPrompt.ask(
121
+ "\nSelect template number",
122
+ show_choices=False,
123
+ show_default=False,
124
+ )
125
+ if 1 <= choice <= len(templates):
126
+ template = templates[choice - 1]
127
+ break
128
+ else:
129
+ print(
130
+ "[red]Invalid selection. Please choose a number from the list.[/red]"
131
+ )
132
+ except (KeyboardInterrupt, EOFError):
133
+ raise typer.Abort()
134
+ except ValueError:
135
+ print("[red]Please enter a valid number.[/red]")
136
+
137
+ if template in git_templates:
138
+ project_name = template
139
+ else:
140
+ if project_name is None:
141
+ project_name = typing.cast(
142
+ str,
143
+ typer.prompt("What is your project's name?", get_project_name()),
144
+ )
198
145
 
199
146
  if not _is_valid_app_name(project_name):
200
147
  raise Exception(
201
148
  f"{project_name} is an invalid DBOS app name. App names must be between 3 and 30 characters long and contain only lowercase letters, numbers, dashes, and underscores."
202
149
  )
203
150
 
204
- templates_dir = _get_templates_directory()
205
- templates = [x.name for x in os.scandir(templates_dir) if x.is_dir()]
206
- if len(templates) == 0:
207
- raise Exception(f"no DBOS templates found in {templates_dir} ")
208
-
209
- if template == None:
210
- if len(templates) == 1:
211
- template = templates[0]
212
- else:
213
- template = Prompt.ask(
214
- "Which project template do you want to use?", choices=templates
215
- )
151
+ if template in git_templates:
152
+ create_template_from_github(app_name=project_name, template_name=template)
216
153
  else:
217
- if template not in templates:
218
- raise Exception(f"template {template} not found in {templates_dir}")
219
-
220
- _copy_template(
221
- path.join(templates_dir, template), project_name, config_mode=config
222
- )
154
+ copy_template(
155
+ path.join(templates_dir, template), project_name, config_mode=config
156
+ )
223
157
  except Exception as e:
224
158
  print(f"[red]{e}[/red]")
225
159
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dbos
3
- Version: 0.20.0a2
3
+ Version: 0.20.0a5
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.20.0a2.dist-info/METADATA,sha256=HuHOltiSuDZN-RYCA22G-kTSVYlfK9bksxlPiAamZuo,5309
2
- dbos-0.20.0a2.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
- dbos-0.20.0a2.dist-info/entry_points.txt,sha256=z6GcVANQV7Uw_82H9Ob2axJX6V3imftyZsljdh-M1HU,54
4
- dbos-0.20.0a2.dist-info/licenses/LICENSE,sha256=VGZit_a5-kdw9WT6fY5jxAWVwGQzgLFyPWrcVVUhVNU,1067
1
+ dbos-0.20.0a5.dist-info/METADATA,sha256=cZ5iLUPDym0buq95icnnMNaD7rZV90kbOut-927xtU0,5309
2
+ dbos-0.20.0a5.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
+ dbos-0.20.0a5.dist-info/entry_points.txt,sha256=_QOQ3tVfEjtjBlr1jS4sHqHya9lI2aIEIWkz8dqYp14,58
4
+ dbos-0.20.0a5.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,13 +10,13 @@ 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=RH08s_nee95vgxdz6AsYuVWF1LuJSVtOyIifblsa4pw,18760
13
- dbos/_core.py,sha256=dmVve1YZyQmAfwKsxqz6N3bXBowsMBmLxBDsymoWKsA,35956
13
+ dbos/_core.py,sha256=-2oh2-NicMJBwTwrd2EQBQm4Vu0caozFeoS9Kj47DzM,36588
14
14
  dbos/_croniter.py,sha256=hbhgfsHBqclUS8VeLnJ9PSE9Z54z6mi4nnrr1aUXn0k,47561
15
15
  dbos/_db_wizard.py,sha256=xgKLna0_6Xi50F3o8msRosXba8NScHlpJR5ICVCkHDQ,7534
16
16
  dbos/_dbos.py,sha256=Kgnity6JxjThIf1L8CQbeobQMiJqUUeWlRf36_eGu2g,35385
17
17
  dbos/_dbos_config.py,sha256=h_q1gzudhsAMVkGMD0qQ6kLic6YhdJgzm50YFSIx9Bo,8196
18
18
  dbos/_error.py,sha256=vtaSsG0QW6cRlwfZ4zzZWy_IHCZlomwSlrDyGWuyn8c,4337
19
- dbos/_fastapi.py,sha256=yRHrCwul2iYBxAAYuBQLcn9LMYUS6PE4CU9y1vUSPR8,3587
19
+ dbos/_fastapi.py,sha256=ke03vqsSYDnO6XeOtOVFXj0-f-v1MGsOxa9McaROvNc,3616
20
20
  dbos/_flask.py,sha256=DZKUZR5-xOzPI7tYZ53r2PvvHVoAb8SYwLzMVFsVfjI,2608
21
21
  dbos/_kafka.py,sha256=o6DbwnsYRDtvVTZVsN7BAK8cdP79AfoWX3Q7CGY2Yuo,4199
22
22
  dbos/_kafka_message.py,sha256=NYvOXNG3Qn7bghn1pv3fg4Pbs86ILZGcK4IB-MLUNu0,409
@@ -42,20 +42,22 @@ dbos/_schemas/application_database.py,sha256=KeyoPrF7hy_ODXV7QNike_VFSD74QBRfQ76
42
42
  dbos/_schemas/system_database.py,sha256=rwp4EvCSaXcUoMaRczZCvETCxGp72k3-hvLyGUDkih0,5163
43
43
  dbos/_serialization.py,sha256=YCYv0qKAwAZ1djZisBC7khvKqG-5OcIv9t9EC5PFIog,1743
44
44
  dbos/_sys_db.py,sha256=ha5E11P83oi78L4R7cX_OL_N1Tf2Ir0Xr30GK1_27SA,52290
45
- dbos/_templates/hello/README.md,sha256=GhxhBj42wjTt1fWEtwNriHbJuKb66Vzu89G4pxNHw2g,930
46
- dbos/_templates/hello/__package/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
- dbos/_templates/hello/__package/main.py,sha256=eI0SS9Nwj-fldtiuSzIlIG6dC91GXXwdRsoHxv6S_WI,2719
48
- dbos/_templates/hello/__package/schema.py,sha256=7Z27JGC8yy7Z44cbVXIREYxtUhU4JVkLCp5Q7UahVQ0,260
49
- dbos/_templates/hello/alembic.ini,sha256=VKBn4Gy8mMuCdY7Hip1jmo3wEUJ1VG1aW7EqY0_n-as,3695
50
- dbos/_templates/hello/dbos-config.yaml.dbos,sha256=OMlcpdYUJKjyAme7phOz3pbn9upcIRjm42iwEThWUEQ,495
51
- dbos/_templates/hello/migrations/env.py.dbos,sha256=GUV6sjkDzf9Vl6wkGEd0RSkK-ftRfV6EUwSQdd0qFXg,2392
52
- dbos/_templates/hello/migrations/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
53
- dbos/_templates/hello/migrations/versions/2024_07_31_180642_init.py,sha256=U5thFWGqNN4QLrNXT7wUUqftIFDNE5eSdqD8JNW1mec,942
54
- dbos/_templates/hello/start_postgres_docker.py,sha256=lQVLlYO5YkhGPEgPqwGc7Y8uDKse9HsWv5fynJEFJHM,1681
45
+ dbos/_templates/dbos-db-starter/README.md,sha256=GhxhBj42wjTt1fWEtwNriHbJuKb66Vzu89G4pxNHw2g,930
46
+ dbos/_templates/dbos-db-starter/__package/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
+ dbos/_templates/dbos-db-starter/__package/main.py,sha256=eI0SS9Nwj-fldtiuSzIlIG6dC91GXXwdRsoHxv6S_WI,2719
48
+ dbos/_templates/dbos-db-starter/__package/schema.py,sha256=7Z27JGC8yy7Z44cbVXIREYxtUhU4JVkLCp5Q7UahVQ0,260
49
+ dbos/_templates/dbos-db-starter/alembic.ini,sha256=VKBn4Gy8mMuCdY7Hip1jmo3wEUJ1VG1aW7EqY0_n-as,3695
50
+ dbos/_templates/dbos-db-starter/dbos-config.yaml.dbos,sha256=OMlcpdYUJKjyAme7phOz3pbn9upcIRjm42iwEThWUEQ,495
51
+ dbos/_templates/dbos-db-starter/migrations/env.py.dbos,sha256=GUV6sjkDzf9Vl6wkGEd0RSkK-ftRfV6EUwSQdd0qFXg,2392
52
+ dbos/_templates/dbos-db-starter/migrations/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
53
+ dbos/_templates/dbos-db-starter/migrations/versions/2024_07_31_180642_init.py,sha256=U5thFWGqNN4QLrNXT7wUUqftIFDNE5eSdqD8JNW1mec,942
54
+ dbos/_templates/dbos-db-starter/start_postgres_docker.py,sha256=lQVLlYO5YkhGPEgPqwGc7Y8uDKse9HsWv5fynJEFJHM,1681
55
55
  dbos/_tracer.py,sha256=rvBY1RQU6DO7rL7EnaJJxGcmd4tP_PpGqUEE6imZnhY,2518
56
56
  dbos/_workflow_commands.py,sha256=tj-gJARjDJ5aYo0ii2udTAU4l36vbeXwmOYh8Q4y_ac,4625
57
- dbos/cli.py,sha256=26fowBwpV-U7kuPdGRnAcuUMJIqYvstMX9qJ0t-B6BI,15354
57
+ dbos/cli/_github_init.py,sha256=Y_bDF9gfO2jB1id4FV5h1oIxEJRWyqVjhb7bNEa5nQ0,3224
58
+ dbos/cli/_template_init.py,sha256=AfuMaO8bmr9WsPNHr6j2cp7kjVVZDUpH7KpbTg0hhFs,2722
59
+ dbos/cli/cli.py,sha256=4YRwY9fIOPAP7CS1OhTOZvLeyihK6ddn0KcYRDvX0E8,13928
58
60
  dbos/dbos-config.schema.json,sha256=X5TpXNcARGceX0zQs0fVgtZW_Xj9uBbY5afPt9Rz9yk,5741
59
61
  dbos/py.typed,sha256=QfzXT1Ktfk3Rj84akygc7_42z0lRpCq0Ilh8OXI6Zas,44
60
62
  version/__init__.py,sha256=L4sNxecRuqdtSFdpUGX3TtBi9KL3k7YsZVIvv-fv9-A,1678
61
- dbos-0.20.0a2.dist-info/RECORD,,
63
+ dbos-0.20.0a5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  [console_scripts]
2
- dbos = dbos.cli:app
2
+ dbos = dbos.cli.cli:app
3
3
 
4
4
  [gui_scripts]
5
5
 
File without changes
File without changes