swiftpy-framework 0.1.0__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.
- swiftpy/.gitignore +0 -0
- swiftpy/__init__.py +572 -0
- swiftpy/admin/__init__.py +50 -0
- swiftpy/admin/auth.py +522 -0
- swiftpy/admin/registry.py +567 -0
- swiftpy/admin/views.py +1583 -0
- swiftpy/ai/__init__.py +199 -0
- swiftpy/ai/_deterministic.py +40 -0
- swiftpy/ai/_fake.py +604 -0
- swiftpy/ai/agents/__init__.py +30 -0
- swiftpy/ai/agents/base_agent.py +506 -0
- swiftpy/ai/agents/memory.py +864 -0
- swiftpy/ai/client.py +1011 -0
- swiftpy/ai/conversation.py +171 -0
- swiftpy/ai/embeddings.py +321 -0
- swiftpy/ai/exceptions.py +75 -0
- swiftpy/ai/history_strategies.py +157 -0
- swiftpy/ai/middleware.py +918 -0
- swiftpy/ai/observability/__init__.py +28 -0
- swiftpy/ai/observability/drivers.py +763 -0
- swiftpy/ai/observability/observer.py +364 -0
- swiftpy/ai/pool.py +102 -0
- swiftpy/ai/pricing.py +101 -0
- swiftpy/ai/prompts/__init__.py +6 -0
- swiftpy/ai/prompts/loader.py +343 -0
- swiftpy/ai/providers/__init__.py +22 -0
- swiftpy/ai/providers/anthropic_provider.py +353 -0
- swiftpy/ai/providers/base.py +273 -0
- swiftpy/ai/providers/openai_provider.py +275 -0
- swiftpy/ai/rag/__init__.py +53 -0
- swiftpy/ai/rag/context_formatter.py +263 -0
- swiftpy/ai/rag/pipeline_builder.py +544 -0
- swiftpy/ai/rag/reranker.py +484 -0
- swiftpy/ai/rag/result.py +78 -0
- swiftpy/ai/rag/retriever.py +315 -0
- swiftpy/ai/redis_store.py +227 -0
- swiftpy/ai/streaming.py +115 -0
- swiftpy/ai/tools/__init__.py +22 -0
- swiftpy/ai/tools/base_tool.py +489 -0
- swiftpy/ai/tools/first_party.py +384 -0
- swiftpy/ai/tools/tool_loop.py +417 -0
- swiftpy/ai/vectorstore/__init__.py +46 -0
- swiftpy/ai/vectorstore/base.py +542 -0
- swiftpy/ai/vectorstore/chroma_adapter.py +435 -0
- swiftpy/ai/vectorstore/in_memory_adapter.py +321 -0
- swiftpy/ai/vectorstore/lancedb_adapter.py +370 -0
- swiftpy/ai/vectorstore/pgvector_adapter.py +496 -0
- swiftpy/ai/vectorstore/pinecone_adapter.py +445 -0
- swiftpy/ai/vectorstore/qdrant_adapter.py +418 -0
- swiftpy/auth/__init__.py +50 -0
- swiftpy/auth/api_key_guard.py +544 -0
- swiftpy/auth/auth_manager.py +259 -0
- swiftpy/auth/exceptions.py +71 -0
- swiftpy/auth/jwt_guard.py +230 -0
- swiftpy/auth/jwt_issuer.py +658 -0
- swiftpy/auth/token_blacklist.py +300 -0
- swiftpy/cache/__init__.py +14 -0
- swiftpy/cache/cache.py +251 -0
- swiftpy/cache/driver.py +216 -0
- swiftpy/cache/drivers/memory.py +199 -0
- swiftpy/cache/drivers/redis.py +421 -0
- swiftpy/console/__init__.py +0 -0
- swiftpy/console/cli.py +68 -0
- swiftpy/console/commands/__init__.py +0 -0
- swiftpy/console/commands/cache.py +164 -0
- swiftpy/console/commands/make.py +935 -0
- swiftpy/console/commands/migrate.py +280 -0
- swiftpy/console/commands/new.py +1806 -0
- swiftpy/console/commands/queue.py +306 -0
- swiftpy/console/commands/seed.py +252 -0
- swiftpy/console/commands/start.py +171 -0
- swiftpy/console/commands/storage.py +104 -0
- swiftpy/console/loader.py +21 -0
- swiftpy/console/stubs/__init__.py +26 -0
- swiftpy/console/stubs/controller.stub +14 -0
- swiftpy/console/stubs/event.stub +14 -0
- swiftpy/console/stubs/job.stub +22 -0
- swiftpy/console/stubs/listener.stub +14 -0
- swiftpy/console/stubs/mail.stub +20 -0
- swiftpy/console/stubs/middleware.stub +16 -0
- swiftpy/console/stubs/migration.alter.stub +17 -0
- swiftpy/console/stubs/migration.api_keys.stub +22 -0
- swiftpy/console/stubs/migration.blank.stub +11 -0
- swiftpy/console/stubs/migration.create.stub +15 -0
- swiftpy/console/stubs/migration.stub +11 -0
- swiftpy/console/stubs/migration.update.stub +17 -0
- swiftpy/console/stubs/model.stub +17 -0
- swiftpy/console/stubs/provider.stub +18 -0
- swiftpy/console/stubs/repository.stub +10 -0
- swiftpy/console/stubs/request.stub +16 -0
- swiftpy/console/stubs/resource.stub +21 -0
- swiftpy/console/stubs/schema.stub +12 -0
- swiftpy/console/stubs/seeder.stub +14 -0
- swiftpy/console/stubs/service.stub +10 -0
- swiftpy/core/__init__.py +0 -0
- swiftpy/core/application.py +1306 -0
- swiftpy/core/bootstrap.py +30 -0
- swiftpy/core/config.py +432 -0
- swiftpy/core/container.py +596 -0
- swiftpy/core/container_exceptions.py +18 -0
- swiftpy/core/context.py +148 -0
- swiftpy/core/exceptions.py +352 -0
- swiftpy/core/providers/base.py +35 -0
- swiftpy/database/__init__.py +41 -0
- swiftpy/database/exceptions.py +42 -0
- swiftpy/database/identifiers.py +105 -0
- swiftpy/database/migrations/__init__.py +36 -0
- swiftpy/database/migrations/blueprint.py +431 -0
- swiftpy/database/migrations/lock.py +104 -0
- swiftpy/database/migrations/migration.py +22 -0
- swiftpy/database/migrations/migrator.py +507 -0
- swiftpy/database/migrations/schema.py +435 -0
- swiftpy/database/orm/__init__.py +33 -0
- swiftpy/database/orm/fields.py +92 -0
- swiftpy/database/orm/model.py +2034 -0
- swiftpy/database/orm/registry.py +33 -0
- swiftpy/database/orm/relationships.py +836 -0
- swiftpy/database/pagination/__init__.py +16 -0
- swiftpy/database/pagination/contracts.py +60 -0
- swiftpy/database/pagination/paginator.py +112 -0
- swiftpy/database/pagination/simple_paginator.py +97 -0
- swiftpy/database/pool.py +218 -0
- swiftpy/database/query_builder.py +1803 -0
- swiftpy/database/seeder.py +39 -0
- swiftpy/database/transaction.py +276 -0
- swiftpy/events/__init__.py +10 -0
- swiftpy/events/dispatcher.py +308 -0
- swiftpy/events/redis_bus.py +552 -0
- swiftpy/filesystem/__init__.py +227 -0
- swiftpy/filesystem/disk.py +378 -0
- swiftpy/filesystem/drivers/__init__.py +11 -0
- swiftpy/filesystem/drivers/base.py +156 -0
- swiftpy/filesystem/drivers/local.py +559 -0
- swiftpy/filesystem/drivers/s3.py +655 -0
- swiftpy/filesystem/events.py +37 -0
- swiftpy/filesystem/exceptions.py +127 -0
- swiftpy/filesystem/manager.py +138 -0
- swiftpy/filesystem/metadata.py +22 -0
- swiftpy/filesystem/paths.py +99 -0
- swiftpy/filesystem/service_provider.py +17 -0
- swiftpy/filesystem/uploads/__init__.py +13 -0
- swiftpy/filesystem/uploads/handlers.py +362 -0
- swiftpy/filesystem/uploads/uploaded_file.py +222 -0
- swiftpy/filesystem/uploads/validators.py +186 -0
- swiftpy/filesystem/visibility.py +22 -0
- swiftpy/helpers/__init__.py +42 -0
- swiftpy/helpers/helper.py +180 -0
- swiftpy/http/exceptions.py +41 -0
- swiftpy/http/middleware.py +307 -0
- swiftpy/http/request.py +375 -0
- swiftpy/http/response.py +442 -0
- swiftpy/http/router.py +1050 -0
- swiftpy/mail/__init__.py +58 -0
- swiftpy/mail/attachments.py +255 -0
- swiftpy/mail/config.py +71 -0
- swiftpy/mail/envelope.py +183 -0
- swiftpy/mail/exceptions.py +90 -0
- swiftpy/mail/facade.py +312 -0
- swiftpy/mail/mailable.py +53 -0
- swiftpy/mail/manager.py +240 -0
- swiftpy/mail/message.py +186 -0
- swiftpy/mail/models.py +19 -0
- swiftpy/mail/queue/__init__.py +5 -0
- swiftpy/mail/queue/job.py +279 -0
- swiftpy/mail/service_provider.py +19 -0
- swiftpy/mail/templates/__init__.py +5 -0
- swiftpy/mail/templates/renderer.py +173 -0
- swiftpy/mail/transports/__init__.py +21 -0
- swiftpy/mail/transports/api/__init__.py +13 -0
- swiftpy/mail/transports/api/base.py +194 -0
- swiftpy/mail/transports/api/mailgun.py +158 -0
- swiftpy/mail/transports/api/resend.py +156 -0
- swiftpy/mail/transports/api/sendgrid.py +172 -0
- swiftpy/mail/transports/base.py +24 -0
- swiftpy/mail/transports/console.py +91 -0
- swiftpy/mail/transports/sendmail.py +128 -0
- swiftpy/mail/transports/smtp.py +466 -0
- swiftpy/queue/__init__.py +13 -0
- swiftpy/queue/dispatcher.py +813 -0
- swiftpy/queue/job.py +541 -0
- swiftpy/queue/worker.py +556 -0
- swiftpy/support/__init__.py +12 -0
- swiftpy/support/keys.py +108 -0
- swiftpy/support/redis_config.py +223 -0
- swiftpy/support/strings.py +114 -0
- swiftpy/testing/__init__.py +20 -0
- swiftpy/testing/fakes/__init__.py +11 -0
- swiftpy/testing/fakes/ai_fake.py +21 -0
- swiftpy/testing/fakes/vectorstore_fake.py +194 -0
- swiftpy/testing/fixtures.py +124 -0
- swiftpy/testing/http_client.py +730 -0
- swiftpy/testing/test_case.py +126 -0
- swiftpy/validation/__init__.py +97 -0
- swiftpy/validation/exceptions.py +26 -0
- swiftpy/validation/form_request.py +302 -0
- swiftpy/validation/protocols.py +33 -0
- swiftpy/validation/rules/__init__.py +89 -0
- swiftpy/validation/rules/builtin.py +391 -0
- swiftpy/validation/rules/exists.py +86 -0
- swiftpy/validation/rules/registry.py +290 -0
- swiftpy/validation/rules/required.py +55 -0
- swiftpy/validation/rules/unique.py +138 -0
- swiftpy/validation/validator.py +612 -0
- swiftpy/websockets/__init__.py +19 -0
- swiftpy/websockets/connection.py +317 -0
- swiftpy/websockets/manager.py +271 -0
- swiftpy_framework-0.1.0.dist-info/METADATA +603 -0
- swiftpy_framework-0.1.0.dist-info/RECORD +211 -0
- swiftpy_framework-0.1.0.dist-info/WHEEL +4 -0
- swiftpy_framework-0.1.0.dist-info/entry_points.txt +2 -0
- swiftpy_framework-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
from collections.abc import AsyncGenerator, Callable
|
|
6
|
+
from contextlib import asynccontextmanager
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
import asyncpg
|
|
10
|
+
|
|
11
|
+
from swiftpy.core.config import Config
|
|
12
|
+
from swiftpy.core.container import Container, get_container, set_container
|
|
13
|
+
from swiftpy.database.pool import DatabasePool
|
|
14
|
+
from swiftpy.database.transaction import TransactionConnection, _active_connection
|
|
15
|
+
|
|
16
|
+
_pytest_fixture: Any
|
|
17
|
+
try:
|
|
18
|
+
from pytest import fixture as _pytest_fixture
|
|
19
|
+
except ImportError:
|
|
20
|
+
_pytest_fixture = None
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger("swiftpy.testing.fixtures")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _build_standalone_config() -> Config:
|
|
26
|
+
"""Load configuration and apply DB_* fallbacks when no config/ directory exists."""
|
|
27
|
+
config = Config.load()
|
|
28
|
+
if not config.has("database.connections"):
|
|
29
|
+
default_conn = str(config.get("database.default", "postgresql"))
|
|
30
|
+
base = f"database.connections.{default_conn}"
|
|
31
|
+
env_defaults: list[tuple[str, str, Any]] = [
|
|
32
|
+
("DB_HOST", f"{base}.host", "127.0.0.1"),
|
|
33
|
+
("DB_PORT", f"{base}.port", 5432),
|
|
34
|
+
("DB_DATABASE", f"{base}.database", "swiftpy"),
|
|
35
|
+
("DB_USERNAME", f"{base}.user", "postgres"),
|
|
36
|
+
("DB_PASSWORD", f"{base}.password", ""),
|
|
37
|
+
]
|
|
38
|
+
for env_key, cfg_key, fallback in env_defaults:
|
|
39
|
+
raw = os.getenv(env_key)
|
|
40
|
+
val: Any = raw if raw is not None else fallback
|
|
41
|
+
if cfg_key.endswith(".port"):
|
|
42
|
+
val = int(val)
|
|
43
|
+
config.set(cfg_key, val)
|
|
44
|
+
return config
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@asynccontextmanager
|
|
48
|
+
async def transactional_test(
|
|
49
|
+
pool: DatabasePool | None = None,
|
|
50
|
+
) -> AsyncGenerator[TransactionConnection, None]:
|
|
51
|
+
"""
|
|
52
|
+
Wrap database operations in an isolated transaction that is rolled back on exit.
|
|
53
|
+
Self-contained: initializes an active DatabasePool automatically if one is not yet bound/ready.
|
|
54
|
+
"""
|
|
55
|
+
initialized_here = False
|
|
56
|
+
if pool is None:
|
|
57
|
+
try:
|
|
58
|
+
container = get_container()
|
|
59
|
+
except RuntimeError:
|
|
60
|
+
container = Container()
|
|
61
|
+
set_container(container)
|
|
62
|
+
|
|
63
|
+
if container.has(DatabasePool):
|
|
64
|
+
pool = container.resolve(DatabasePool)
|
|
65
|
+
else:
|
|
66
|
+
config = (
|
|
67
|
+
container.resolve(Config)
|
|
68
|
+
if container.has(Config)
|
|
69
|
+
else _build_standalone_config()
|
|
70
|
+
)
|
|
71
|
+
if not container.has(Config):
|
|
72
|
+
container.instance(Config, config)
|
|
73
|
+
pool = DatabasePool(config)
|
|
74
|
+
container.instance(DatabasePool, pool)
|
|
75
|
+
|
|
76
|
+
if not pool.is_initialized:
|
|
77
|
+
await pool.init()
|
|
78
|
+
initialized_here = True
|
|
79
|
+
|
|
80
|
+
db_pool = pool.get_pool()
|
|
81
|
+
conn = await db_pool.acquire()
|
|
82
|
+
handle = TransactionConnection(conn)
|
|
83
|
+
tx = conn.transaction()
|
|
84
|
+
await tx.start()
|
|
85
|
+
token = _active_connection.set(handle)
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
yield handle
|
|
89
|
+
finally:
|
|
90
|
+
try:
|
|
91
|
+
await handle.rollback_transaction(tx)
|
|
92
|
+
except (asyncpg.PostgresError, OSError):
|
|
93
|
+
logger.debug("Transaction rollback encountered an error", exc_info=True)
|
|
94
|
+
finally:
|
|
95
|
+
handle.close()
|
|
96
|
+
_active_connection.reset(token)
|
|
97
|
+
await db_pool.release(conn)
|
|
98
|
+
if initialized_here:
|
|
99
|
+
await pool.close()
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
async def _db_transaction_impl() -> AsyncGenerator[TransactionConnection, None]:
|
|
103
|
+
"""
|
|
104
|
+
Pytest fixture wrapping test execution in a rolled-back database transaction.
|
|
105
|
+
Works standalone without requiring external project-specific pool fixtures.
|
|
106
|
+
"""
|
|
107
|
+
async with transactional_test() as conn:
|
|
108
|
+
yield conn
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _missing_pytest_fixture() -> AsyncGenerator[TransactionConnection, None]:
|
|
112
|
+
raise RuntimeError(
|
|
113
|
+
"pytest is required to use the 'db_transaction' fixture."
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
db_transaction: Callable[[], AsyncGenerator[TransactionConnection, None]] | object
|
|
118
|
+
if _pytest_fixture is not None:
|
|
119
|
+
db_transaction = _pytest_fixture(name="db_transaction")(_db_transaction_impl)
|
|
120
|
+
else:
|
|
121
|
+
db_transaction = _missing_pytest_fixture
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
__all__ = ["db_transaction", "transactional_test"]
|