devmate 1.0.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.
- devmate/__init__.py +6 -0
- devmate/__main__.py +5 -0
- devmate/app/__init__.py +1 -0
- devmate/app/cli.py +1663 -0
- devmate/app/tui.py +291 -0
- devmate/app/web/__init__.py +95 -0
- devmate/bus/__init__.py +1 -0
- devmate/bus/bus.py +151 -0
- devmate/bus/command.py +84 -0
- devmate/core/__init__.py +1 -0
- devmate/core/config.py +115 -0
- devmate/core/logging.py +54 -0
- devmate/core/security.py +61 -0
- devmate/events/__init__.py +1 -0
- devmate/events/bus.py +97 -0
- devmate/events/domain_event.py +37 -0
- devmate/module/__init__.py +1 -0
- devmate/module/registry.py +74 -0
- devmate/security/audit.py +96 -0
- devmate/security/vault.py +221 -0
- devmate-1.0.0.dist-info/METADATA +116 -0
- devmate-1.0.0.dist-info/RECORD +37 -0
- devmate-1.0.0.dist-info/WHEEL +5 -0
- devmate-1.0.0.dist-info/entry_points.txt +18 -0
- devmate-1.0.0.dist-info/top_level.txt +13 -0
- devmate_agent/__init__.py +440 -0
- devmate_apidev/__init__.py +271 -0
- devmate_apihub/__init__.py +313 -0
- devmate_dbadmin/__init__.py +263 -0
- devmate_gitflow/__init__.py +247 -0
- devmate_monitor/__init__.py +112 -0
- devmate_notekeeper/__init__.py +280 -0
- devmate_regexlab/__init__.py +212 -0
- devmate_reporter/__init__.py +170 -0
- devmate_scaffold/__init__.py +181 -0
- devmate_sshman/__init__.py +330 -0
- devmate_toolkit/__init__.py +223 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"""
|
|
2
|
+
vault — 加密密钥管理器
|
|
3
|
+
|
|
4
|
+
加密体系:
|
|
5
|
+
主密码(用户输入)
|
|
6
|
+
↓ Argon2id KDF(salt + 内存硬参数)
|
|
7
|
+
256-bit 主密钥
|
|
8
|
+
↓ AES-256-GCM(随机 nonce,认证加密)
|
|
9
|
+
加密密钥值 → 写入 ~/.devmate/vault/keys/<name>
|
|
10
|
+
|
|
11
|
+
安全性:
|
|
12
|
+
- 主密码不存储,只存 KDF 参数和 salt
|
|
13
|
+
- 每次加密使用随机 nonce(12 字节)
|
|
14
|
+
- 认证标签确保密文完整性
|
|
15
|
+
- 锁定后 salt 和 nonce 从内存中清除
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
import os
|
|
20
|
+
|
|
21
|
+
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
|
22
|
+
from cryptography.hazmat.primitives.kdf.argon2 import Argon2id
|
|
23
|
+
|
|
24
|
+
from devmate.core.config import VAULT_PATH
|
|
25
|
+
from devmate.core.logging import logger
|
|
26
|
+
|
|
27
|
+
# ── 常量 ────────────────────────────────────────────────
|
|
28
|
+
|
|
29
|
+
KEYS_DIR = VAULT_PATH / "keys"
|
|
30
|
+
LOCK_MARKER = VAULT_PATH / ".locked"
|
|
31
|
+
METADATA_FILE = VAULT_PATH / "metadata.json"
|
|
32
|
+
NONCE_BYTES = 12 # AES-GCM 推荐 nonce 长度
|
|
33
|
+
KEY_BYTES = 32 # AES-256 = 32 字节
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# ── 异常 ────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
class VaultError(Exception):
|
|
39
|
+
"""vault 操作异常"""
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
class VaultLockedError(VaultError):
|
|
43
|
+
"""vault 已锁定"""
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
class VaultUnlockedError(VaultError):
|
|
47
|
+
"""vault 未锁定(不需要再 unlock)"""
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
class KeyNotFoundError(VaultError):
|
|
51
|
+
"""密钥不存在"""
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# ── Vault 核心 ──────────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
class Vault:
|
|
58
|
+
"""加密密钥管理器"""
|
|
59
|
+
|
|
60
|
+
def __init__(self):
|
|
61
|
+
self._key: bytes | None = None # 派生出的 256-bit 密钥(None = 锁定)
|
|
62
|
+
self._salt: bytes | None = None # KDF salt
|
|
63
|
+
self._params: dict | None = None # Argon2id 参数
|
|
64
|
+
|
|
65
|
+
# ── 属性 ────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def is_locked(self) -> bool:
|
|
69
|
+
"""vault 是否锁定"""
|
|
70
|
+
return self._key is None or LOCK_MARKER.exists()
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def is_unlocked(self) -> bool:
|
|
74
|
+
return not self.is_locked
|
|
75
|
+
|
|
76
|
+
# ── 初始化与目录管理 ────────────────────────
|
|
77
|
+
|
|
78
|
+
def _ensure_dirs(self):
|
|
79
|
+
"""确保 vault 目录存在"""
|
|
80
|
+
KEYS_DIR.mkdir(parents=True, exist_ok=True)
|
|
81
|
+
|
|
82
|
+
# ── 主密码处理 ──────────────────────────────
|
|
83
|
+
|
|
84
|
+
def _derive_key(self, master_password: str) -> bytes:
|
|
85
|
+
"""用 Argon2id 从主密码派生 256-bit 密钥"""
|
|
86
|
+
password_bytes = master_password.encode("utf-8")
|
|
87
|
+
|
|
88
|
+
if self._salt is None:
|
|
89
|
+
# 首次使用:生成随机 salt
|
|
90
|
+
self._salt = os.urandom(16)
|
|
91
|
+
self._params = {
|
|
92
|
+
"salt": self._salt.hex(),
|
|
93
|
+
"iterations": 3, # OWASP 推荐 ≥ 2
|
|
94
|
+
"memory_cost": 65536, # 64 MB
|
|
95
|
+
"lanes": 4,
|
|
96
|
+
"key_len": KEY_BYTES,
|
|
97
|
+
}
|
|
98
|
+
self._save_metadata()
|
|
99
|
+
|
|
100
|
+
kdf = Argon2id(
|
|
101
|
+
salt=bytes.fromhex(self._params["salt"]),
|
|
102
|
+
length=self._params["key_len"],
|
|
103
|
+
iterations=self._params["iterations"],
|
|
104
|
+
memory_cost=self._params["memory_cost"],
|
|
105
|
+
lanes=self._params["lanes"],
|
|
106
|
+
)
|
|
107
|
+
return kdf.derive(password_bytes)
|
|
108
|
+
|
|
109
|
+
# ── 元数据持久化 ────────────────────────────
|
|
110
|
+
|
|
111
|
+
def _save_metadata(self):
|
|
112
|
+
"""保存 KDF 参数到文件"""
|
|
113
|
+
data = {
|
|
114
|
+
"salt": self._params["salt"],
|
|
115
|
+
"iterations": self._params["iterations"],
|
|
116
|
+
"memory_cost": self._params["memory_cost"],
|
|
117
|
+
"lanes": self._params["lanes"],
|
|
118
|
+
"key_len": self._params["key_len"],
|
|
119
|
+
}
|
|
120
|
+
METADATA_FILE.write_text(json.dumps(data, indent=2))
|
|
121
|
+
|
|
122
|
+
def _load_metadata(self):
|
|
123
|
+
"""从文件加载 KDF 参数"""
|
|
124
|
+
if not METADATA_FILE.exists():
|
|
125
|
+
self._salt = None
|
|
126
|
+
self._params = None
|
|
127
|
+
return
|
|
128
|
+
data = json.loads(METADATA_FILE.read_text())
|
|
129
|
+
self._salt = bytes.fromhex(data["salt"])
|
|
130
|
+
self._params = data
|
|
131
|
+
|
|
132
|
+
# ── 核心操作 ────────────────────────────────
|
|
133
|
+
|
|
134
|
+
def unlock(self, master_password: str):
|
|
135
|
+
"""解锁 vault"""
|
|
136
|
+
if self.is_unlocked:
|
|
137
|
+
raise VaultUnlockedError("vault 已经解锁")
|
|
138
|
+
|
|
139
|
+
self._ensure_dirs()
|
|
140
|
+
self._load_metadata()
|
|
141
|
+
|
|
142
|
+
# 首次使用:创建新 vault
|
|
143
|
+
if self._params is None:
|
|
144
|
+
self._key = self._derive_key(master_password)
|
|
145
|
+
self._save_metadata()
|
|
146
|
+
else:
|
|
147
|
+
self._key = self._derive_key(master_password)
|
|
148
|
+
|
|
149
|
+
# 移除锁定标记
|
|
150
|
+
if LOCK_MARKER.exists():
|
|
151
|
+
LOCK_MARKER.unlink()
|
|
152
|
+
|
|
153
|
+
logger.info("vault 已解锁")
|
|
154
|
+
|
|
155
|
+
def lock(self):
|
|
156
|
+
"""锁定 vault(从内存中清除密钥)"""
|
|
157
|
+
self._key = None
|
|
158
|
+
self._salt = None
|
|
159
|
+
self._params = None
|
|
160
|
+
LOCK_MARKER.touch()
|
|
161
|
+
logger.info("vault 已锁定")
|
|
162
|
+
|
|
163
|
+
def set(self, name: str, value: str, master_password: str):
|
|
164
|
+
"""存储一个加密密钥"""
|
|
165
|
+
if self.is_locked:
|
|
166
|
+
self.unlock(master_password)
|
|
167
|
+
|
|
168
|
+
# 生成随机 nonce
|
|
169
|
+
nonce = os.urandom(NONCE_BYTES)
|
|
170
|
+
|
|
171
|
+
# AES-256-GCM 加密
|
|
172
|
+
aesgcm = AESGCM(self._key)
|
|
173
|
+
ciphertext = aesgcm.encrypt(nonce, value.encode("utf-8"), None)
|
|
174
|
+
|
|
175
|
+
# 存储:nonce + 密文(nonce 在前面,解密时需要)
|
|
176
|
+
key_file = KEYS_DIR / name
|
|
177
|
+
key_file.write_bytes(nonce + ciphertext)
|
|
178
|
+
logger.info(f"密钥已存储: {name}")
|
|
179
|
+
|
|
180
|
+
def get(self, name: str, master_password: str) -> str:
|
|
181
|
+
"""读取一个解密后的密钥"""
|
|
182
|
+
if self.is_locked:
|
|
183
|
+
self.unlock(master_password)
|
|
184
|
+
|
|
185
|
+
key_file = KEYS_DIR / name
|
|
186
|
+
if not key_file.exists():
|
|
187
|
+
raise KeyNotFoundError(f"密钥不存在: {name}")
|
|
188
|
+
|
|
189
|
+
data = key_file.read_bytes()
|
|
190
|
+
nonce = data[:NONCE_BYTES]
|
|
191
|
+
ciphertext = data[NONCE_BYTES:]
|
|
192
|
+
|
|
193
|
+
aesgcm = AESGCM(self._key)
|
|
194
|
+
plaintext = aesgcm.decrypt(nonce, ciphertext, None)
|
|
195
|
+
return plaintext.decode("utf-8")
|
|
196
|
+
|
|
197
|
+
def list(self) -> list[str]:
|
|
198
|
+
"""列出所有密钥名称(不需要解锁)"""
|
|
199
|
+
if not KEYS_DIR.exists():
|
|
200
|
+
return []
|
|
201
|
+
return sorted(f.name for f in KEYS_DIR.iterdir() if f.is_file())
|
|
202
|
+
|
|
203
|
+
def delete(self, name: str, master_password: str):
|
|
204
|
+
"""删除一个密钥"""
|
|
205
|
+
if self.is_locked:
|
|
206
|
+
self.unlock(master_password)
|
|
207
|
+
|
|
208
|
+
key_file = KEYS_DIR / name
|
|
209
|
+
if not key_file.exists():
|
|
210
|
+
raise KeyNotFoundError(f"密钥不存在: {name}")
|
|
211
|
+
key_file.unlink()
|
|
212
|
+
logger.info(f"密钥已删除: {name}")
|
|
213
|
+
|
|
214
|
+
def exists(self, name: str) -> bool:
|
|
215
|
+
"""检查密钥是否存在"""
|
|
216
|
+
return (KEYS_DIR / name).exists()
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
# ── 全局实例 ────────────────────────────────────────────
|
|
220
|
+
|
|
221
|
+
vault = Vault()
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: devmate
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: 程序员终端瑞士军刀——替代 5 个独立工具,一个 CLI 搞定
|
|
5
|
+
Author-email: DevMate Team <devmate@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: cli,developer-tools,terminal,productivity
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Topic :: Software Development
|
|
14
|
+
Classifier: Topic :: Utilities
|
|
15
|
+
Requires-Python: >=3.11
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
Requires-Dist: click>=8.1
|
|
18
|
+
Requires-Dist: rich>=13.0
|
|
19
|
+
Requires-Dist: pydantic>=2.0
|
|
20
|
+
Requires-Dist: pydantic-settings>=2.0
|
|
21
|
+
Requires-Dist: pyyaml>=6.0
|
|
22
|
+
Requires-Dist: sqlalchemy>=2.0
|
|
23
|
+
Requires-Dist: alembic>=1.13
|
|
24
|
+
Requires-Dist: cryptography>=42.0
|
|
25
|
+
Requires-Dist: httpx>=0.27
|
|
26
|
+
Provides-Extra: web
|
|
27
|
+
Requires-Dist: fastapi>=0.110; extra == "web"
|
|
28
|
+
Requires-Dist: uvicorn[standard]>=0.29; extra == "web"
|
|
29
|
+
Requires-Dist: jinja2>=3.1; extra == "web"
|
|
30
|
+
Requires-Dist: python-multipart>=0.0.9; extra == "web"
|
|
31
|
+
Requires-Dist: python-jose[cryptography]>=3.3; extra == "web"
|
|
32
|
+
Requires-Dist: passlib[bcrypt]>=1.7; extra == "web"
|
|
33
|
+
Provides-Extra: tui
|
|
34
|
+
Requires-Dist: textual>=1.0; extra == "tui"
|
|
35
|
+
Provides-Extra: ai
|
|
36
|
+
Requires-Dist: chromadb>=0.5; extra == "ai"
|
|
37
|
+
Requires-Dist: tiktoken>=0.7; extra == "ai"
|
|
38
|
+
Provides-Extra: dev
|
|
39
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
40
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
41
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
42
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
43
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
44
|
+
Provides-Extra: all
|
|
45
|
+
Requires-Dist: devmate[web]; extra == "all"
|
|
46
|
+
Requires-Dist: devmate[tui]; extra == "all"
|
|
47
|
+
Requires-Dist: devmate[ai]; extra == "all"
|
|
48
|
+
Requires-Dist: devmate[dev]; extra == "all"
|
|
49
|
+
|
|
50
|
+
# 🏗️ DevMate
|
|
51
|
+
|
|
52
|
+
> **程序员终端瑞士军刀——替代 5 个独立工具,一个 CLI 搞定**
|
|
53
|
+
|
|
54
|
+
DevMate 是一个 CLI + TUI + Web 三模架构的程序员全能工坊。装一个 devmate,少装 Postman + TablePlus + htop + 正则工具 + 文件管理器。
|
|
55
|
+
|
|
56
|
+
## 快速开始
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# 安装
|
|
60
|
+
pip install devmate
|
|
61
|
+
|
|
62
|
+
# 首次运行(交互式引导)
|
|
63
|
+
devmate
|
|
64
|
+
|
|
65
|
+
# 试试这些命令
|
|
66
|
+
devmate tk organize ~/Downloads --dry-run # 整理文件(预览模式)
|
|
67
|
+
devmate db connect sqlite:///test.db # 连接数据库
|
|
68
|
+
devmate api get https://httpbin.org/get # 发送 HTTP 请求
|
|
69
|
+
devmate ai add default --provider openai # 配置 AI 模型
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 已实现模块(Phase 1)
|
|
73
|
+
|
|
74
|
+
| 模块 | CLI 入口 | 功能 | 状态 |
|
|
75
|
+
|------|---------|------|------|
|
|
76
|
+
| **toolkit** | `devmate tk` | 文件整理、目录大小排行、缓存清理 | ✅ |
|
|
77
|
+
| **apidev** | `devmate api` | HTTP 客户端、Mock Server、请求历史 | ✅ |
|
|
78
|
+
| **dbadmin** | `devmate db` | SQL 编辑器、表浏览器、保存的查询 | ✅ |
|
|
79
|
+
| **apihub** | `devmate ai` | AI 模型统一接入、对话、历史记录 | ✅ |
|
|
80
|
+
| vault | `devmate vault` | 加密密钥管理器 | ✅ |
|
|
81
|
+
| audit | `devmate audit` | 审计日志 | ✅ |
|
|
82
|
+
|
|
83
|
+
## 安装方式
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# 最小安装(CLI 核心)
|
|
87
|
+
pip install devmate
|
|
88
|
+
|
|
89
|
+
# 开发安装(含测试 + 代码检查工具)
|
|
90
|
+
pip install "devmate[dev]"
|
|
91
|
+
|
|
92
|
+
# 完整安装
|
|
93
|
+
pip install "devmate[all]"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 项目状态
|
|
97
|
+
|
|
98
|
+
**v0.1.0-alpha** — Phase 1 完成,4 个 MVP 模块可用。
|
|
99
|
+
|
|
100
|
+
## 开发
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
git clone https://github.com/CXuanPro/DevMate.git
|
|
104
|
+
cd DevMate
|
|
105
|
+
python -m venv .venv && source .venv/bin/activate
|
|
106
|
+
pip install -e ".[dev]"
|
|
107
|
+
|
|
108
|
+
# 验证
|
|
109
|
+
devmate --help
|
|
110
|
+
|
|
111
|
+
# 运行测试
|
|
112
|
+
pytest
|
|
113
|
+
|
|
114
|
+
# 代码检查
|
|
115
|
+
ruff check src/ tests/
|
|
116
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
devmate/__init__.py,sha256=0w2oV2j16BKZhV6VaJqeXdOSXmu2z0sClMhX-NAvbkQ,193
|
|
2
|
+
devmate/__main__.py,sha256=BM2m4-Qx1fDJ7671ZixHiPMeTP_TtR35rvT7rTsSPEU,103
|
|
3
|
+
devmate/app/__init__.py,sha256=zueaNl5oUUM6cKVSMS5bHN5lJi-1ovnQmEQCxadF7Cg,57
|
|
4
|
+
devmate/app/cli.py,sha256=YGuxc_M1XsXt-Wl7J_bl7llsOnw-YZWhzXgjMUPvdbs,60273
|
|
5
|
+
devmate/app/tui.py,sha256=jyiVFVPv527_l-HCfzbS0_5-X9lKdYEF-eFPmMs5o6A,8589
|
|
6
|
+
devmate/app/web/__init__.py,sha256=X-IiyGpgNLBgD91KMgQiLB43op1XR3F6T7jMjBvscWg,3755
|
|
7
|
+
devmate/bus/__init__.py,sha256=0PwmZK-CMsADH_t3M4AFUdk8v7C29dHd6s657rRuTVY,65
|
|
8
|
+
devmate/bus/bus.py,sha256=OQOgkKjZwXPaO_Z95qNbptZ96_44e0uklbpoCNB1dDw,5279
|
|
9
|
+
devmate/bus/command.py,sha256=L-AtXmFFO4m0CEw7pcRUV_-QwFNVISv8tMnHQ-SZYtQ,2444
|
|
10
|
+
devmate/core/__init__.py,sha256=JwY0ZX6F4qt6kTW0qjlPEqtdgVhANMMvmHJ3Nzrwl2o,56
|
|
11
|
+
devmate/core/config.py,sha256=NQpxnqXjJZ3YOzyhzxSfazZD_TNOvYiDD5rwDql66o4,3847
|
|
12
|
+
devmate/core/logging.py,sha256=ImxNsPhTwAjqd9FPckYhlkrsLKMNwHL2kuj2aOuHFpk,1811
|
|
13
|
+
devmate/core/security.py,sha256=-5a6l7MRnA5lv18fCjMgFOdkeMTBZiEJhehBZ4aUtjc,1960
|
|
14
|
+
devmate/events/__init__.py,sha256=Mj86hZaW4-_9tFf7zM1Q7GPuxyPmJQoPE3PJ5fFN6rg,47
|
|
15
|
+
devmate/events/bus.py,sha256=ZqUggP2JfcdFK3Ol0KjDB0xR5nP8Yz_hO3KzLwRWC3c,3516
|
|
16
|
+
devmate/events/domain_event.py,sha256=YBA6805DPuFcLEGWwGLrvHWO1X70mmV4sJd9Tq-q0RM,1356
|
|
17
|
+
devmate/module/__init__.py,sha256=xDsOkChb4D1A_nv9kbhJiRXSxnGpbj8pnQ3TesbKGH8,50
|
|
18
|
+
devmate/module/registry.py,sha256=Z-mhSKvCkNCiIE8Uh9PVR-ZvbD_GdtCC_gvEN9ORa4g,2157
|
|
19
|
+
devmate/security/audit.py,sha256=WDgL-PlHx06YxSRCRQgecy7AHY45xHMhQ18q6-nrz4k,3203
|
|
20
|
+
devmate/security/vault.py,sha256=qsJV325H-1fGZHfyvk971sNELQFCAIIXXtqAglb0LoU,7420
|
|
21
|
+
devmate_agent/__init__.py,sha256=e6I93HLmdvk9Cs0cZJagECV9iusBvUfN0wU8x_md_lI,15691
|
|
22
|
+
devmate_apidev/__init__.py,sha256=2rQw0H-OcCn4-WDD10YdWCJkkUyU427BqGpkymzh7AY,9638
|
|
23
|
+
devmate_apihub/__init__.py,sha256=tbZ466vIC1zC4bHIzrAE1AS9jn2R3srFcPvW4a0j43E,10593
|
|
24
|
+
devmate_dbadmin/__init__.py,sha256=3TDtyywPdAD9gjI-lC_5Iz3x5ouGoobYTcku42OvcgI,9304
|
|
25
|
+
devmate_gitflow/__init__.py,sha256=HhB-Pz0TqTtMEt248D-_GvZAHXDNp4wOE0cIXc6IjQ0,8536
|
|
26
|
+
devmate_monitor/__init__.py,sha256=yLPVbnhUCt8xok__H9MhtHWFXvkvYx57-6jjC7_70IM,3518
|
|
27
|
+
devmate_notekeeper/__init__.py,sha256=-nlLZhWYB3U2Bne-5onqjw86Tta5lc-5UWz5OUFAw-E,9286
|
|
28
|
+
devmate_regexlab/__init__.py,sha256=HcjSs5nSNQcjtnzvUoHfn1jmZva_6ZoLO0mIV8hWcEg,7150
|
|
29
|
+
devmate_reporter/__init__.py,sha256=Zz2wXXldIiVex6G5fp6wE69VUKMYPl69TwYd3zu5f3g,5686
|
|
30
|
+
devmate_scaffold/__init__.py,sha256=mQqGjzgvREaOzdQXnfyLO0ETOt1A-dyx6KkzQNv8NVM,6381
|
|
31
|
+
devmate_sshman/__init__.py,sha256=hJW9oKLKgBregY2-Str0hdNY9rVznHGVUuD-U5o6NIM,11258
|
|
32
|
+
devmate_toolkit/__init__.py,sha256=e_IxW6klFfRLR4bIIElThdzyQ-kr-OEjkRwVWardGxA,7826
|
|
33
|
+
devmate-1.0.0.dist-info/METADATA,sha256=B_p93mUDOHnUyc7IHKD8te32n0dWkYW7QzjHqpxrdZw,3582
|
|
34
|
+
devmate-1.0.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
35
|
+
devmate-1.0.0.dist-info/entry_points.txt,sha256=V1_cyikZm292vEc6la7MgTkDISy1E5uhuIIkRwhs9mE,434
|
|
36
|
+
devmate-1.0.0.dist-info/top_level.txt,sha256=w2celaaxGYQXf2XQPLOyw5TBBKSZgCBU6_KuLYdeMzI,201
|
|
37
|
+
devmate-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[console_scripts]
|
|
2
|
+
devmate = devmate.app.cli:main
|
|
3
|
+
|
|
4
|
+
[devmate.modules]
|
|
5
|
+
agent = devmate_agent
|
|
6
|
+
apidev = devmate_apidev
|
|
7
|
+
apihub = devmate_apihub
|
|
8
|
+
dbadmin = devmate_dbadmin
|
|
9
|
+
gitflow = devmate_gitflow
|
|
10
|
+
monitor = devmate_monitor
|
|
11
|
+
notekeeper = devmate_notekeeper
|
|
12
|
+
publisher = devmate_publisher
|
|
13
|
+
regexlab = devmate_regexlab
|
|
14
|
+
reporter = devmate_reporter
|
|
15
|
+
scaffold = devmate_scaffold
|
|
16
|
+
sshman = devmate_sshman
|
|
17
|
+
toolkit = devmate_toolkit
|
|
18
|
+
vault = devmate_vault
|