pythia-plsql 0.3.1__tar.gz → 0.3.2__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.
- {pythia_plsql-0.3.1/scripts/pythia_plsql.egg-info → pythia_plsql-0.3.2}/PKG-INFO +1 -1
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/pyproject.toml +1 -1
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/scripts/pythia.py +43 -8
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2/scripts/pythia_plsql.egg-info}/PKG-INFO +1 -1
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/tests/test_install.py +23 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/tests/test_phase3.py +29 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/LICENSE +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/README.md +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/queries/compile-errors.sql +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/queries/dependencies.sql +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/queries/impact.sql +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/queries/invalid-objects.sql +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/queries/name-occupants.sql +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/queries/object-source.sql +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/queries/plscope-enabled.sql +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/queries/plscope-statements.sql +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/queries/plscope-usages.sql +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/queries/session-privileges.sql +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/queries/similar-candidates.sql +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/queries/source.sql +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/scripts/pythia_plsql.egg-info/SOURCES.txt +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/scripts/pythia_plsql.egg-info/dependency_links.txt +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/scripts/pythia_plsql.egg-info/entry_points.txt +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/scripts/pythia_plsql.egg-info/requires.txt +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/scripts/pythia_plsql.egg-info/top_level.txt +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/setup.cfg +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/skills/pythia-apply/SKILL.md +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/skills/pythia-explore/SKILL.md +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/skills/pythia-explore/reference/data-dictionary.md +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/skills/pythia-impact/SKILL.md +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/skills/pythia-review/SKILL.md +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/skills/pythia-review/reference/antipatterns.md +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/skills/pythia-setup/SKILL.md +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/skills/pythia-skill-author/SKILL.md +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/skills/pythia-write/SKILL.md +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/skills/pythia-write/reference/patterns.md +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/tests/test_phase1.py +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/tests/test_phase2.py +0 -0
- {pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/tests/test_phase5.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythia-plsql
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: PL/SQL development for AI agents on Oracle Database - expert data-dictionary queries, impact analysis, and a snapshot-verified write path with honest rollback.
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/thaildhe172591/pythia
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pythia-plsql"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.2"
|
|
8
8
|
description = "PL/SQL development for AI agents on Oracle Database - expert data-dictionary queries, impact analysis, and a snapshot-verified write path with honest rollback."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -209,16 +209,30 @@ HEADLESS_YES_MSG = (
|
|
|
209
209
|
|
|
210
210
|
|
|
211
211
|
def human_at_the_keyboard():
|
|
212
|
-
"""True only when a person is typing
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
212
|
+
"""True only when a person is typing at a real console.
|
|
213
|
+
|
|
214
|
+
isatty() alone is not enough on Windows: NUL is a character device, so
|
|
215
|
+
a subprocess launched with stdin=DEVNULL reports isatty() == True and
|
|
216
|
+
would sail straight through this gate. Only a real console answers
|
|
217
|
+
GetConsoleMode, so ask that too. PYTHIA_CI=1 is the documented escape
|
|
218
|
+
for real pipelines."""
|
|
216
219
|
if os.environ.get("PYTHIA_CI"):
|
|
217
220
|
return True
|
|
218
221
|
try:
|
|
219
|
-
|
|
222
|
+
if not sys.stdin.isatty():
|
|
223
|
+
return False
|
|
220
224
|
except (AttributeError, ValueError):
|
|
221
225
|
return False
|
|
226
|
+
if os.name == "nt":
|
|
227
|
+
try:
|
|
228
|
+
import ctypes
|
|
229
|
+
handle = ctypes.windll.kernel32.GetStdHandle(-10) # STD_INPUT
|
|
230
|
+
mode = ctypes.c_ulong()
|
|
231
|
+
return bool(ctypes.windll.kernel32.GetConsoleMode(
|
|
232
|
+
handle, ctypes.byref(mode)))
|
|
233
|
+
except Exception: # noqa: BLE001 — any failure means "not a console"
|
|
234
|
+
return False
|
|
235
|
+
return True
|
|
222
236
|
|
|
223
237
|
|
|
224
238
|
def forbid_write_flag(argv):
|
|
@@ -617,6 +631,12 @@ def load_settings(root):
|
|
|
617
631
|
sys.exit(f"Cannot parse {path}: {e}")
|
|
618
632
|
|
|
619
633
|
|
|
634
|
+
def undo_group_action(ns):
|
|
635
|
+
"""Undoing a CREATE is a DROP, which is `structural` — so the policy on
|
|
636
|
+
that group decides whether the restore command we print can run."""
|
|
637
|
+
return load_policy(ns.project_root)["structural"][0]
|
|
638
|
+
|
|
639
|
+
|
|
620
640
|
def journal_root(root):
|
|
621
641
|
return pathlib.Path(root) / CONFIG_DIR / "journal"
|
|
622
642
|
|
|
@@ -1237,6 +1257,9 @@ def run_apply(conn, schema, ns, file_text, origin=None):
|
|
|
1237
1257
|
"type": otype, "errors": [list(r) for r in own_errors],
|
|
1238
1258
|
"newly_invalid": [list(x) for x in broke],
|
|
1239
1259
|
"restore": f"{invocation()} journal restore {entry}",
|
|
1260
|
+
"restore_is_drop": created,
|
|
1261
|
+
"restore_blocked_by_policy": (
|
|
1262
|
+
created and undo_group_action(ns) == "deny"),
|
|
1240
1263
|
"exit": 0 if ok else 3}))
|
|
1241
1264
|
else:
|
|
1242
1265
|
en = getattr(ns, "color", False)
|
|
@@ -1257,9 +1280,21 @@ def run_apply(conn, schema, ns, file_text, origin=None):
|
|
|
1257
1280
|
print(f" {len(broke)} objects were VALID before and are INVALID now:")
|
|
1258
1281
|
for n2, t2 in broke:
|
|
1259
1282
|
print(paint(f" {n2} ({t2})", "red", en))
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1283
|
+
if created:
|
|
1284
|
+
print("\n To undo — note: undo means DROPPING it "
|
|
1285
|
+
"(it did not exist before):")
|
|
1286
|
+
else:
|
|
1287
|
+
print("\n To undo:")
|
|
1288
|
+
print(" " + paint(f"{invocation()} journal restore {entry}",
|
|
1289
|
+
"cyan", en))
|
|
1290
|
+
if created and undo_group_action(ns) == "deny":
|
|
1291
|
+
# the honest half: that restore is a DROP, DROP is structural,
|
|
1292
|
+
# and structural is deny — so the line above would be refused
|
|
1293
|
+
print(paint(" ...but that restore is a DROP, and structural is "
|
|
1294
|
+
"set to deny, so it will be refused.", "yellow", en))
|
|
1295
|
+
print(paint(" The developer decides: "
|
|
1296
|
+
f"{invocation()} policy set structural confirm",
|
|
1297
|
+
"yellow", en))
|
|
1263
1298
|
return 0 if ok else 3
|
|
1264
1299
|
|
|
1265
1300
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pythia-plsql
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: PL/SQL development for AI agents on Oracle Database - expert data-dictionary queries, impact analysis, and a snapshot-verified write path with honest rollback.
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/thaildhe172591/pythia
|
|
@@ -122,6 +122,29 @@ def test_agent_user_json_saves_the_same_password_it_prints():
|
|
|
122
122
|
os.chdir(cwd)
|
|
123
123
|
|
|
124
124
|
|
|
125
|
+
def test_devnull_stdin_is_not_a_human():
|
|
126
|
+
"""The gate must hold for a real subprocess, not just in theory. On
|
|
127
|
+
Windows NUL is a character device and isatty() says True for it, so a
|
|
128
|
+
stdin=DEVNULL child would otherwise self-approve writes."""
|
|
129
|
+
import os
|
|
130
|
+
import subprocess
|
|
131
|
+
env = {k: v for k, v in os.environ.items() if k != "PYTHIA_CI"}
|
|
132
|
+
with tempfile.TemporaryDirectory() as td:
|
|
133
|
+
(pathlib.Path(td) / ".pythia").mkdir()
|
|
134
|
+
(pathlib.Path(td) / ".pythia" / "connections.json").write_text(
|
|
135
|
+
json.dumps({"dev": {"host": "h", "user": "U", "password": "p",
|
|
136
|
+
"schema": "U"}}), encoding="utf-8")
|
|
137
|
+
env["PYTHONPATH"] = str(ROOT / "scripts") # -m pythia from the repo
|
|
138
|
+
r = subprocess.run(
|
|
139
|
+
[sys.executable, "-m", "pythia", "policy", "set", "structural",
|
|
140
|
+
"allow"],
|
|
141
|
+
cwd=td, env=env, stdin=subprocess.DEVNULL, text=True,
|
|
142
|
+
capture_output=True)
|
|
143
|
+
assert r.returncode != 0, r.stdout + r.stderr
|
|
144
|
+
assert "developer" in (r.stdout + r.stderr).lower()
|
|
145
|
+
assert not (pathlib.Path(td) / ".pythia" / "policy.json").is_file()
|
|
146
|
+
|
|
147
|
+
|
|
125
148
|
def test_one_version_across_every_manifest():
|
|
126
149
|
"""pyproject, plugin.json, marketplace.json and npm/package.json must all
|
|
127
150
|
carry the same version — the release workflow publishes from one tag."""
|
|
@@ -658,6 +658,35 @@ def test_headless_policy_loosening_is_refused_tightening_allowed():
|
|
|
658
658
|
assert pythia.load_policy(td)["plsql_source"][0] == "deny"
|
|
659
659
|
|
|
660
660
|
|
|
661
|
+
def test_report_admits_a_created_objects_undo_is_blocked():
|
|
662
|
+
"""pythia exists so nothing lies about rollback. Undoing a CREATE is a
|
|
663
|
+
DROP, DROP is structural, and structural is deny by default — so the
|
|
664
|
+
printed restore command would be refused. Say so, in the same breath."""
|
|
665
|
+
import contextlib
|
|
666
|
+
import io
|
|
667
|
+
with tempfile.TemporaryDirectory() as td:
|
|
668
|
+
conn = FakeConn(base_script(db_source="")) # object did not exist
|
|
669
|
+
buf = io.StringIO()
|
|
670
|
+
with contextlib.redirect_stdout(buf):
|
|
671
|
+
pythia.run_apply(conn, "APP", apply_ns(td, file="f.sql", yes=True),
|
|
672
|
+
NEW_FILE)
|
|
673
|
+
out = buf.getvalue().lower()
|
|
674
|
+
assert "dropping it" in out
|
|
675
|
+
assert "will be refused" in out, out[-400:]
|
|
676
|
+
assert "policy set structural confirm" in out
|
|
677
|
+
# and once the developer has loosened it, the warning goes away
|
|
678
|
+
with tempfile.TemporaryDirectory() as td:
|
|
679
|
+
pathlib.Path(td, ".pythia").mkdir()
|
|
680
|
+
pathlib.Path(td, ".pythia", "policy.json").write_text(
|
|
681
|
+
'{"structural": "confirm"}', encoding="utf-8")
|
|
682
|
+
conn = FakeConn(base_script(db_source=""))
|
|
683
|
+
buf = io.StringIO()
|
|
684
|
+
with contextlib.redirect_stdout(buf):
|
|
685
|
+
pythia.run_apply(conn, "APP", apply_ns(td, file="f.sql", yes=True),
|
|
686
|
+
NEW_FILE)
|
|
687
|
+
assert "will be refused" not in buf.getvalue().lower()
|
|
688
|
+
|
|
689
|
+
|
|
661
690
|
def main():
|
|
662
691
|
failed = 0
|
|
663
692
|
for name, fn in sorted(globals().items()):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/scripts/pythia_plsql.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pythia_plsql-0.3.1 → pythia_plsql-0.3.2}/skills/pythia-explore/reference/data-dictionary.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|