projectdavid-orm 1.12.0__tar.gz → 1.13.1__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.
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/CHANGELOG.md +15 -0
- {projectdavid_orm-1.12.0/src/projectdavid_orm.egg-info → projectdavid_orm-1.13.1}/PKG-INFO +3 -1
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/pyproject.toml +3 -1
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm/__init__.py +2 -0
- projectdavid_orm-1.13.1/src/projectdavid_orm/enums.py +20 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm/ormInterface.py +2 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm/projectdavid_orm/models.py +75 -8
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1/src/projectdavid_orm.egg-info}/PKG-INFO +3 -1
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm.egg-info/SOURCES.txt +4 -1
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm.egg-info/requires.txt +2 -0
- projectdavid_orm-1.13.1/tests/test_runtime_dependency_boundary.py +57 -0
- projectdavid_orm-1.13.1/tests/test_scratchpad_public_exports.py +6 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/LICENSE +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/MANIFEST.in +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/README.md +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/setup.cfg +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_common.egg-info/PKG-INFO +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_common.egg-info/SOURCES.txt +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_common.egg-info/dependency_links.txt +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_common.egg-info/entry_points.txt +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_common.egg-info/requires.txt +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_common.egg-info/top_level.txt +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm/constants/__init__.py +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm/projectdavid_orm/__init__.py +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm/projectdavid_orm/base.py +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm/utilities/__init__.py +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm.egg-info/dependency_links.txt +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm.egg-info/top_level.txt +0 -0
- {projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/tests/test_clients.py +0 -0
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
## [1.13.1](https://github.com/project-david-ai/projectdavid-orm/compare/v1.13.0...v1.13.1) (2026-09-29)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **deps:** decouple ORM from Common runtime ([4e1ca2e](https://github.com/project-david-ai/projectdavid-orm/commit/4e1ca2e9b2a1b84d014fc0447849964bf974daf5))
|
|
7
|
+
* **exports:** expose Scratchpad through public ORM API ([205ae03](https://github.com/project-david-ai/projectdavid-orm/commit/205ae03ebe801701d9c19ce83e1b59764a8ab93b))
|
|
8
|
+
|
|
9
|
+
# [1.13.0](https://github.com/project-david-ai/projectdavid-orm/compare/v1.12.0...v1.13.0) (2026-09-29)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
* **schema:** add thread-associated scratchpad resource ([5e8d87c](https://github.com/project-david-ai/projectdavid-orm/commit/5e8d87c6641b4eed245feb42c373c91bd643cfc3))
|
|
15
|
+
|
|
1
16
|
# [1.12.0](https://github.com/project-david-ai/projectdavid-orm/compare/v1.11.0...v1.12.0) (2026-09-28)
|
|
2
17
|
|
|
3
18
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: projectdavid-orm
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.13.1
|
|
4
4
|
Summary: Shared SQLAlchemy ORM models for ProjectDavid services
|
|
5
5
|
Author-email: "Francis N." <engineering@projectdavid.co.uk>
|
|
6
6
|
License: PolyForm Noncommercial License 1.0.0
|
|
@@ -15,6 +15,8 @@ Requires-Dist: sqlalchemy>=2.0
|
|
|
15
15
|
Requires-Dist: pymysql
|
|
16
16
|
Requires-Dist: pydantic>=2.0
|
|
17
17
|
Requires-Dist: python-dotenv
|
|
18
|
+
Requires-Dist: passlib==1.7.4
|
|
19
|
+
Requires-Dist: bcrypt==4.0.1
|
|
18
20
|
Provides-Extra: dev
|
|
19
21
|
Requires-Dist: pytest; extra == "dev"
|
|
20
22
|
Requires-Dist: black==24.1.1; extra == "dev"
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "projectdavid-orm"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.13.1"
|
|
8
8
|
description = "Shared SQLAlchemy ORM models for ProjectDavid services"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
@@ -19,6 +19,8 @@ dependencies = [
|
|
|
19
19
|
"pymysql",
|
|
20
20
|
"pydantic>=2.0",
|
|
21
21
|
"python-dotenv",
|
|
22
|
+
"passlib==1.7.4",
|
|
23
|
+
"bcrypt==4.0.1",
|
|
22
24
|
]
|
|
23
25
|
|
|
24
26
|
[project.optional-dependencies]
|
|
@@ -15,6 +15,7 @@ from .ormInterface import (
|
|
|
15
15
|
OrmInterface,
|
|
16
16
|
Run,
|
|
17
17
|
Sandbox,
|
|
18
|
+
Scratchpad,
|
|
18
19
|
Thread,
|
|
19
20
|
TrainingJob,
|
|
20
21
|
User,
|
|
@@ -36,6 +37,7 @@ __all__ = [
|
|
|
36
37
|
"Assistant",
|
|
37
38
|
"Action",
|
|
38
39
|
"Sandbox",
|
|
40
|
+
"Scratchpad",
|
|
39
41
|
# File system
|
|
40
42
|
"File",
|
|
41
43
|
"FileStorage",
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class StatusEnum(str, Enum):
|
|
5
|
+
"""Canonical persistence status values used by ORM models."""
|
|
6
|
+
|
|
7
|
+
deleted = "deleted"
|
|
8
|
+
active = "active"
|
|
9
|
+
queued = "queued"
|
|
10
|
+
in_progress = "in_progress"
|
|
11
|
+
pending_action = "action_required"
|
|
12
|
+
completed = "completed"
|
|
13
|
+
failed = "failed"
|
|
14
|
+
cancelling = "cancelling"
|
|
15
|
+
cancelled = "cancelled"
|
|
16
|
+
pending = "pending"
|
|
17
|
+
processing = "processing"
|
|
18
|
+
expired = "expired"
|
|
19
|
+
retrying = "retrying"
|
|
20
|
+
offline = "offline"
|
{projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm/projectdavid_orm/models.py
RENAMED
|
@@ -3,9 +3,6 @@ import time
|
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
|
|
5
5
|
from passlib.context import CryptContext
|
|
6
|
-
from projectdavid_common import ValidationInterface
|
|
7
|
-
from projectdavid_common.schemas.enums import StatusEnum
|
|
8
|
-
from projectdavid_common.utilities.logging_service import LoggingUtility
|
|
9
6
|
from sqlalchemy import JSON, BigInteger, Boolean, Column, DateTime
|
|
10
7
|
from sqlalchemy import Enum as SAEnum
|
|
11
8
|
from sqlalchemy import (
|
|
@@ -22,11 +19,9 @@ from sqlalchemy import (
|
|
|
22
19
|
from sqlalchemy.ext.mutable import MutableDict
|
|
23
20
|
from sqlalchemy.orm import joinedload, relationship
|
|
24
21
|
|
|
25
|
-
from .
|
|
26
|
-
|
|
27
|
-
logger = LoggingUtility()
|
|
22
|
+
from projectdavid_orm.enums import StatusEnum
|
|
28
23
|
|
|
29
|
-
|
|
24
|
+
from .base import Base
|
|
30
25
|
|
|
31
26
|
# --- Association Tables ---
|
|
32
27
|
|
|
@@ -195,6 +190,12 @@ class User(Base):
|
|
|
195
190
|
lazy="select",
|
|
196
191
|
)
|
|
197
192
|
|
|
193
|
+
scratchpads = relationship(
|
|
194
|
+
"Scratchpad",
|
|
195
|
+
back_populates="owner",
|
|
196
|
+
lazy="select",
|
|
197
|
+
)
|
|
198
|
+
|
|
198
199
|
__table_args__ = (
|
|
199
200
|
UniqueConstraint(
|
|
200
201
|
"oauth_provider", "provider_user_id", name="uq_user_oauth_provider_id"
|
|
@@ -269,6 +270,72 @@ class Thread(Base):
|
|
|
269
270
|
)
|
|
270
271
|
owner = relationship("User", foreign_keys=[owner_id], lazy="select")
|
|
271
272
|
|
|
273
|
+
scratchpad = relationship(
|
|
274
|
+
"Scratchpad",
|
|
275
|
+
back_populates="thread",
|
|
276
|
+
uselist=False,
|
|
277
|
+
cascade="all, delete-orphan",
|
|
278
|
+
single_parent=True,
|
|
279
|
+
lazy="select",
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
class Scratchpad(Base):
|
|
284
|
+
"""Tenant-owned working-memory resource associated with one thread."""
|
|
285
|
+
|
|
286
|
+
__tablename__ = "scratchpads"
|
|
287
|
+
|
|
288
|
+
id = Column(String(64), primary_key=True, index=True)
|
|
289
|
+
|
|
290
|
+
owner_id = Column(
|
|
291
|
+
String(64),
|
|
292
|
+
ForeignKey("users.id", ondelete="CASCADE"),
|
|
293
|
+
nullable=False,
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
thread_id = Column(
|
|
297
|
+
String(64),
|
|
298
|
+
ForeignKey("threads.id", ondelete="CASCADE"),
|
|
299
|
+
nullable=False,
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
created_at = Column(DateTime, nullable=False, default=datetime.utcnow)
|
|
303
|
+
updated_at = Column(
|
|
304
|
+
DateTime,
|
|
305
|
+
nullable=False,
|
|
306
|
+
default=datetime.utcnow,
|
|
307
|
+
onupdate=datetime.utcnow,
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
meta_data = Column(
|
|
311
|
+
MutableDict.as_mutable(JSON),
|
|
312
|
+
nullable=False,
|
|
313
|
+
default=dict,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
owner = relationship(
|
|
317
|
+
"User",
|
|
318
|
+
back_populates="scratchpads",
|
|
319
|
+
lazy="select",
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
thread = relationship(
|
|
323
|
+
"Thread",
|
|
324
|
+
back_populates="scratchpad",
|
|
325
|
+
lazy="select",
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
__table_args__ = (
|
|
329
|
+
UniqueConstraint(
|
|
330
|
+
"thread_id",
|
|
331
|
+
name="uq_scratchpads_thread_id",
|
|
332
|
+
),
|
|
333
|
+
Index(
|
|
334
|
+
"idx_scratchpads_owner_id",
|
|
335
|
+
"owner_id",
|
|
336
|
+
),
|
|
337
|
+
)
|
|
338
|
+
|
|
272
339
|
|
|
273
340
|
class Message(Base):
|
|
274
341
|
__tablename__ = "messages"
|
|
@@ -356,7 +423,7 @@ class Run(Base):
|
|
|
356
423
|
required_action = Column(String(256), nullable=True)
|
|
357
424
|
response_format = Column(String(64), nullable=True)
|
|
358
425
|
|
|
359
|
-
status = Column(SAEnum(
|
|
426
|
+
status = Column(SAEnum(StatusEnum), nullable=False)
|
|
360
427
|
|
|
361
428
|
thread_id = Column(String(64), nullable=False)
|
|
362
429
|
tool_choice = Column(String(64), nullable=True)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: projectdavid-orm
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.13.1
|
|
4
4
|
Summary: Shared SQLAlchemy ORM models for ProjectDavid services
|
|
5
5
|
Author-email: "Francis N." <engineering@projectdavid.co.uk>
|
|
6
6
|
License: PolyForm Noncommercial License 1.0.0
|
|
@@ -15,6 +15,8 @@ Requires-Dist: sqlalchemy>=2.0
|
|
|
15
15
|
Requires-Dist: pymysql
|
|
16
16
|
Requires-Dist: pydantic>=2.0
|
|
17
17
|
Requires-Dist: python-dotenv
|
|
18
|
+
Requires-Dist: passlib==1.7.4
|
|
19
|
+
Requires-Dist: bcrypt==4.0.1
|
|
18
20
|
Provides-Extra: dev
|
|
19
21
|
Requires-Dist: pytest; extra == "dev"
|
|
20
22
|
Requires-Dist: black==24.1.1; extra == "dev"
|
{projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm.egg-info/SOURCES.txt
RENAMED
|
@@ -10,6 +10,7 @@ src/projectdavid_common.egg-info/entry_points.txt
|
|
|
10
10
|
src/projectdavid_common.egg-info/requires.txt
|
|
11
11
|
src/projectdavid_common.egg-info/top_level.txt
|
|
12
12
|
src/projectdavid_orm/__init__.py
|
|
13
|
+
src/projectdavid_orm/enums.py
|
|
13
14
|
src/projectdavid_orm/ormInterface.py
|
|
14
15
|
src/projectdavid_orm.egg-info/PKG-INFO
|
|
15
16
|
src/projectdavid_orm.egg-info/SOURCES.txt
|
|
@@ -21,4 +22,6 @@ src/projectdavid_orm/projectdavid_orm/__init__.py
|
|
|
21
22
|
src/projectdavid_orm/projectdavid_orm/base.py
|
|
22
23
|
src/projectdavid_orm/projectdavid_orm/models.py
|
|
23
24
|
src/projectdavid_orm/utilities/__init__.py
|
|
24
|
-
tests/test_clients.py
|
|
25
|
+
tests/test_clients.py
|
|
26
|
+
tests/test_runtime_dependency_boundary.py
|
|
27
|
+
tests/test_scratchpad_public_exports.py
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from projectdavid_orm.enums import StatusEnum
|
|
4
|
+
from projectdavid_orm.projectdavid_orm.models import ApiKey
|
|
5
|
+
|
|
6
|
+
EXPECTED_STATUS_VALUES = {
|
|
7
|
+
"deleted": "deleted",
|
|
8
|
+
"active": "active",
|
|
9
|
+
"queued": "queued",
|
|
10
|
+
"in_progress": "in_progress",
|
|
11
|
+
"pending_action": "action_required",
|
|
12
|
+
"completed": "completed",
|
|
13
|
+
"failed": "failed",
|
|
14
|
+
"cancelling": "cancelling",
|
|
15
|
+
"cancelled": "cancelled",
|
|
16
|
+
"pending": "pending",
|
|
17
|
+
"processing": "processing",
|
|
18
|
+
"expired": "expired",
|
|
19
|
+
"retrying": "retrying",
|
|
20
|
+
"offline": "offline",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_status_enum_persistence_contract_is_preserved():
|
|
25
|
+
assert {item.name: item.value for item in StatusEnum} == EXPECTED_STATUS_VALUES
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_models_have_no_runtime_dependency_on_common():
|
|
29
|
+
models_path = (
|
|
30
|
+
Path(__file__).parents[1]
|
|
31
|
+
/ "src"
|
|
32
|
+
/ "projectdavid_orm"
|
|
33
|
+
/ "projectdavid_orm"
|
|
34
|
+
/ "models.py"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
source = models_path.read_text(encoding="utf-8")
|
|
38
|
+
|
|
39
|
+
assert "projectdavid_common" not in source
|
|
40
|
+
assert "ValidationInterface" not in source
|
|
41
|
+
assert "LoggingUtility" not in source
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_bcrypt_backend_hashes_and_verifies_api_keys():
|
|
45
|
+
plain = "project-david-runtime-dependency-probe"
|
|
46
|
+
|
|
47
|
+
hashed = ApiKey.hash_key(plain)
|
|
48
|
+
|
|
49
|
+
assert hashed != plain
|
|
50
|
+
|
|
51
|
+
api_key = ApiKey(
|
|
52
|
+
key_name="dependency-probe",
|
|
53
|
+
hashed_key=hashed,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
assert api_key.verify_key(plain)
|
|
57
|
+
assert not api_key.verify_key(plain + "-invalid")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_common.egg-info/PKG-INFO
RENAMED
|
File without changes
|
{projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_common.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_common.egg-info/requires.txt
RENAMED
|
File without changes
|
{projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_common.egg-info/top_level.txt
RENAMED
|
File without changes
|
{projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm/constants/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm/projectdavid_orm/base.py
RENAMED
|
File without changes
|
{projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm/utilities/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{projectdavid_orm-1.12.0 → projectdavid_orm-1.13.1}/src/projectdavid_orm.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|