claudenv 1.3.0 → 1.3.2

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,62 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Коннектор к MSSQL: <%= name %> (host <%= host %>, db <%= database %>).
5
+ Сгенерирован claudenv (skill source-connector).
6
+
7
+ Креды читаются из .env.local (gitignored), НЕ хардкодятся:
8
+ <%= userEnv %>=<логин>
9
+ <%= passwordEnv %>=<пароль>
10
+
11
+ Зависимости: pip install pymssql sqlalchemy pandas
12
+ """
13
+
14
+ import os
15
+ import sys
16
+ from urllib.parse import quote_plus
17
+
18
+ import pandas as pd
19
+ from sqlalchemy import create_engine
20
+
21
+ HOST = os.getenv("<%= name.toUpperCase().replace(/[^A-Z0-9]/g, '_') %>_HOST", "<%= host %>")
22
+ PORT = os.getenv("<%= name.toUpperCase().replace(/[^A-Z0-9]/g, '_') %>_PORT", "<%= port || 1433 %>")
23
+ DATABASE = os.getenv("<%= name.toUpperCase().replace(/[^A-Z0-9]/g, '_') %>_DB", "<%= database %>")
24
+
25
+
26
+ def load_env_local(path=".env.local"):
27
+ env = {}
28
+ if os.path.exists(path):
29
+ with open(path, encoding="utf-8") as fh:
30
+ for line in fh:
31
+ line = line.strip()
32
+ if line and not line.startswith("#") and "=" in line:
33
+ k, _, v = line.partition("=")
34
+ env[k.strip()] = v.strip()
35
+ return env
36
+
37
+
38
+ _env = load_env_local()
39
+ USER = _env.get("<%= userEnv %>") or os.getenv("<%= userEnv %>")
40
+ PASSWORD = _env.get("<%= passwordEnv %>") or os.getenv("<%= passwordEnv %>")
41
+
42
+ if not USER or not PASSWORD:
43
+ sys.exit("Нет кред в .env.local: <%= userEnv %> / <%= passwordEnv %>")
44
+
45
+
46
+ def engine():
47
+ # пароль экранируем - в нём могут быть спецсимволы (@ : ~ и т.п.)
48
+ url = f"mssql+pymssql://{quote_plus(USER)}:{quote_plus(PASSWORD)}@{HOST}:{PORT}/{DATABASE}"
49
+ return create_engine(url)
50
+
51
+
52
+ def query(sql):
53
+ """Выполнить SELECT, вернуть DataFrame."""
54
+ return pd.read_sql(sql, engine())
55
+
56
+
57
+ if __name__ == "__main__":
58
+ sql = sys.argv[1] if len(sys.argv) > 1 else "SELECT 1 AS ok"
59
+ df = query(sql)
60
+ print(f"Строк: {len(df)}")
61
+ with pd.option_context("display.max_columns", None, "display.width", 200):
62
+ print(df.head(20).to_string(index=False))
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Коннектор к REST API: <%= name %> (base <%= host %>).
5
+ Сгенерирован claudenv (skill source-connector).
6
+
7
+ Токен читается из .env.local (gitignored), НЕ хардкодится:
8
+ <%= tokenEnv %>=<токен>
9
+
10
+ Зависимости: pip install requests
11
+ """
12
+
13
+ import os
14
+ import sys
15
+
16
+ import requests
17
+
18
+ BASE = os.getenv("<%= name.toUpperCase().replace(/[^A-Z0-9]/g, '_') %>_BASE", "<%= host %>")
19
+
20
+
21
+ def load_env_local(path=".env.local"):
22
+ env = {}
23
+ if os.path.exists(path):
24
+ with open(path, encoding="utf-8") as fh:
25
+ for line in fh:
26
+ line = line.strip()
27
+ if line and not line.startswith("#") and "=" in line:
28
+ k, _, v = line.partition("=")
29
+ env[k.strip()] = v.strip()
30
+ return env
31
+
32
+
33
+ _env = load_env_local()
34
+ TOKEN = _env.get("<%= tokenEnv %>") or os.getenv("<%= tokenEnv %>")
35
+
36
+ if not TOKEN:
37
+ sys.exit("Нет токена в .env.local: <%= tokenEnv %>")
38
+
39
+
40
+ def client():
41
+ s = requests.Session()
42
+ s.headers.update({
43
+ "Authorization": f"Bearer {TOKEN}",
44
+ "Accept": "application/json",
45
+ })
46
+ return s
47
+
48
+
49
+ def get(path, **params):
50
+ """GET к API, вернуть JSON. path - относительный (/api/...)."""
51
+ r = client().get(f"{BASE}{path}", params=params, timeout=30)
52
+ r.raise_for_status()
53
+ return r.json()
54
+
55
+
56
+ if __name__ == "__main__":
57
+ path = sys.argv[1] if len(sys.argv) > 1 else "/"
58
+ import json
59
+ print(json.dumps(get(path), ensure_ascii=False, indent=2)[:2000])