neurocore-skill-postgres 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.
@@ -0,0 +1,5 @@
1
+ """neurocore-skill-postgres — PostgreSQL query skill for NeuroCore."""
2
+
3
+ from neurocore_skill_postgres.skill import PostgresSkill
4
+
5
+ __all__ = ["PostgresSkill"]
@@ -0,0 +1,68 @@
1
+ """PostgresSkill — run a parameterized SQL query against PostgreSQL.
2
+
3
+ Reads ``sql`` (and optional ``sql_params``) from context (config provides
4
+ defaults) and writes returned rows to ``postgres_rows``.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import logging
9
+ import os
10
+ from typing import Any
11
+
12
+ from flowengine import FlowContext
13
+
14
+ from neurocore import AsyncSkill, SkillMeta
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class PostgresSkill(AsyncSkill):
20
+ """Async parameterized SQL execution against PostgreSQL (psycopg 3)."""
21
+
22
+ skill_meta = SkillMeta(
23
+ name="postgres",
24
+ version="0.1.0",
25
+ description="Run parameterized SQL against PostgreSQL",
26
+ author="NeuroCore Contributors",
27
+ requires=["psycopg[binary]>=3.1"],
28
+ provides=["postgres_rows"],
29
+ consumes=["sql", "sql_params"],
30
+ tags=["database", "sql", "postgres"],
31
+ config_schema={
32
+ "properties": {
33
+ "dsn": {"type": "string", "description": "Connection string."},
34
+ "sql": {"type": "string", "description": "Default SQL (overridable)."},
35
+ }
36
+ },
37
+ )
38
+
39
+ def _resolve_dsn(self) -> str:
40
+ return self.config.get("dsn", "") or os.environ.get("DATABASE_URL", "")
41
+
42
+ async def _execute(self, sql: str, params: Any) -> list[dict[str, Any]]:
43
+ """Execute ``sql`` and return rows as dicts (empty for non-SELECT)."""
44
+ import psycopg
45
+ from psycopg.rows import dict_row
46
+
47
+ async with await psycopg.AsyncConnection.connect(
48
+ self._resolve_dsn(), row_factory=dict_row
49
+ ) as conn, conn.cursor() as cur:
50
+ await cur.execute(sql, params)
51
+ if cur.description is None:
52
+ await conn.commit()
53
+ return []
54
+ return [dict(row) for row in await cur.fetchall()]
55
+
56
+ async def process(self, context: FlowContext) -> FlowContext:
57
+ sql = str(context.get("sql") or self.config.get("sql", ""))
58
+ if not sql:
59
+ logger.warning("PostgresSkill: no 'sql' provided.")
60
+ context.set("postgres_rows", [])
61
+ return context
62
+ params = context.get("sql_params")
63
+ try:
64
+ context.set("postgres_rows", await self._execute(sql, params))
65
+ except Exception as exc: # noqa: BLE001
66
+ logger.error("PostgresSkill query failed: %s", exc, exc_info=True)
67
+ context.set("postgres_rows", {"error": str(exc)})
68
+ return context
@@ -0,0 +1,50 @@
1
+ Metadata-Version: 2.4
2
+ Name: neurocore-skill-postgres
3
+ Version: 0.1.0
4
+ Summary: PostgreSQL query skill for NeuroCore
5
+ Author: NeuroCore Contributors
6
+ License-Expression: Apache-2.0
7
+ Keywords: ai,database,neurocore,postgres,skill,sql
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
13
+ Classifier: Typing :: Typed
14
+ Requires-Python: >=3.13
15
+ Requires-Dist: neurocore-ai>=0.2.0
16
+ Requires-Dist: psycopg[binary]>=3.1
17
+ Provides-Extra: dev
18
+ Requires-Dist: mypy>=1.8; extra == 'dev'
19
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
20
+ Requires-Dist: pytest>=9.0.2; extra == 'dev'
21
+ Requires-Dist: ruff>=0.8; extra == 'dev'
22
+ Description-Content-Type: text/markdown
23
+
24
+ # neurocore-skill-postgres
25
+
26
+ Run parameterized SQL against PostgreSQL from a NeuroCore flow (psycopg 3).
27
+
28
+ ```bash
29
+ pip install neurocore-skill-postgres
30
+ export DATABASE_URL=postgresql://user:pass@localhost/db
31
+ ```
32
+
33
+ ```yaml
34
+ components:
35
+ - name: query
36
+ type: postgres
37
+ config:
38
+ sql: "SELECT id, name FROM users WHERE active = %s"
39
+ flow:
40
+ type: sequential
41
+ steps:
42
+ - component: query
43
+ ```
44
+
45
+ Provide `sql` (and optional `sql_params`) via config or context. Results are
46
+ written to `postgres_rows` (a list of row dicts; empty list for non-SELECT
47
+ statements, which are committed).
48
+
49
+ > Use parameterized queries (`%s` placeholders + `sql_params`) — never string
50
+ > interpolation — to avoid SQL injection.
@@ -0,0 +1,6 @@
1
+ neurocore_skill_postgres/__init__.py,sha256=LqqCjpEBYqFLlNmf5gIWEZ7_dfBsd3PfFp4vAApy61g,160
2
+ neurocore_skill_postgres/skill.py,sha256=Fp9tF8Zd1-kZ2c_ugRDR5NDWGa2DwnkH99LOULA6MiY,2456
3
+ neurocore_skill_postgres-0.1.0.dist-info/METADATA,sha256=uUEJAHWfSf9cm4DEy0kVAWEVvA564Oi2o2VCidpUXn0,1572
4
+ neurocore_skill_postgres-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
5
+ neurocore_skill_postgres-0.1.0.dist-info/entry_points.txt,sha256=umlQVsAYOny0WGAj6yYzC5lbhq4Km5VgLsRwJaPLKwc,69
6
+ neurocore_skill_postgres-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [neurocore.skills]
2
+ postgres = neurocore_skill_postgres:PostgresSkill