pilot.linkstec 0.0.32__py3-none-any.whl → 0.0.91__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.
Files changed (49) hide show
  1. pilot/base/__init__.py +0 -0
  2. pilot/base/ai_call.py +38 -0
  3. pilot/base/ai_info.py +20 -0
  4. pilot/base/chage_file_tag_base.py +73 -0
  5. pilot/base/db_operation_base.py +536 -0
  6. pilot/base/delete_commnents_base.py +306 -0
  7. pilot/base/file_operation.py +44 -0
  8. pilot/base/get_file_encoding.py +14 -0
  9. pilot/base/make_parsing_java_file_order_base.py +154 -0
  10. pilot/base/split_file_base.py +256 -0
  11. pilot/client/__init__.py +0 -0
  12. pilot/client/ai_client.py +75 -0
  13. pilot/config/config_reader.py +81 -43
  14. pilot/create_python/__init__.py +0 -0
  15. pilot/create_python/config/__init__.py +0 -0
  16. pilot/create_python/create_python.py +150 -0
  17. pilot/create_python/sample/__init__.py +0 -0
  18. pilot/create_python/sample/child_sample/__init__.py +0 -0
  19. pilot/create_python/sample/child_sample/job/__init__.py +0 -0
  20. pilot/create_python/sample/config/__init__.py +0 -0
  21. pilot/db/__init__.py +0 -0
  22. pilot/db/create_table.py +34 -0
  23. pilot/db/db_connect.py +49 -0
  24. pilot/db/db_main.py +293 -0
  25. pilot/db/db_util.py +508 -0
  26. pilot/db/ddl/__init__.py +18 -0
  27. pilot/db/dml/__init__.py +18 -0
  28. pilot/db/sql_executor.py +62 -0
  29. pilot/db/sql_loader.py +233 -0
  30. pilot/db/sql_service.py +55 -0
  31. pilot/file_tool/__init__.py +0 -0
  32. pilot/file_tool/create_prompt_file.py +75 -0
  33. pilot/file_tool/json_file_tool.py +103 -0
  34. pilot/job/base/__init__.py +0 -0
  35. pilot/job/base/convert/__init__.py +0 -0
  36. pilot/job/base/convert/encodingTransformerJob.py +16 -0
  37. pilot/job/base/convert/tabReplaceJob.py +27 -0
  38. pilot/job/base/generate/__init__.py +0 -0
  39. pilot/job/base/generate/generateJsonBaseJob.py +42 -0
  40. pilot/job/base/generate/generateTextBaseJob.py +40 -0
  41. pilot/job/impl/base_job.py +4 -0
  42. pilot/prompt/__init__.py +0 -0
  43. pilot/unit/impl/base_unit.py +1 -0
  44. {pilot_linkstec-0.0.32.dist-info → pilot_linkstec-0.0.91.dist-info}/METADATA +1 -1
  45. pilot_linkstec-0.0.91.dist-info/RECORD +75 -0
  46. pilot_linkstec-0.0.32.dist-info/RECORD +0 -35
  47. {pilot_linkstec-0.0.32.dist-info → pilot_linkstec-0.0.91.dist-info}/WHEEL +0 -0
  48. {pilot_linkstec-0.0.32.dist-info → pilot_linkstec-0.0.91.dist-info}/licenses/LICENSE +0 -0
  49. {pilot_linkstec-0.0.32.dist-info → pilot_linkstec-0.0.91.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,256 @@
1
+ import copy
2
+ import json
3
+ import re
4
+ from pathlib import Path
5
+ from typing import List, Dict, Tuple
6
+
7
+ from lxml import etree as ET
8
+
9
+ from pilot.job.impl.base_job import BaseJob
10
+
11
+ from base.file_operation import read_file_lines, write_json_file
12
+
13
+
14
+ class SplitFile(BaseJob):
15
+
16
+ @staticmethod
17
+ def split_java_methods(java_code: str):
18
+ """
19
+ 与えられた単一の完全な Java ソースコードから
20
+ 1. 各メソッド(コンストラクタ含む)本体(コメント・アノテーション付き)
21
+ 2. メソッドを除いた残りのクラスコード
22
+ を抽出し、指示通りの JSON 文字列を返す。
23
+
24
+ 【前提】
25
+ * 入力は 1 ファイル分だけ。
26
+ * クラスは 1 つ(内部クラス・列挙型があっても OK)。
27
+ * メソッドはネストしない(ローカルクラス・ローカルメソッドは対象外)。
28
+ * 文字列リテラルやコメント中の波括弧は正規表現だけでは完全に安全に扱えないが、
29
+ 本ユーティリティは「実務上よく出会う」コードを対象に設計している。
30
+ 必要なら JavaParser 等の本格的パーサに差し替えて下さい。
31
+
32
+ 【出力形式】
33
+ JSON 文字列(UTF‑8)で、質問文に書かれたスキーマ通り。
34
+ """
35
+ # ------------------------------------------------------------------
36
+ # 1️⃣ パッケージ・インポートの取得(無い場合は空文字列)
37
+ # ------------------------------------------------------------------
38
+ package_pat = re.compile(r'^\s*package\s+([\w\.]+)\s*;\s*', re.MULTILINE)
39
+ pkg_match = package_pat.search(java_code)
40
+ package_name = pkg_match.group(1) if pkg_match else ""
41
+
42
+ # ------------------------------------------------------------------
43
+ # 2️⃣ クラス宣言の取得(クラス名だけ抜き出す)
44
+ # ------------------------------------------------------------------
45
+ # class / interface / enum のいずれかが対象。アノテーションや修飾子は無視。
46
+ class_pat = re.compile(
47
+ r'''(?x) # Verbose
48
+ (?:@\w+(?:\s*\([^)]*\))?\s*)* # 前置アノテーション(任意)
49
+ (public|protected|private)?\s* # アクセス修飾子(任意)
50
+ (final|abstract)?\s* # class 修飾子(任意)
51
+ (class|interface|enum)\s+ # キーワード
52
+ (?P<name>\w+) # クラス名(取得対象)
53
+ (?:\s*<[^>]*>)? # ジェネリクス(任意)
54
+ (?:\s+extends\s+[^{]+)? # extends 句(任意)
55
+ (?:\s+implements\s+[^{]+)? # implements 句(任意)
56
+ \s*{ # 開始波括弧
57
+ ''')
58
+ class_match = class_pat.search(java_code)
59
+ if not class_match:
60
+ raise ValueError("クラス宣言が見つかりませんでした。")
61
+ class_name = class_match.group('name')
62
+
63
+ # ------------------------------------------------------------------
64
+ # 3️⃣ メソッド(=コンストラクタも含む)全体を抽出
65
+ # ------------------------------------------------------------------
66
+ # 正規表現で「コメント・アノテーション + 修飾子 + 戻り値(またはコンストラクタ) + 名前 + パラメータ + 本体」までを取得。
67
+ # コメントは //, /** */ , /* */ のいずれか。アノテーションは @ で始まる。
68
+ # 本体は波括弧の対称性を数えて取得(re.DOTALL で改行も含める)。
69
+ method_pat = re.compile(
70
+ r'''(?x) # Verbose
71
+ (?:
72
+ (?:/\*\*.*?\*/\s*)? # Javadoc コメント(任意)
73
+ (?:/\*.*?\*/\s*)? # ブロックコメント(任意)
74
+ (?:\/\/[^\n]*\s*)? # 行コメント(任意)
75
+ )*
76
+ (?:@\w+(?:\s*\([^)]*\))?\s*)* # アノテーション(0 個以上)
77
+ (?:public|protected|private|\s)* # アクセス修飾子(任意)
78
+ (?:static\s+)? # static 修飾子(任意)
79
+ (?:final\s+|synchronized\s+|abstract\s+|native\s+)* # 余分な修飾子(任意)
80
+ (?:<[^>]+>\s+)? # メソッドレベルのジェネリクス(任意)
81
+ (?:[\w\<\>\[\]]+\s+)? # 戻り値型(コンストラクタなら無い)
82
+ (?P<name>\w+) # メソッド名(コンストラクタはクラス名)
83
+ \s*\( # パラメータ開始
84
+ [^\)]* # 中身は簡易的に「) まで」スキップ
85
+ \)\s*
86
+ (?:throws\s+[^{]+)? # throws 句(任意)
87
+ \{ # 本体開始
88
+ ''')
89
+
90
+ # メソッド本体の波括弧対称性を数えるためのヘルパー
91
+ def extract_body(start_idx: int) -> Tuple[int, str]:
92
+ """start_idx は '{' の位置。対になる '}' まで走査して全文字列を返す。"""
93
+ depth = 0
94
+ i = start_idx
95
+ while i < len(java_code):
96
+ ch = java_code[i]
97
+ if ch == '{':
98
+ depth += 1
99
+ elif ch == '}':
100
+ depth -= 1
101
+ if depth == 0:
102
+ # i を含めて抜き出す
103
+ return i + 1, java_code[start_idx:i + 1]
104
+ i += 1
105
+ raise ValueError("メソッド本体の終端 '}' が見つかりません。")
106
+
107
+ # すべてのメソッド情報を格納するリスト
108
+ methods: List[Dict] = []
109
+
110
+ # 走査インデックス
111
+ pos = 0
112
+ while True:
113
+ m = method_pat.search(java_code, pos)
114
+ if not m:
115
+ break
116
+
117
+ # メソッド名取得
118
+ method_name = m.group('name')
119
+ # コンストラクタかどうか判定(名前がクラス名と同じならコンストラクタ)
120
+ is_constructor = method_name == class_name
121
+
122
+ # メソッド宣言全体の開始位置(コメント・アノテーションを含むので、直前に遡る)
123
+ decl_start = m.start()
124
+ # ただし上記正規表現はコメント・アノテーションを「0 回以上」含めているので
125
+ # ここで取得した start はすでにそれらを含んだ位置になる。
126
+
127
+ # 本体開始波括弧のインデックス
128
+ brace_idx = java_code.find('{', m.end() - 1)
129
+ if brace_idx == -1:
130
+ raise ValueError("メソッド本体開始 '{' が見つかりません。")
131
+
132
+ # 本体全体を取得
133
+ body_end, body_str = extract_body(brace_idx)
134
+
135
+ # 完全なメソッド文字列(宣言 + 本体)
136
+ method_full = java_code[decl_start:body_end]
137
+
138
+ # 位置情報を保持して後で「残りコード」から除去できるようにする
139
+ methods.append({
140
+ "methodName": method_name,
141
+ "isConstructor": is_constructor,
142
+ "code": method_full,
143
+ "start": decl_start,
144
+ "end": body_end
145
+ })
146
+
147
+ # 次の検索は本体終了位置から続ける
148
+ pos = body_end
149
+
150
+ # ------------------------------------------------------------------
151
+ # 4️⃣ 「残りコード」作成(メソッド領域を空白に置換してからトリム)
152
+ # ------------------------------------------------------------------
153
+ remaining = list(java_code) # 文字列を可変リストに
154
+ for m in methods:
155
+ # メソッド領域はスペースで埋めておく(行番号・インデントを保つため)
156
+ for i in range(m["start"], m["end"]):
157
+ remaining[i] = ' '
158
+ remaining_code = ''.join(remaining)
159
+
160
+ # 余計な空行を削除(ただしクラスの波括弧は残す)
161
+ remaining_code = re.sub(r'\n\s*\n', '\n', remaining_code).strip() + '\n'
162
+
163
+ # ------------------------------------------------------------------
164
+ # 5️⃣ JSON オブジェクト生成
165
+ # ------------------------------------------------------------------
166
+ json_files: List[Dict] = []
167
+ for m in methods:
168
+ file_name = f"{class_name}_{m['methodName']}.txt"
169
+ # エスケープ処理(JSON 用に \ と " をエスケープ)
170
+ escaped_code = m["code"].replace('\\', '\\\\').replace('"', '\\"')
171
+ escaped_remaining = remaining_code.replace('\\', '\\\\').replace('"', '\\"')
172
+
173
+ json_files.append({
174
+ "fileName": file_name,
175
+ "className": class_name,
176
+ "methodName": m["methodName"],
177
+ "package": package_name,
178
+ "code": escaped_code,
179
+ "remainingClassCode": escaped_remaining
180
+ })
181
+
182
+ result = {"files": json_files}
183
+ return json.dumps(result, ensure_ascii=False, indent=2)
184
+
185
+ @staticmethod
186
+ def _extract_statement_nodes(root: ET.Element) -> List[ET.Element]:
187
+ """返回所有可执行语句的 Element(保留完整节点)。"""
188
+ stmts = []
189
+ for tag in ("select", "insert", "update", "delete"):
190
+ stmts.extend(root.findall(f".//{tag}"))
191
+ return stmts
192
+
193
+
194
+ def split_mybatis_xml(self, xml_path, out_dir: Path) -> List:
195
+ """
196
+ 把根节点中的每条语句(select/insert/update/delete)按照它们的 id
197
+ 写入独立文件。每个子文件只包含单条语句本身(不再包裹 <mapper>)。
198
+ """
199
+ parser = ET.XMLParser(remove_blank_text=False) # 保留原始缩进、换行
200
+ tree = ET.parse(str(xml_path), parser=parser)
201
+ root = tree.getroot()
202
+
203
+ out_dir.mkdir(parents=True, exist_ok=True)
204
+
205
+ out_put_list = []
206
+ for stmt in self._extract_statement_nodes(root):
207
+ stmt_id = stmt.get("id")
208
+ if not stmt_id: # 没有 id 的语句直接跳过
209
+ continue
210
+
211
+ # 复制一份,防止修改原始树结构
212
+ stmt_copy = copy.deepcopy(stmt)
213
+
214
+ # 生成文件路径(这里仍然使用 .xml,当然你可以改成 .sql、.txt …)
215
+ out_path = out_dir / f"{stmt_id}.xml"
216
+
217
+ # 把单条语句写入文件
218
+ # - xml_declaration=False → 不输出 <?xml …?> 声明
219
+ # - pretty_print=True → 保持原始的缩进格式
220
+ tree = ET.ElementTree(stmt_copy)
221
+ tree.write(
222
+ str(out_path),
223
+ encoding="utf-8",
224
+ xml_declaration=False,
225
+ pretty_print=True
226
+ )
227
+ print(f"✔ 生成 {out_path}")
228
+ out_put_list.append(out_path)
229
+
230
+ return out_put_list
231
+
232
+
233
+ def run(self):
234
+ try:
235
+
236
+ lines = read_file_lines(self.file_path)
237
+
238
+ str_code = ''.join(lines)
239
+
240
+ remove_file_type = self.__getattribute__('file_type')
241
+ output_file_path = self.__getattribute__('target_file_path')
242
+ match remove_file_type:
243
+ case 'Java':
244
+ _split_result = self.split_java_methods(str_code)
245
+ write_json_file(json.loads(_split_result), output_file_path)
246
+ case 'mybatis':
247
+ _split_file_list = self.split_mybatis_xml(self.file_path, output_file_path)
248
+ setattr(self, 'split_file_list', _split_file_list)
249
+ case _:
250
+ _split_result =None
251
+
252
+ except Exception as e:
253
+ self.logger.error(f"{__name__}異常終了. {e}")
254
+ return
255
+
256
+ super().run()
File without changes
@@ -0,0 +1,75 @@
1
+ import requests
2
+
3
+ from pilot.config.config_reader import get_config
4
+ from pilot.logging.logger import get_logger
5
+
6
+
7
+ class AIClient:
8
+ def __init__(self):
9
+ self.logger = get_logger(__name__)
10
+ self.config_dto = get_config()
11
+ self.headers = {"Content-Type": "application/json;charset=utf-8"}
12
+
13
+ def call(self, user_prompt: str, system_prompt: str = "") -> str:
14
+ messages = []
15
+ if system_prompt:
16
+ messages.append({"role": "system", "content": system_prompt})
17
+ messages.append({"role": "user", "content": user_prompt})
18
+
19
+ request_data = self._build_request_payload(messages)
20
+
21
+ response_data = self._send_post_request(self.api_url, self.headers, request_data)
22
+ if not isinstance(response_data, dict):
23
+ self.logger.error("無効なAPI応答またはリクエスト失敗")
24
+ return ""
25
+
26
+ result_text = self._extract_response_content(response_data)
27
+ return result_text
28
+
29
+ def _build_request_payload(self, messages: list[dict]) -> dict:
30
+ raise NotImplementedError("サブクラスでリクエストペイロードの構築を実装してください")
31
+
32
+ def _send_post_request(self, url: str, headers: dict, data: dict) -> dict or str:
33
+ try:
34
+ response = requests.post(url, headers=headers, json=data)
35
+ except Exception as e:
36
+ self.logger.error(f"リクエスト失敗: {e}")
37
+ return ""
38
+ if response.status_code != 200:
39
+ self.logger.error(f"ステータスコード {response.status_code}: {response.text}")
40
+ return ""
41
+ try:
42
+ return response.json()
43
+ except Exception as e:
44
+ self.logger.error(f"JSON解析失敗: {e}")
45
+ return ""
46
+
47
+ def _extract_response_content(self, response: dict) -> str:
48
+ raise NotImplementedError("サブクラスでレスポンスの解析を実装してください")
49
+
50
+
51
+ class LMStudioClient(AIClient):
52
+ def __init__(self):
53
+ super().__init__()
54
+ self.api_url = self.config_dto.lm_studio_api_url
55
+ self.model_name = self.config_dto.lm_studio_model_name
56
+
57
+ def _build_request_payload(self, messages: list[dict]) -> dict:
58
+ payload = {
59
+ "model": self.model_name,
60
+ "stream": False,
61
+ "temperature": 0.8,
62
+ "max_tokens": 15000,
63
+ "messages": messages,
64
+ }
65
+ return payload
66
+
67
+ def _extract_response_content(self, response: dict) -> str:
68
+ if not isinstance(response, dict):
69
+ return str(response)
70
+ if "usage" in response:
71
+ self.logger.debug(f"使用状況: {response['usage']}")
72
+ choices = response.get("choices", [])
73
+ if choices:
74
+ return choices[0].get("message", {}).get("content") or str(response)
75
+ return str(response)
@@ -1,39 +1,54 @@
1
1
  import configparser
2
- import os
3
2
  import inspect
3
+ import os
4
4
  from dataclasses import dataclass
5
- from typing import List
5
+ from typing import Optional
6
+
6
7
 
7
8
  @dataclass
8
9
  class ConfigDTO:
9
- work_space: str
10
- threads: int
11
10
  project: str
11
+ log_level: str
12
+ threads: int
13
+ lm_studio_api_url: str
14
+ lm_studio_model_name: str
15
+ work_space: str
16
+ copy_path: str
17
+ json_file_path:str
12
18
  steps: list[str]
13
- skipsteps: list[str]
14
- runsteps: list[str]
15
- multisteps: list[str]
19
+
16
20
 
17
21
  class ConfigReader:
18
- def __init__(self, filename = None):
19
- filepath = None
20
- if filename is None:
21
- filepath = self.find_config_path()
22
-
23
- if filename is not None:
24
- cwd = os.getcwd()
25
- filepath = os.path.join(cwd, 'config', filename)
26
- if not os.path.exists(filepath):
27
- raise FileNotFoundError(f"Configuration file not found: {filepath}")
28
-
29
- self.config = configparser.ConfigParser()
30
- self.config.optionxform = str
31
-
32
- with open(filepath, 'r', encoding='utf-8') as f:
33
- content = f.read()
34
- if not content.lstrip().startswith('['):
35
- content = '[DEFAULT]\n' + content
36
- self.config.read_string(content)
22
+ _instance = None
23
+ _loaded = False
24
+
25
+ def __new__(cls, filepath=None):
26
+ if cls._instance is None:
27
+ cls._instance = super().__new__(cls)
28
+ return cls._instance
29
+
30
+ def __init__(self, filepath=None):
31
+ if self._loaded:
32
+ return
33
+
34
+ try:
35
+ if filepath is None:
36
+ filepath = self.find_config_path()
37
+ if not os.path.exists(filepath):
38
+ raise FileNotFoundError(f"設定ファイルが見つかりません: {filepath}")
39
+
40
+ self.config = configparser.ConfigParser()
41
+ self.config.optionxform = str
42
+ with open(filepath, 'r', encoding='utf-8') as f:
43
+ content = f.read()
44
+ if not content.lstrip().startswith('['):
45
+ content = '[DEFAULT]\n' + content
46
+ self.config.read_string(content)
47
+
48
+ self._loaded = True
49
+ except Exception as e:
50
+ print(f"設定ファイル読み込みエラー: {e}")
51
+ raise
37
52
 
38
53
  @classmethod
39
54
  def find_config_path(cls):
@@ -52,10 +67,11 @@ class ConfigReader:
52
67
 
53
68
  base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
54
69
  fallback_path = os.path.join(base_dir, 'config', 'control.properties')
70
+
55
71
  if os.path.exists(fallback_path):
56
72
  return fallback_path
57
73
 
58
- raise FileNotFoundError("control.properties not found in expected locations")
74
+ raise FileNotFoundError("control.properties が期待される場所に見つかりません")
59
75
 
60
76
  def get(self, section, option, fallback=None, cast_type=str):
61
77
  try:
@@ -71,25 +87,47 @@ class ConfigReader:
71
87
  return fallback
72
88
 
73
89
  def get_dto(self) -> ConfigDTO:
74
- input_path = self.get('DEFAULT', 'input_path', fallback='.')
75
- work_space = self.get('DEFAULT', 'work_space', fallback='.')
76
- threads = int(self.get('DEFAULT', 'threads', fallback=1))
77
90
  project = self.get('DEFAULT', 'project', fallback='')
91
+ log_level = self.get('DEFAULT', 'log_level', fallback='INFO')
92
+ threads = self.get('DEFAULT', 'threads', fallback=1, cast_type=int)
93
+ lm_studio_api_url = self.get('DEFAULT', 'lm_studio_api_url', fallback='.')
94
+ lm_studio_model_name = self.get('DEFAULT', 'lm_studio_model_name', fallback='.')
95
+ work_space = self.get('DEFAULT', 'work_space', fallback='.')
96
+ copy_path = self.get('DEFAULT', 'copy_file_path', fallback='.')
97
+ json_file_path = self.get('DEFAULT', 'json_file_path', fallback='.')
78
98
  steps_str = self.get('DEFAULT', 'steps', fallback='')
99
+
79
100
  steps = [s.strip() for s in steps_str.split(',')] if steps_str else []
80
- skipsteps_str = self.get('DEFAULT', 'skipsteps', fallback='')
81
- skipsteps = [s.strip() for s in skipsteps_str.split(',')] if skipsteps_str else []
82
- runsteps_str = self.get('DEFAULT', 'runsteps', fallback='')
83
- runsteps = [s.strip() for s in runsteps_str.split(',')] if runsteps_str else []
84
- multisteps_str = self.get('DEFAULT', 'multisteps', fallback='')
85
- multisteps = [s.strip() for s in multisteps_str.split(',')] if multisteps_str else []
86
101
 
87
102
  return ConfigDTO(
88
- work_space=work_space,
89
- threads=threads,
90
103
  project=project,
91
- steps=steps,
92
- skipsteps=skipsteps,
93
- runsteps=runsteps,
94
- multisteps=multisteps
95
- )
104
+ log_level=log_level,
105
+ threads=threads,
106
+ lm_studio_api_url=lm_studio_api_url,
107
+ lm_studio_model_name=lm_studio_model_name,
108
+ work_space=work_space,
109
+ copy_path=copy_path,
110
+ json_file_path=json_file_path,
111
+ steps=steps
112
+ )
113
+
114
+
115
+ # 全局設定管理用の変数
116
+ _global_config: Optional[ConfigDTO] = None
117
+
118
+
119
+ def init_config(filepath=None):
120
+ global _global_config
121
+ try:
122
+ config_reader = ConfigReader(filepath)
123
+ _global_config = config_reader.get_dto()
124
+ except Exception as e:
125
+ print(f"設定初期化エラー: {e}")
126
+ raise
127
+
128
+
129
+ def get_config() -> ConfigDTO:
130
+ global _global_config
131
+ if _global_config is None:
132
+ raise RuntimeError("設定が初期化されていません。init_config() を最初に呼び出してください。")
133
+ return _global_config
File without changes
File without changes
@@ -0,0 +1,150 @@
1
+ import configparser
2
+ import os
3
+ from dataclasses import dataclass
4
+ from pathlib import Path
5
+
6
+ def generate_code():
7
+ # マインコンバート
8
+ cwd = Path(os.getcwd())
9
+
10
+ config_file_path = os.path.join(cwd, 'config', 'create_file.properties')
11
+ config_dto = read_config_file(config_file_path)
12
+
13
+ target_project_root_path = cwd.parent
14
+ # サンプルファイル作成
15
+ print('CONFIGファイルを作成する')
16
+ sample_config_file_path = os.path.join(cwd, 'sample', 'config', 'properties.txt')
17
+ replacements = {
18
+ "WORK_SPACE": config_dto.work_space,
19
+ "PROJECT_NAME": os.path.basename(target_project_root_path),
20
+ "STEP_NAME": "step_000,step_001,step_002"
21
+ }
22
+ target_project_config_path = os.path.join(target_project_root_path, 'config', config_dto.sub_project_name + '_' + config_dto.sub_source_folder + '_' + config_dto.sub_sub_source_folder_1+'.properties')
23
+ read_replace_create_file(sample_config_file_path, replacements, Path(target_project_config_path))
24
+
25
+ print('Main Jobファイルを作成する')
26
+ # サブファイルコントロール、ジョブ、ユニットファイルの作成
27
+ target_project_sub_project_path = os.path.join(target_project_root_path, 'src', config_dto.sub_project_name, config_dto.sub_source_folder, config_dto.sub_sub_source_folder_1)
28
+ # サンプルサブコントロールファイルの作成
29
+ sample_job_file_path = os.path.join(cwd, 'sample', 'child_sample', 'job.txt')
30
+ replacements_job = {}
31
+ target_project_sub_job_path = os.path.join(target_project_sub_project_path, config_dto.sub_source_folder + '_' + config_dto.sub_sub_source_folder_1 + '_job.py')
32
+ read_replace_create_file(sample_job_file_path, replacements_job, Path(target_project_sub_job_path))
33
+
34
+ print('Main Unitファイルを作成する')
35
+ sample_unit_file_path = os.path.join(cwd, 'sample', 'child_sample', 'unit.txt')
36
+ replacements_unit = {
37
+ "JOB_PACKAGE": 'src.'+ config_dto.sub_project_name + '.'+ config_dto.sub_source_folder + '.' + config_dto.sub_sub_source_folder_1 + '.' + os.path.basename(target_project_sub_job_path).split('.')[0],
38
+ "GYOMU_JOB_PACKAGE_000": 'src.'+ config_dto.sub_project_name + '.' + config_dto.sub_source_folder + '.' + config_dto.sub_sub_source_folder_1 + '.jobs.job_000',
39
+ "GYOMU_JOB_PACKAGE_001": 'src.' + config_dto.sub_project_name + '.' + config_dto.sub_source_folder + '.' + config_dto.sub_sub_source_folder_1 + '.jobs.job_001',
40
+ "GYOMU_JOB_PACKAGE_002": 'src.' + config_dto.sub_project_name + '.' + config_dto.sub_source_folder + '.' + config_dto.sub_sub_source_folder_1 + '.jobs.job_002'
41
+ }
42
+ target_project_unit_path = os.path.join(target_project_sub_project_path, config_dto.sub_source_folder + '_' + config_dto.sub_sub_source_folder_1 + '_unit.py' )
43
+ read_replace_create_file(sample_unit_file_path, replacements_unit, Path(target_project_unit_path))
44
+
45
+ print('Main Controllerファイルを作成する')
46
+ sample_controller_file_path = os.path.join(cwd, 'sample', 'child_sample', 'controller.txt')
47
+ replacements_control = {
48
+ "UNIT_PACKAGE": 'src.'+ config_dto.sub_project_name + '.'+ config_dto.sub_source_folder + '.'+ config_dto.sub_sub_source_folder_1 + '.' + os.path.basename(target_project_unit_path).split('.')[0]
49
+ }
50
+ target_project_sub_controller_path = os.path.join(target_project_sub_project_path, config_dto.sub_source_folder + '_' + config_dto.sub_sub_source_folder_1 + '_control.py')
51
+ read_replace_create_file(sample_controller_file_path, replacements_control, Path(target_project_sub_controller_path))
52
+
53
+ init_file_path = Path(os.path.join(target_project_sub_project_path, '__init__.py'))
54
+ create_file(init_file_path,'')
55
+
56
+ print('業務Job用フォルダを作成する')
57
+ job_file_path = Path(os.path.join(target_project_sub_project_path,'jobs'))
58
+ job_file_path.mkdir(parents=True, exist_ok=True)
59
+ sample_job000_file_path = os.path.join(cwd, 'sample', 'child_sample', 'job' ,'job_000.txt')
60
+ sample_job_sample_file_path = os.path.join(cwd, 'sample', 'child_sample', 'job', 'job_sample.txt')
61
+ replacements_job000 = {
62
+ 'JOB_PACKAGE': 'src.'+ config_dto.sub_project_name + '.'+ config_dto.sub_source_folder + '.' + config_dto.sub_sub_source_folder_1 + '.' + os.path.basename(target_project_sub_job_path).split('.')[0]
63
+ }
64
+ target_project_job000_path = os.path.join(target_project_sub_project_path, 'jobs','job_000.py')
65
+ target_project_job001_path = os.path.join(target_project_sub_project_path, 'jobs','job_001.py')
66
+ target_project_job002_path = os.path.join(target_project_sub_project_path, 'jobs', 'job_002.py')
67
+ read_replace_create_file(sample_job000_file_path, replacements_job000, Path(target_project_job000_path))
68
+ replacements_job001 = {
69
+ 'JOB_NAME':'Job_001',
70
+ 'JOB_PACKAGE': 'src.'+ config_dto.sub_project_name + '.'+ config_dto.sub_source_folder + '.' + config_dto.sub_sub_source_folder_1 + '.' + os.path.basename(target_project_sub_job_path).split('.')[0]
71
+ }
72
+ read_replace_create_file(sample_job_sample_file_path, replacements_job001, Path(target_project_job001_path))
73
+ replacements_job002 = {
74
+ 'JOB_NAME': 'Job_002',
75
+ 'JOB_PACKAGE': 'src.'+ config_dto.sub_project_name + '.'+ config_dto.sub_source_folder + '.' + config_dto.sub_sub_source_folder_1 + '.' + os.path.basename(target_project_sub_job_path).split('.')[0]
76
+ }
77
+ read_replace_create_file(sample_job_sample_file_path, replacements_job002, Path(target_project_job002_path))
78
+
79
+ init_job_file_path = Path(os.path.join(target_project_sub_project_path, 'jobs', '__init__.py'))
80
+ create_file(init_job_file_path,'')
81
+
82
+ print('Main controllerファイルを作成する')
83
+ # サンプルパス
84
+ sample_main_controller_file_path = os.path.join(cwd, 'sample', 'main_convert.txt')
85
+ # パラメーター
86
+ replacements = {
87
+ "CONTROLLER_PACKAGE": 'src.'+ config_dto.sub_project_name + '.' + config_dto.sub_source_folder + '.' + config_dto.sub_sub_source_folder_1 +'.' + os.path.basename(target_project_sub_controller_path).split('.')[0],
88
+ "PYTHON_CONFIG_PROPERTIES": config_dto.sub_project_name + '_' + config_dto.sub_source_folder + '_' + config_dto.sub_sub_source_folder_1 + '.properties'
89
+ }
90
+ # 目標ファイルパス
91
+ target_project_main_controller_path = Path(os.path.join(target_project_root_path, config_dto.sub_project_name + '_'
92
+ + config_dto.sub_source_folder + '_' + config_dto.sub_sub_source_folder_1 +'_controller.py'))
93
+ read_replace_create_file(sample_main_controller_file_path, replacements, target_project_main_controller_path)
94
+
95
+
96
+ def read_replace_create_file(sample_file_path:str, replacements, target_file_path):
97
+ file_content = read_file(sample_file_path)
98
+ after_replace_content = replace_template_vars(file_content, replacements)
99
+
100
+ create_file(target_file_path, after_replace_content)
101
+
102
+ def read_file(template_file_path) -> str:
103
+ with open(template_file_path, 'r', encoding='utf-8') as f:
104
+ template_file = f.read()
105
+ return template_file
106
+
107
+ def replace_template_vars(template: str, replacements: dict) -> str:
108
+ result = template
109
+ if replacements:
110
+ for key, value in replacements.items():
111
+ placeholder = f"{{{{{key}}}}}"
112
+ result = result.replace(placeholder, str(value))
113
+ return result
114
+
115
+
116
+ def create_file(target_path, target_file_content):
117
+ target_path.parent.mkdir(parents=True, exist_ok=True)
118
+ with open(target_path, 'w', encoding='utf-8') as f:
119
+ f.write(target_file_content)
120
+
121
+ def read_config_file(find_config_path):
122
+ config = configparser.ConfigParser()
123
+ config.optionxform = str
124
+
125
+ with open(find_config_path, 'r', encoding='utf-8') as f:
126
+ content = f.read()
127
+ if not content.lstrip().startswith('['):
128
+ content = '[DEFAULT]\n' + content
129
+ config.read_string(content)
130
+
131
+ work_space = config.get('DEFAULT', 'work_space', fallback='.')
132
+ str_sub_project_name = config.get('DEFAULT', 'sub_project_name', fallback='.')
133
+ str_sub_source_folder = config.get('DEFAULT', 'sub_source_folder', fallback='.')
134
+ str_source_folder_1 = config.get('DEFAULT', 'sub_sub_source_folder_1', fallback='.')
135
+ return ConfigDTO(
136
+ work_space=work_space,
137
+ sub_project_name=str_sub_project_name,
138
+ sub_source_folder=str_sub_source_folder,
139
+ sub_sub_source_folder_1=str_source_folder_1
140
+ )
141
+
142
+ @dataclass
143
+ class ConfigDTO:
144
+ work_space: str
145
+ sub_project_name:str
146
+ sub_source_folder:str
147
+ sub_sub_source_folder_1:str
148
+
149
+ if __name__ == "__main__":
150
+ generate_code()
File without changes
File without changes
File without changes
pilot/db/__init__.py ADDED
File without changes