dbos-enterprise 0.1.0a2__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.
@@ -0,0 +1,5 @@
1
+ Copyright (c) 2026 DBOS, Inc. All rights reserved.
2
+
3
+ This software is licensed under the DBOS Conductor Software License:
4
+
5
+ https://www.dbos.dev/conductor-license
@@ -0,0 +1,34 @@
1
+ Metadata-Version: 2.1
2
+ Name: dbos-enterprise
3
+ Version: 0.1.0a2
4
+ Summary: Enterprise extension for DBOS Transact
5
+ Author-Email: "DBOS, Inc." <contact@dbos.dev>
6
+ License: DBOS Conductor Software License (https://www.dbos.dev/conductor-license)
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Programming Language :: Python
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3 :: Only
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: License :: Other/Proprietary License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: dbos<3.3,>=3.2.0a0
22
+ Requires-Dist: websockets>=14.0
23
+ Description-Content-Type: text/markdown
24
+
25
+ # DBOS Enterprise for Python
26
+
27
+ Closed-source extension of [DBOS Transact](https://github.com/dbos-inc/dbos-transact-py).
28
+ Requires a DBOS Conductor API key.
29
+
30
+ ```
31
+ pip install dbos[enterprise]
32
+ ```
33
+
34
+ See [DEVELOPING.md](./DEVELOPING.md) to work on this repo.
@@ -0,0 +1,10 @@
1
+ # DBOS Enterprise for Python
2
+
3
+ Closed-source extension of [DBOS Transact](https://github.com/dbos-inc/dbos-transact-py).
4
+ Requires a DBOS Conductor API key.
5
+
6
+ ```
7
+ pip install dbos[enterprise]
8
+ ```
9
+
10
+ See [DEVELOPING.md](./DEVELOPING.md) to work on this repo.
@@ -0,0 +1,7 @@
1
+ from importlib.metadata import version
2
+
3
+ from ._version import DBOSEnterpriseVersionError, check_core_version
4
+
5
+ __version__ = version("dbos-enterprise")
6
+
7
+ __all__ = ["DBOSEnterpriseVersionError", "check_core_version", "__version__"]
@@ -0,0 +1,22 @@
1
+ """Scratch code proving the package can reach core internals. Delete when real code lands."""
2
+
3
+ from typing import TypedDict
4
+
5
+ from dbos._utils import GlobalParams
6
+
7
+
8
+ class ExecutorInfo(TypedDict):
9
+ app_name: str | None
10
+ app_version: str
11
+ executor_id: str
12
+ dbos_version: str
13
+
14
+
15
+ def describe_executor() -> ExecutorInfo:
16
+ """Report the identity core assigns this process at launch."""
17
+ return {
18
+ "app_name": GlobalParams.app_name,
19
+ "app_version": GlobalParams.app_version,
20
+ "executor_id": GlobalParams.executor_id,
21
+ "dbos_version": GlobalParams.dbos_version,
22
+ }
@@ -0,0 +1,24 @@
1
+ import re
2
+ from importlib.metadata import version
3
+
4
+ _MAJOR_MINOR = re.compile(r"^(\d+)\.(\d+)")
5
+
6
+
7
+ class DBOSEnterpriseVersionError(Exception):
8
+ """dbos and dbos-enterprise are installed at different minor versions."""
9
+
10
+
11
+ def _major_minor(package: str) -> tuple[int, int]:
12
+ match = _MAJOR_MINOR.match(version(package))
13
+ assert match is not None, f"unparseable version for {package}"
14
+ return int(match.group(1)), int(match.group(2))
15
+
16
+
17
+ def check_core_version() -> None:
18
+ """Raise unless dbos and dbos-enterprise share a major.minor version."""
19
+ core, enterprise = _major_minor("dbos"), _major_minor("dbos-enterprise")
20
+ if core != enterprise:
21
+ raise DBOSEnterpriseVersionError(
22
+ f"dbos {version('dbos')} and dbos-enterprise {version('dbos-enterprise')} "
23
+ "must share a minor version; upgrade both with `pip install -U dbos[enterprise]`."
24
+ )
File without changes
@@ -0,0 +1,93 @@
1
+ [project]
2
+ name = "dbos-enterprise"
3
+ dynamic = []
4
+ description = "Enterprise extension for DBOS Transact"
5
+ authors = [
6
+ { name = "DBOS, Inc.", email = "contact@dbos.dev" },
7
+ ]
8
+ dependencies = [
9
+ "dbos>=3.2.0a0,<3.3",
10
+ "websockets>=14.0",
11
+ ]
12
+ requires-python = ">=3.10"
13
+ readme = "README.md"
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Programming Language :: Python",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3 :: Only",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ "Programming Language :: Python :: 3.14",
24
+ "Intended Audience :: Developers",
25
+ "License :: Other/Proprietary License",
26
+ "Operating System :: OS Independent",
27
+ "Topic :: Software Development :: Libraries :: Python Modules",
28
+ ]
29
+ version = "0.1.0a2"
30
+
31
+ [project.license]
32
+ text = "DBOS Conductor Software License (https://www.dbos.dev/conductor-license)"
33
+
34
+ [build-system]
35
+ requires = [
36
+ "pdm-backend",
37
+ ]
38
+ build-backend = "pdm.backend"
39
+
40
+ [tool.pdm]
41
+ distribution = true
42
+
43
+ [tool.pdm.build]
44
+ includes = [
45
+ "dbos_enterprise/",
46
+ ]
47
+ source-includes = [
48
+ "tests/",
49
+ "version/",
50
+ ]
51
+
52
+ [tool.pdm.version]
53
+ source = "scm"
54
+ version_format = "version:format_version"
55
+
56
+ [tool.black]
57
+ line-length = 88
58
+
59
+ [tool.isort]
60
+ profile = "black"
61
+ filter_files = true
62
+ atomic = true
63
+
64
+ [tool.mypy]
65
+ strict = true
66
+
67
+ [tool.pytest.ini_options]
68
+ addopts = "-s"
69
+ log_cli_format = "%(asctime)s [%(levelname)8s] (%(name)s:%(filename)s:%(lineno)s) %(message)s"
70
+ log_cli_level = "INFO"
71
+ log_cli = true
72
+ timeout = 120
73
+
74
+ [dependency-groups]
75
+ dev = [
76
+ "pytest>=8.3.3",
77
+ "mypy>=1.15.0",
78
+ "pytest-mock>=3.14.0",
79
+ "black>=24.10.0",
80
+ "pre-commit>=4.0.1",
81
+ "isort>=5.13.2",
82
+ "GitPython>=3.1.43",
83
+ "pdm-backend>=2.4.2",
84
+ "pytest-asyncio>=0.25.0",
85
+ "pyright>=1.1.398",
86
+ "pytest-timeout>=2.3.1",
87
+ "psycopg[binary]>=3.1",
88
+ "types-PyYAML>=6.0.12.20240808",
89
+ "types-python-dateutil>=2.9.0.20260518",
90
+ ]
91
+ core = [
92
+ "-e file:///${PROJECT_ROOT}/../dbos-transact-py",
93
+ ]
File without changes
@@ -0,0 +1,92 @@
1
+ import os
2
+ import sqlite3
3
+ from pathlib import Path
4
+ from typing import Any, Generator
5
+ from urllib.parse import quote
6
+
7
+ import pytest
8
+ import sqlalchemy as sa
9
+ from dbos import DBOS, DBOSConfig
10
+ from dbos._utils import GlobalParams
11
+
12
+
13
+ def using_sqlite() -> bool:
14
+ return os.environ.get("DBOS_DATABASE", None) == "SQLITE"
15
+
16
+
17
+ @pytest.fixture()
18
+ def skip_with_sqlite() -> None:
19
+ if using_sqlite():
20
+ pytest.skip("Skipping test when testing SQLite")
21
+
22
+
23
+ def postgres_system_url() -> str:
24
+ password = quote(os.environ.get("PGPASSWORD", "dbos"), safe="")
25
+ return f"postgresql+psycopg://postgres:{password}@localhost:5432/dbosenterprise_test_dbos_sys"
26
+
27
+
28
+ @pytest.fixture()
29
+ def sqlite_path(tmp_path: Path) -> Path:
30
+ # WAL mode, so a committing writer never stalls the notification poller.
31
+ db_path = tmp_path / "test.sqlite"
32
+ connection = sqlite3.connect(db_path)
33
+ try:
34
+ connection.execute("PRAGMA journal_mode=WAL")
35
+ finally:
36
+ connection.close()
37
+ return db_path
38
+
39
+
40
+ @pytest.fixture()
41
+ def config(sqlite_path: Path) -> DBOSConfig:
42
+ return {
43
+ "name": "enterprise-test-app",
44
+ "system_database_url": (
45
+ f"sqlite:///{sqlite_path}" if using_sqlite() else postgres_system_url()
46
+ ),
47
+ "enable_otlp": False,
48
+ "notification_listener_polling_interval_sec": 0.01,
49
+ }
50
+
51
+
52
+ def reset_global_params() -> None:
53
+ GlobalParams.app_version = os.environ.get("DBOS__APPVERSION", "")
54
+ GlobalParams.executor_id = os.environ.get("DBOS__VMID") or "local"
55
+ GlobalParams.app_name = None
56
+
57
+
58
+ @pytest.fixture(autouse=True)
59
+ def clean_process_identity() -> Generator[None, Any, None]:
60
+ yield
61
+ reset_global_params()
62
+
63
+
64
+ def _drop_system_database() -> None:
65
+ # Each test migrates from scratch; the suite is small enough for that.
66
+ DBOS.destroy(destroy_registry=True)
67
+ for var in ("DBOS__VMID", "DBOS__APPVERSION", "DBOS__APPID"):
68
+ os.environ.pop(var, None)
69
+ reset_global_params()
70
+ if using_sqlite():
71
+ return
72
+ url = sa.make_url(postgres_system_url())
73
+ engine = sa.create_engine(
74
+ url.set(database="postgres"), connect_args={"connect_timeout": 30}
75
+ )
76
+ try:
77
+ with engine.connect() as connection:
78
+ connection.execution_options(isolation_level="AUTOCOMMIT")
79
+ connection.execute(
80
+ sa.text(f"DROP DATABASE IF EXISTS {url.database} WITH (FORCE)")
81
+ )
82
+ finally:
83
+ engine.dispose()
84
+
85
+
86
+ @pytest.fixture()
87
+ def dbos(config: DBOSConfig) -> Generator[DBOS, Any, None]:
88
+ _drop_system_database()
89
+ dbos = DBOS(config=config)
90
+ DBOS.launch()
91
+ yield dbos
92
+ DBOS.destroy(destroy_registry=True)
@@ -0,0 +1,24 @@
1
+ from dbos import DBOS
2
+
3
+ from dbos_enterprise._scratch import describe_executor
4
+
5
+
6
+ def test_workflow_runs_against_core(dbos: DBOS) -> None:
7
+ @DBOS.step()
8
+ def greet_step(name: str) -> str:
9
+ return f"hello, {name}"
10
+
11
+ @DBOS.workflow()
12
+ def greet(name: str) -> str:
13
+ return greet_step(name)
14
+
15
+ assert greet("enterprise") == "hello, enterprise"
16
+ steps = DBOS.list_workflow_steps(DBOS.list_workflows()[0].workflow_id)
17
+ assert [s["function_name"] for s in steps] == [greet_step.__qualname__]
18
+
19
+
20
+ def test_describe_executor(dbos: DBOS) -> None:
21
+ info = describe_executor()
22
+ assert info["app_name"] == "enterprise-test-app"
23
+ assert info["executor_id"] == "local"
24
+ assert info["dbos_version"]
@@ -0,0 +1,38 @@
1
+ import pytest
2
+
3
+ from dbos_enterprise import (
4
+ DBOSEnterpriseVersionError,
5
+ __version__,
6
+ _version,
7
+ check_core_version,
8
+ )
9
+
10
+
11
+ def _fake_version(versions: dict[str, str]) -> "type[object]":
12
+ def fake(package: str) -> str:
13
+ return versions[package]
14
+
15
+ return fake # type: ignore[return-value]
16
+
17
+
18
+ def test_matching_minor_passes(monkeypatch: pytest.MonkeyPatch) -> None:
19
+ monkeypatch.setattr(
20
+ _version,
21
+ "version",
22
+ _fake_version({"dbos": "3.4.1", "dbos-enterprise": "3.4.0"}),
23
+ )
24
+ check_core_version()
25
+
26
+
27
+ def test_mismatched_minor_raises(monkeypatch: pytest.MonkeyPatch) -> None:
28
+ monkeypatch.setattr(
29
+ _version,
30
+ "version",
31
+ _fake_version({"dbos": "3.5.0", "dbos-enterprise": "3.4.0"}),
32
+ )
33
+ with pytest.raises(DBOSEnterpriseVersionError, match="share a minor version"):
34
+ check_core_version()
35
+
36
+
37
+ def test_package_reports_a_version() -> None:
38
+ assert __version__
@@ -0,0 +1,45 @@
1
+ from pdm.backend.hooks.version import SCMVersion
2
+
3
+
4
+ def format_version(git_version: SCMVersion) -> str:
5
+ """
6
+ Format version into string.
7
+
8
+ 1. Release versions may only be published from release branches. Their version is a git tag.
9
+ 2. Preview versions are published from main. They are PEP440 alpha releases whose version is the
10
+ next release version number followed by "a" followed by the number of commits since the last release.
11
+ If the last release was 1.2.3 and there have been ten commits since, the preview version is 1.2.3a10
12
+ 3. Test versions are published from feature branches. They are PEP440 local versions tagged with a git hash.
13
+ """
14
+ assert git_version.branch is not None
15
+ is_release = "release" in git_version.branch
16
+ is_preview = git_version.branch == "main"
17
+
18
+ next_version = guess_next_version(str(git_version.version))
19
+
20
+ if git_version.distance is None:
21
+ if is_release:
22
+ version = str(git_version.version)
23
+ elif is_preview:
24
+ version = f"{next_version}a0"
25
+ else:
26
+ version = f"{next_version}a0+{git_version.node}"
27
+ else:
28
+ if is_release:
29
+ raise Exception(
30
+ f"Release branches may only publish tagged releases. Distance: {git_version.distance}"
31
+ )
32
+ elif is_preview:
33
+ version = f"{next_version}a{git_version.distance}"
34
+ else:
35
+ version = f"{next_version}a{git_version.distance}+{git_version.node}"
36
+
37
+ return version
38
+
39
+
40
+ def guess_next_version(version_number: str) -> str:
41
+ # A repo with no release tag yet reports "0.0"; pad it to three parts.
42
+ parts = [int(part) for part in version_number.split(".")]
43
+ major, minor, patch = (parts + [0, 0, 0])[:3]
44
+ minor += 1
45
+ return f"{major}.{minor}.{patch}"