-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup.py
More file actions
232 lines (183 loc) · 8.45 KB
/
Copy pathsetup.py
File metadata and controls
232 lines (183 loc) · 8.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
セットアップスクリプト
依存関係のチェック、.envファイルの作成、config.yamlの確認を行う
"""
import os
import re
import sys
import subprocess
from io import StringIO
from pathlib import Path
from typing import List, Dict, Any
def is_env_value_configured(content: str, key: str = "OPENAI_API_KEY") -> bool:
"""環境変数ファイルの最終割当が非空かを厳密に判定する。
``python-dotenv`` と同じパーサーを使うことで、引用符・export・コメント・重複
キーを正しく扱う。runtimeの ``load_dotenv`` と同じく変数展開も有効にし、重複時は
有効な最終割当だけを採用する。値は前後空白を除いて判定するが、実際の ``.env``
の内容は変更しない。
"""
try:
from dotenv import dotenv_values
except ImportError:
# python-dotenv is a declared dependency, but setup.py should still provide a
# useful check when dependencies have not been installed yet. This fallback keeps
# the exact-key/last-assignment contract for the common unquoted form.
value = None
for raw_line in content.splitlines():
line = raw_line.strip()
if not line or line.startswith("#"):
continue
if line.startswith("export "):
line = line[7:].lstrip()
name, separator, raw_value = line.partition("=")
if separator and name.strip() == key:
value = raw_value.strip()
if len(value) >= 2 and value[0] in {"'", '"'} and value[-1] == value[0]:
value = value[1:-1]
# dotenv_values(interpolate=True) と同様、${NAME} は環境変数へ
# 展開し、未設定なら空文字にする。既存環境変数で解決する参照は
# 設定済みとして扱う。
def expand(match: re.Match) -> str:
return os.environ.get(match.group(1), "")
value = re.sub(r"\$\{([A-Za-z_][A-Za-z0-9_]*)\}", expand, value)
return bool(value and value.strip())
values = dotenv_values(stream=StringIO(content), interpolate=True)
value = values.get(key)
return isinstance(value, str) and bool(value.strip())
class SetupTool:
"""セットアップツール"""
def __init__(self):
self.project_root = Path(__file__).parent
self.errors = []
self.warnings = []
def run(self):
"""セットアップを実行"""
print("=== Event AutoPin セットアップ ===\n")
# 1. Python バージョンチェック
self.check_python_version()
# 2. 依存関係チェック
self.check_dependencies()
# 3. ディレクトリ作成
self.create_directories()
# 4. 環境変数ファイル作成
self.setup_env_file()
# 5. 設定ファイルチェック
self.check_config_file()
# 結果表示
self.show_results()
def check_python_version(self):
"""Pythonバージョンをチェック"""
print("1. Pythonバージョンチェック...")
version = sys.version_info
if version.major < 3 or (version.major == 3 and version.minor < 8):
self.errors.append("Python 3.8以上が必要です")
else:
print(f" ✅ Python {version.major}.{version.minor}.{version.micro}")
def check_dependencies(self):
"""依存関係をチェック"""
print("\n2. 依存関係チェック...")
# パッケージのインポートチェック
required_packages = {
'requests': 'requests',
'bs4': 'beautifulsoup4',
'pandas': 'pandas',
'openai': 'openai',
'dotenv': 'python-dotenv',
'yaml': 'PyYAML',
'PIL': 'Pillow',
'lxml': 'lxml'
}
missing_packages = []
for import_name, package_name in required_packages.items():
try:
__import__(import_name)
print(f" ✅ {package_name}")
except ImportError:
missing_packages.append(package_name)
print(f" ❌ {package_name}")
if missing_packages:
self.warnings.append(
f"以下のパッケージが不足しています: {', '.join(missing_packages)}\n"
f" 実行してください: pip install -r requirements.txt"
)
def create_directories(self):
"""必要なディレクトリを作成"""
print("\n3. ディレクトリ作成...")
directories = ['output', 'logs', 'config_examples']
for dir_name in directories:
dir_path = self.project_root / dir_name
dir_path.mkdir(exist_ok=True)
print(f" ✅ {dir_name}/")
def setup_env_file(self):
"""環境変数ファイルをセットアップ"""
print("\n4. 環境変数ファイルセットアップ...")
env_path = self.project_root / '.env'
if env_path.exists():
with open(env_path, 'r', encoding='utf-8') as f:
content = f.read()
if is_env_value_configured(content):
print(" ✅ .envファイルは既に存在します")
else:
self.warnings.append(".envファイルにOPENAI_API_KEYが設定されていません")
else:
print(" 📝 .envファイルを作成します...")
api_key = input(" OpenAI APIキーを入力してください: ").strip()
if api_key:
with open(env_path, 'w', encoding='utf-8') as f:
f.write(f"OPENAI_API_KEY={api_key}\n")
print(" ✅ .envファイルを作成しました")
else:
self.warnings.append("APIキーが入力されませんでした。後で.envファイルを編集してください")
def check_config_file(self):
"""設定ファイルをチェック"""
print("\n5. 設定ファイルチェック...")
config_path = self.project_root / 'config.yaml'
if not config_path.exists():
self.errors.append("config.yamlが見つかりません")
return
try:
import yaml
with open(config_path, 'r', encoding='utf-8') as f:
config = yaml.safe_load(f)
# 必須項目のチェック
if not config.get('target', {}).get('url'):
self.warnings.append("config.yamlにターゲットURLが設定されていません")
print(" ✅ config.yaml")
# 設定内容を表示
target_url = config.get('target', {}).get('url', '未設定')
# `caico` remains the legacy config key for existing projects.
output_format = config.get('output', {}).get('format', 'caico')
print(f" - ターゲットURL: {target_url}")
print(f" - 出力フォーマット: {output_format}")
except Exception as e:
self.errors.append(f"config.yamlの読み込みエラー: {e}")
def show_results(self):
"""結果を表示"""
print("\n" + "=" * 50)
print("セットアップ結果")
print("=" * 50)
if self.errors:
print("\n❌ エラー:")
for error in self.errors:
print(f" - {error}")
if self.warnings:
print("\n⚠️ 警告:")
for warning in self.warnings:
print(f" - {warning}")
if not self.errors:
print("\n✅ セットアップが完了しました!")
print("\n次のコマンドでツールを実行できます:")
print(" python main.py")
if self.warnings:
print("\n※ 警告事項を確認して、必要に応じて対処してください")
else:
print("\n❌ エラーを修正してから再度セットアップを実行してください")
sys.exit(1)
def main():
"""メイン関数"""
setup = SetupTool()
setup.run()
if __name__ == "__main__":
main()