pyjallib 0.1.9__py3-none-any.whl → 0.1.10__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.
- pyjallib/__init__.py +1 -1
- pyjallib/max/ConfigFiles/Default_3DSMaxNamingConfig.json +161 -0
- pyjallib/max/__init__.py +14 -2
- pyjallib/max/anim.py +60 -36
- pyjallib/max/autoClavicle.py +97 -132
- pyjallib/max/autoClavicleChain.py +173 -0
- pyjallib/max/bip.py +211 -14
- pyjallib/max/bone.py +341 -16
- pyjallib/max/groinBone.py +116 -77
- pyjallib/max/groinBoneChain.py +173 -0
- pyjallib/max/header.py +42 -6
- pyjallib/max/helper.py +3 -21
- pyjallib/max/hip.py +239 -366
- pyjallib/max/kneeBone.py +517 -0
- pyjallib/max/macro/jal_macro_align.py +11 -10
- pyjallib/max/macro/jal_macro_bone.py +2 -1
- pyjallib/max/macro/jal_macro_constraint.py +2 -1
- pyjallib/max/macro/jal_macro_helper.py +2 -1
- pyjallib/max/macro/jal_macro_link.py +2 -1
- pyjallib/max/macro/jal_macro_select.py +2 -1
- pyjallib/max/mirror.py +1 -1
- pyjallib/max/twistBone.py +258 -475
- pyjallib/max/twistBoneChain.py +162 -0
- pyjallib/max/volumeBone.py +273 -0
- pyjallib/max/volumeBoneChain.py +363 -0
- pyjallib/namePart.py +16 -16
- pyjallib/nameToPath.py +1 -1
- pyjallib/naming.py +15 -16
- pyjallib/namingConfig.py +3 -3
- {pyjallib-0.1.9.dist-info → pyjallib-0.1.10.dist-info}/METADATA +1 -1
- pyjallib-0.1.10.dist-info/RECORD +46 -0
- pyjallib/max/volumePreserveBone.py +0 -209
- pyjallib/p4module.py +0 -488
- pyjallib-0.1.9.dist-info/RECORD +0 -41
- {pyjallib-0.1.9.dist-info → pyjallib-0.1.10.dist-info}/WHEEL +0 -0
pyjallib/p4module.py
DELETED
@@ -1,488 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
P4Python을 사용하는 Perforce 모듈.
|
3
|
-
|
4
|
-
이 모듈은 P4Python을 사용하여 Perforce 서버와 상호작용하는 기능을 제공합니다.
|
5
|
-
주요 기능:
|
6
|
-
- 워크스페이스 연결
|
7
|
-
- 체인지리스트 관리 (생성, 조회, 편집, 제출, 되돌리기)
|
8
|
-
- 파일 작업 (체크아웃, 추가, 삭제)
|
9
|
-
- 파일 동기화 및 업데이트 확인
|
10
|
-
"""
|
11
|
-
|
12
|
-
import logging
|
13
|
-
from P4 import P4, P4Exception
|
14
|
-
import os
|
15
|
-
from pathlib import Path
|
16
|
-
|
17
|
-
# 로깅 설정
|
18
|
-
logger = logging.getLogger(__name__)
|
19
|
-
logger.setLevel(logging.DEBUG)
|
20
|
-
# 사용자 문서 폴더 내 로그 파일 저장
|
21
|
-
log_path = os.path.join(Path.home() / "Documents", 'p4module.log')
|
22
|
-
file_handler = logging.FileHandler(log_path, encoding='utf-8')
|
23
|
-
file_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
|
24
|
-
logger.addHandler(file_handler)
|
25
|
-
|
26
|
-
|
27
|
-
class P4Module:
|
28
|
-
"""P4Python을 사용하여 Perforce 작업을 수행하는 클래스."""
|
29
|
-
|
30
|
-
def __init__(self):
|
31
|
-
"""P4Module 인스턴스를 초기화합니다."""
|
32
|
-
self.p4 = P4()
|
33
|
-
self.connected = False
|
34
|
-
logger.info("P4Module 인스턴스 생성됨")
|
35
|
-
|
36
|
-
def _is_connected(self) -> bool:
|
37
|
-
"""Perforce 서버 연결 상태를 확인합니다.
|
38
|
-
|
39
|
-
Returns:
|
40
|
-
bool: 연결되어 있으면 True, 아니면 False
|
41
|
-
"""
|
42
|
-
if not self.connected:
|
43
|
-
logger.warning("Perforce 서버에 연결되지 않았습니다.")
|
44
|
-
return False
|
45
|
-
return True
|
46
|
-
|
47
|
-
def _handle_p4_exception(self, e: P4Exception, context_msg: str = "") -> None:
|
48
|
-
"""P4Exception을 처리하고 로깅합니다.
|
49
|
-
|
50
|
-
Args:
|
51
|
-
e (P4Exception): 발생한 예외
|
52
|
-
context_msg (str, optional): 예외가 발생한 컨텍스트 설명
|
53
|
-
"""
|
54
|
-
logger.error(f"{context_msg} 중 P4Exception 발생: {e}")
|
55
|
-
for err in self.p4.errors:
|
56
|
-
logger.error(f" P4 Error: {err}")
|
57
|
-
for warn in self.p4.warnings:
|
58
|
-
logger.warning(f" P4 Warning: {warn}")
|
59
|
-
|
60
|
-
def connect(self, workspace_name: str) -> bool:
|
61
|
-
"""지정된 워크스페이스에 연결합니다.
|
62
|
-
|
63
|
-
Args:
|
64
|
-
workspace_name (str): 연결할 워크스페이스 이름
|
65
|
-
|
66
|
-
Returns:
|
67
|
-
bool: 연결 성공 시 True, 실패 시 False
|
68
|
-
"""
|
69
|
-
logger.info(f"'{workspace_name}' 워크스페이스에 연결 시도 중...")
|
70
|
-
try:
|
71
|
-
self.p4.client = workspace_name
|
72
|
-
self.p4.connect()
|
73
|
-
self.connected = True
|
74
|
-
logger.info(f"'{workspace_name}' 워크스페이스에 성공적으로 연결됨 (User: {self.p4.user}, Port: {self.p4.port})")
|
75
|
-
return True
|
76
|
-
except P4Exception as e:
|
77
|
-
self.connected = False
|
78
|
-
self._handle_p4_exception(e, f"'{workspace_name}' 워크스페이스 연결")
|
79
|
-
return False
|
80
|
-
|
81
|
-
def get_pending_change_list(self) -> list:
|
82
|
-
"""워크스페이스의 Pending된 체인지 리스트를 가져옵니다.
|
83
|
-
|
84
|
-
Returns:
|
85
|
-
list: 체인지 리스트 정보 딕셔너리들의 리스트
|
86
|
-
"""
|
87
|
-
if not self._is_connected():
|
88
|
-
return []
|
89
|
-
logger.debug("Pending 체인지 리스트 조회 중...")
|
90
|
-
try:
|
91
|
-
pending_changes = self.p4.run_changes("-s", "pending", "-u", self.p4.user, "-c", self.p4.client)
|
92
|
-
change_numbers = [int(cl['change']) for cl in pending_changes]
|
93
|
-
|
94
|
-
# 각 체인지 리스트 번호에 대한 상세 정보 가져오기
|
95
|
-
change_list_info = []
|
96
|
-
for change_number in change_numbers:
|
97
|
-
cl_info = self.get_change_list_by_number(change_number)
|
98
|
-
if cl_info:
|
99
|
-
change_list_info.append(cl_info)
|
100
|
-
|
101
|
-
logger.info(f"Pending 체인지 리스트 {len(change_list_info)}개 조회 완료")
|
102
|
-
return change_list_info
|
103
|
-
except P4Exception as e:
|
104
|
-
self._handle_p4_exception(e, "Pending 체인지 리스트 조회")
|
105
|
-
return []
|
106
|
-
|
107
|
-
def create_change_list(self, description: str) -> dict:
|
108
|
-
"""새로운 체인지 리스트를 생성합니다.
|
109
|
-
|
110
|
-
Args:
|
111
|
-
description (str): 체인지 리스트 설명
|
112
|
-
|
113
|
-
Returns:
|
114
|
-
dict: 생성된 체인지 리스트 정보. 실패 시 빈 딕셔너리
|
115
|
-
"""
|
116
|
-
if not self._is_connected():
|
117
|
-
return {}
|
118
|
-
logger.info(f"새 체인지 리스트 생성 시도: '{description}'")
|
119
|
-
try:
|
120
|
-
change_spec = self.p4.fetch_change()
|
121
|
-
change_spec["Description"] = description
|
122
|
-
result = self.p4.save_change(change_spec)
|
123
|
-
created_change_number = int(result[0].split()[1])
|
124
|
-
logger.info(f"체인지 리스트 {created_change_number} 생성 완료: '{description}'")
|
125
|
-
return self.get_change_list_by_number(created_change_number)
|
126
|
-
except P4Exception as e:
|
127
|
-
self._handle_p4_exception(e, f"체인지 리스트 생성 ('{description}')")
|
128
|
-
return {}
|
129
|
-
except (IndexError, ValueError) as e:
|
130
|
-
logger.error(f"체인지 리스트 번호 파싱 오류: {e}")
|
131
|
-
return {}
|
132
|
-
|
133
|
-
def get_change_list_by_number(self, change_list_number: int) -> dict:
|
134
|
-
"""체인지 리스트 번호로 체인지 리스트를 가져옵니다.
|
135
|
-
|
136
|
-
Args:
|
137
|
-
change_list_number (int): 체인지 리스트 번호
|
138
|
-
|
139
|
-
Returns:
|
140
|
-
dict: 체인지 리스트 정보. 실패 시 빈 딕셔너리
|
141
|
-
"""
|
142
|
-
if not self._is_connected():
|
143
|
-
return {}
|
144
|
-
logger.debug(f"체인지 리스트 {change_list_number} 정보 조회 중...")
|
145
|
-
try:
|
146
|
-
cl_info = self.p4.fetch_change(change_list_number)
|
147
|
-
if cl_info:
|
148
|
-
logger.info(f"체인지 리스트 {change_list_number} 정보 조회 완료.")
|
149
|
-
return cl_info
|
150
|
-
else:
|
151
|
-
logger.warning(f"체인지 리스트 {change_list_number}를 찾을 수 없습니다.")
|
152
|
-
return {}
|
153
|
-
except P4Exception as e:
|
154
|
-
self._handle_p4_exception(e, f"체인지 리스트 {change_list_number} 정보 조회")
|
155
|
-
return {}
|
156
|
-
|
157
|
-
def get_change_list_by_description(self, description: str) -> dict:
|
158
|
-
"""체인지 리스트 설명으로 체인지 리스트를 가져옵니다.
|
159
|
-
|
160
|
-
Args:
|
161
|
-
description (str): 체인지 리스트 설명
|
162
|
-
|
163
|
-
Returns:
|
164
|
-
dict: 체인지 리스트 정보 (일치하는 첫 번째 체인지 리스트)
|
165
|
-
"""
|
166
|
-
if not self._is_connected():
|
167
|
-
return {}
|
168
|
-
logger.debug(f"설명으로 체인지 리스트 조회 중: '{description}'")
|
169
|
-
try:
|
170
|
-
pending_changes = self.p4.run_changes("-l", "-s", "pending", "-u", self.p4.user, "-c", self.p4.client)
|
171
|
-
for cl in pending_changes:
|
172
|
-
cl_desc = cl.get('Description', b'').decode('utf-8', 'replace').strip()
|
173
|
-
if cl_desc == description.strip():
|
174
|
-
logger.info(f"설명 '{description}'에 해당하는 체인지 리스트 {cl['change']} 조회 완료.")
|
175
|
-
return self.get_change_list_by_number(int(cl['change']))
|
176
|
-
logger.info(f"설명 '{description}'에 해당하는 Pending 체인지 리스트를 찾을 수 없습니다.")
|
177
|
-
return {}
|
178
|
-
except P4Exception as e:
|
179
|
-
self._handle_p4_exception(e, f"설명으로 체인지 리스트 조회 ('{description}')")
|
180
|
-
return {}
|
181
|
-
|
182
|
-
def edit_change_list(self, change_list_number: int, description: str = None, add_file_paths: list = None, remove_file_paths: list = None) -> dict:
|
183
|
-
"""체인지 리스트를 편집합니다.
|
184
|
-
|
185
|
-
Args:
|
186
|
-
change_list_number (int): 체인지 리스트 번호
|
187
|
-
description (str, optional): 변경할 설명
|
188
|
-
add_file_paths (list, optional): 추가할 파일 경로 리스트
|
189
|
-
remove_file_paths (list, optional): 제거할 파일 경로 리스트
|
190
|
-
|
191
|
-
Returns:
|
192
|
-
dict: 업데이트된 체인지 리스트 정보
|
193
|
-
"""
|
194
|
-
if not self._is_connected():
|
195
|
-
return {}
|
196
|
-
logger.info(f"체인지 리스트 {change_list_number} 편집 시도...")
|
197
|
-
try:
|
198
|
-
if description is not None:
|
199
|
-
change_spec = self.p4.fetch_change(change_list_number)
|
200
|
-
current_description = change_spec.get('Description', '').strip()
|
201
|
-
if current_description != description.strip():
|
202
|
-
change_spec['Description'] = description
|
203
|
-
self.p4.save_change(change_spec)
|
204
|
-
logger.info(f"체인지 리스트 {change_list_number} 설명 변경 완료: '{description}'")
|
205
|
-
|
206
|
-
if add_file_paths:
|
207
|
-
for file_path in add_file_paths:
|
208
|
-
try:
|
209
|
-
self.p4.run_reopen("-c", change_list_number, file_path)
|
210
|
-
logger.info(f"파일 '{file_path}'를 체인지 리스트 {change_list_number}로 이동 완료.")
|
211
|
-
except P4Exception as e_reopen:
|
212
|
-
self._handle_p4_exception(e_reopen, f"파일 '{file_path}'을 CL {change_list_number}로 이동")
|
213
|
-
|
214
|
-
if remove_file_paths:
|
215
|
-
for file_path in remove_file_paths:
|
216
|
-
try:
|
217
|
-
self.p4.run_revert("-c", change_list_number, file_path)
|
218
|
-
logger.info(f"파일 '{file_path}'를 체인지 리스트 {change_list_number}에서 제거(revert) 완료.")
|
219
|
-
except P4Exception as e_revert:
|
220
|
-
self._handle_p4_exception(e_revert, f"파일 '{file_path}'을 CL {change_list_number}에서 제거(revert)")
|
221
|
-
|
222
|
-
return self.get_change_list_by_number(change_list_number)
|
223
|
-
|
224
|
-
except P4Exception as e:
|
225
|
-
self._handle_p4_exception(e, f"체인지 리스트 {change_list_number} 편집")
|
226
|
-
return self.get_change_list_by_number(change_list_number)
|
227
|
-
|
228
|
-
def _file_op(self, command: str, file_path: str, change_list_number: int, op_name: str) -> bool:
|
229
|
-
"""파일 작업을 수행하는 내부 헬퍼 함수입니다.
|
230
|
-
|
231
|
-
Args:
|
232
|
-
command (str): 실행할 명령어 (edit/add/delete)
|
233
|
-
file_path (str): 대상 파일 경로
|
234
|
-
change_list_number (int): 체인지 리스트 번호
|
235
|
-
op_name (str): 작업 이름 (로깅용)
|
236
|
-
|
237
|
-
Returns:
|
238
|
-
bool: 작업 성공 시 True, 실패 시 False
|
239
|
-
"""
|
240
|
-
if not self._is_connected():
|
241
|
-
return False
|
242
|
-
logger.info(f"파일 '{file_path}'에 대한 '{op_name}' 작업 시도 (CL: {change_list_number})...")
|
243
|
-
try:
|
244
|
-
if command == "edit":
|
245
|
-
self.p4.run_edit("-c", change_list_number, file_path)
|
246
|
-
elif command == "add":
|
247
|
-
self.p4.run_add("-c", change_list_number, file_path)
|
248
|
-
elif command == "delete":
|
249
|
-
self.p4.run_delete("-c", change_list_number, file_path)
|
250
|
-
else:
|
251
|
-
logger.error(f"지원되지 않는 파일 작업: {command}")
|
252
|
-
return False
|
253
|
-
logger.info(f"파일 '{file_path}'에 대한 '{op_name}' 작업 성공 (CL: {change_list_number}).")
|
254
|
-
return True
|
255
|
-
except P4Exception as e:
|
256
|
-
self._handle_p4_exception(e, f"파일 '{file_path}' {op_name} (CL: {change_list_number})")
|
257
|
-
return False
|
258
|
-
|
259
|
-
def checkout_file(self, file_path: str, change_list_number: int) -> bool:
|
260
|
-
"""파일을 체크아웃합니다.
|
261
|
-
|
262
|
-
Args:
|
263
|
-
file_path (str): 체크아웃할 파일 경로
|
264
|
-
change_list_number (int): 체인지 리스트 번호
|
265
|
-
|
266
|
-
Returns:
|
267
|
-
bool: 체크아웃 성공 시 True, 실패 시 False
|
268
|
-
"""
|
269
|
-
return self._file_op("edit", file_path, change_list_number, "체크아웃")
|
270
|
-
|
271
|
-
def add_file(self, file_path: str, change_list_number: int) -> bool:
|
272
|
-
"""파일을 추가합니다.
|
273
|
-
|
274
|
-
Args:
|
275
|
-
file_path (str): 추가할 파일 경로
|
276
|
-
change_list_number (int): 체인지 리스트 번호
|
277
|
-
|
278
|
-
Returns:
|
279
|
-
bool: 추가 성공 시 True, 실패 시 False
|
280
|
-
"""
|
281
|
-
return self._file_op("add", file_path, change_list_number, "추가")
|
282
|
-
|
283
|
-
def delete_file(self, file_path: str, change_list_number: int) -> bool:
|
284
|
-
"""파일을 삭제합니다.
|
285
|
-
|
286
|
-
Args:
|
287
|
-
file_path (str): 삭제할 파일 경로
|
288
|
-
change_list_number (int): 체인지 리스트 번호
|
289
|
-
|
290
|
-
Returns:
|
291
|
-
bool: 삭제 성공 시 True, 실패 시 False
|
292
|
-
"""
|
293
|
-
return self._file_op("delete", file_path, change_list_number, "삭제")
|
294
|
-
|
295
|
-
def submit_change_list(self, change_list_number: int) -> bool:
|
296
|
-
"""체인지 리스트를 제출합니다.
|
297
|
-
|
298
|
-
Args:
|
299
|
-
change_list_number (int): 제출할 체인지 리스트 번호
|
300
|
-
|
301
|
-
Returns:
|
302
|
-
bool: 제출 성공 시 True, 실패 시 False
|
303
|
-
"""
|
304
|
-
if not self._is_connected():
|
305
|
-
return False
|
306
|
-
logger.info(f"체인지 리스트 {change_list_number} 제출 시도...")
|
307
|
-
try:
|
308
|
-
self.p4.run_submit("-c", change_list_number)
|
309
|
-
logger.info(f"체인지 리스트 {change_list_number} 제출 성공.")
|
310
|
-
return True
|
311
|
-
except P4Exception as e:
|
312
|
-
self._handle_p4_exception(e, f"체인지 리스트 {change_list_number} 제출")
|
313
|
-
if any("nothing to submit" in err.lower() for err in self.p4.errors):
|
314
|
-
logger.warning(f"체인지 리스트 {change_list_number}에 제출할 파일이 없습니다.")
|
315
|
-
return False
|
316
|
-
|
317
|
-
def revert_change_list(self, change_list_number: int) -> bool:
|
318
|
-
"""체인지 리스트를 되돌리고 삭제합니다.
|
319
|
-
|
320
|
-
체인지 리스트 내 모든 파일을 되돌린 후 빈 체인지 리스트를 삭제합니다.
|
321
|
-
|
322
|
-
Args:
|
323
|
-
change_list_number (int): 되돌릴 체인지 리스트 번호
|
324
|
-
|
325
|
-
Returns:
|
326
|
-
bool: 되돌리기 및 삭제 성공 시 True, 실패 시 False
|
327
|
-
"""
|
328
|
-
if not self._is_connected():
|
329
|
-
return False
|
330
|
-
logger.info(f"체인지 리스트 {change_list_number} 전체 되돌리기 및 삭제 시도...")
|
331
|
-
try:
|
332
|
-
# 체인지 리스트의 모든 파일 되돌리기
|
333
|
-
self.p4.run_revert("-c", change_list_number, "//...")
|
334
|
-
logger.info(f"체인지 리스트 {change_list_number} 전체 되돌리기 성공.")
|
335
|
-
|
336
|
-
# 빈 체인지 리스트 삭제
|
337
|
-
try:
|
338
|
-
self.p4.run_change("-d", change_list_number)
|
339
|
-
logger.info(f"체인지 리스트 {change_list_number} 삭제 완료.")
|
340
|
-
except P4Exception as e_delete:
|
341
|
-
self._handle_p4_exception(e_delete, f"체인지 리스트 {change_list_number} 삭제")
|
342
|
-
logger.warning(f"파일 되돌리기는 성공했으나 체인지 리스트 {change_list_number} 삭제에 실패했습니다.")
|
343
|
-
return False
|
344
|
-
|
345
|
-
return True
|
346
|
-
except P4Exception as e:
|
347
|
-
self._handle_p4_exception(e, f"체인지 리스트 {change_list_number} 전체 되돌리기")
|
348
|
-
return False
|
349
|
-
|
350
|
-
def delete_empty_change_list(self, change_list_number: int) -> bool:
|
351
|
-
"""빈 체인지 리스트를 삭제합니다.
|
352
|
-
|
353
|
-
Args:
|
354
|
-
change_list_number (int): 삭제할 체인지 리스트 번호
|
355
|
-
|
356
|
-
Returns:
|
357
|
-
bool: 삭제 성공 시 True, 실패 시 False
|
358
|
-
"""
|
359
|
-
if not self._is_connected():
|
360
|
-
return False
|
361
|
-
|
362
|
-
logger.info(f"체인지 리스트 {change_list_number} 삭제 시도 중...")
|
363
|
-
try:
|
364
|
-
# 체인지 리스트 정보 가져오기
|
365
|
-
change_spec = self.p4.fetch_change(change_list_number)
|
366
|
-
|
367
|
-
# 파일이 있는지 확인
|
368
|
-
if change_spec and change_spec.get('Files') and len(change_spec['Files']) > 0:
|
369
|
-
logger.warning(f"체인지 리스트 {change_list_number}에 파일이 {len(change_spec['Files'])}개 있어 삭제할 수 없습니다.")
|
370
|
-
return False
|
371
|
-
|
372
|
-
# 빈 체인지 리스트 삭제
|
373
|
-
self.p4.run_change("-d", change_list_number)
|
374
|
-
logger.info(f"빈 체인지 리스트 {change_list_number} 삭제 완료.")
|
375
|
-
return True
|
376
|
-
except P4Exception as e:
|
377
|
-
self._handle_p4_exception(e, f"체인지 리스트 {change_list_number} 삭제")
|
378
|
-
return False
|
379
|
-
|
380
|
-
def revert_files(self, change_list_number: int, file_paths: list) -> bool:
|
381
|
-
"""체인지 리스트 내의 특정 파일들을 되돌립니다.
|
382
|
-
|
383
|
-
Args:
|
384
|
-
change_list_number (int): 체인지 리스트 번호
|
385
|
-
file_paths (list): 되돌릴 파일 경로 리스트
|
386
|
-
|
387
|
-
Returns:
|
388
|
-
bool: 되돌리기 성공 시 True, 실패 시 False
|
389
|
-
"""
|
390
|
-
if not self._is_connected():
|
391
|
-
return False
|
392
|
-
if not file_paths:
|
393
|
-
logger.warning("되돌릴 파일 목록이 비어있습니다.")
|
394
|
-
return True
|
395
|
-
|
396
|
-
logger.info(f"체인지 리스트 {change_list_number}에서 {len(file_paths)}개 파일 되돌리기 시도...")
|
397
|
-
try:
|
398
|
-
for file_path in file_paths:
|
399
|
-
self.p4.run_revert("-c", change_list_number, file_path)
|
400
|
-
logger.info(f"파일 '{file_path}'를 체인지 리스트 {change_list_number}에서 되돌리기 성공.")
|
401
|
-
return True
|
402
|
-
except P4Exception as e:
|
403
|
-
self._handle_p4_exception(e, f"체인지 리스트 {change_list_number}에서 파일 되돌리기")
|
404
|
-
return False
|
405
|
-
|
406
|
-
def check_update_required(self, file_paths: list) -> bool:
|
407
|
-
"""파일들의 업데이트 필요 여부를 확인합니다.
|
408
|
-
|
409
|
-
Args:
|
410
|
-
file_paths (list): 확인할 파일 경로 리스트
|
411
|
-
|
412
|
-
Returns:
|
413
|
-
bool: 업데이트가 필요한 파일이 있으면 True, 없으면 False
|
414
|
-
"""
|
415
|
-
if not self._is_connected():
|
416
|
-
return False
|
417
|
-
if not file_paths:
|
418
|
-
logger.debug("업데이트 필요 여부 확인할 파일 목록이 비어있습니다.")
|
419
|
-
return False
|
420
|
-
logger.debug(f"파일 업데이트 필요 여부 확인 중 (파일 {len(file_paths)}개): {file_paths}")
|
421
|
-
try:
|
422
|
-
sync_preview_results = self.p4.run_sync("-n", file_paths)
|
423
|
-
needs_update = False
|
424
|
-
for result in sync_preview_results:
|
425
|
-
if isinstance(result, dict):
|
426
|
-
if 'up-to-date' not in result.get('how', '') and \
|
427
|
-
'no such file(s)' not in result.get('depotFile', ''):
|
428
|
-
if result.get('how') and 'syncing' in result.get('how'):
|
429
|
-
needs_update = True
|
430
|
-
logger.info(f"파일 '{result.get('clientFile', result.get('depotFile'))}' 업데이트 필요: {result.get('how')}")
|
431
|
-
break
|
432
|
-
elif result.get('action') and result.get('action') not in ['checked', 'exists']:
|
433
|
-
needs_update = True
|
434
|
-
logger.info(f"파일 '{result.get('clientFile', result.get('depotFile'))}' 업데이트 필요 (action: {result.get('action')})")
|
435
|
-
break
|
436
|
-
elif isinstance(result, str):
|
437
|
-
if "up-to-date" not in result and "no such file(s)" not in result:
|
438
|
-
needs_update = True
|
439
|
-
logger.info(f"파일 업데이트 필요 (문자열 결과): {result}")
|
440
|
-
break
|
441
|
-
|
442
|
-
if needs_update:
|
443
|
-
logger.info(f"지정된 파일 중 업데이트가 필요한 파일이 있습니다.")
|
444
|
-
else:
|
445
|
-
logger.info(f"지정된 모든 파일이 최신 상태입니다.")
|
446
|
-
return needs_update
|
447
|
-
except P4Exception as e:
|
448
|
-
self._handle_p4_exception(e, f"파일 업데이트 필요 여부 확인 ({file_paths})")
|
449
|
-
return False
|
450
|
-
|
451
|
-
def sync_files(self, file_paths: list) -> bool:
|
452
|
-
"""파일들을 동기화합니다.
|
453
|
-
|
454
|
-
Args:
|
455
|
-
file_paths (list): 동기화할 파일 경로 리스트
|
456
|
-
|
457
|
-
Returns:
|
458
|
-
bool: 동기화 성공 시 True, 실패 시 False
|
459
|
-
"""
|
460
|
-
if not self._is_connected():
|
461
|
-
return False
|
462
|
-
if not file_paths:
|
463
|
-
logger.debug("싱크할 파일 목록이 비어있습니다.")
|
464
|
-
return True
|
465
|
-
logger.info(f"파일 싱크 시도 (파일 {len(file_paths)}개): {file_paths}")
|
466
|
-
try:
|
467
|
-
self.p4.run_sync(file_paths)
|
468
|
-
logger.info(f"파일 싱크 완료: {file_paths}")
|
469
|
-
return True
|
470
|
-
except P4Exception as e:
|
471
|
-
self._handle_p4_exception(e, f"파일 싱크 ({file_paths})")
|
472
|
-
return False
|
473
|
-
|
474
|
-
def disconnect(self):
|
475
|
-
"""Perforce 서버와의 연결을 해제합니다."""
|
476
|
-
if self.connected:
|
477
|
-
try:
|
478
|
-
self.p4.disconnect()
|
479
|
-
self.connected = False
|
480
|
-
logger.info("Perforce 서버 연결 해제 완료.")
|
481
|
-
except P4Exception as e:
|
482
|
-
self._handle_p4_exception(e, "Perforce 서버 연결 해제")
|
483
|
-
else:
|
484
|
-
logger.debug("Perforce 서버에 이미 연결되지 않은 상태입니다.")
|
485
|
-
|
486
|
-
def __del__(self):
|
487
|
-
"""객체가 소멸될 때 자동으로 연결을 해제합니다."""
|
488
|
-
self.disconnect()
|
pyjallib-0.1.9.dist-info/RECORD
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
pyjallib/__init__.py,sha256=X0ZMNtwB41sBz52zFz6ZLQDJuIjEdglhcBsjWcE-v2U,460
|
2
|
-
pyjallib/namePart.py,sha256=D1hnFNnZbrNicAiW2ZUaIT0LU5pro3uFYrFYOEjt7_Y,24001
|
3
|
-
pyjallib/nameToPath.py,sha256=61EWrc0Wc1K1Qsc4G6jewIccI0IHbiZWroRcU_lX1Wc,4664
|
4
|
-
pyjallib/naming.py,sha256=jJ6w0n_nnUE2uZy_I4KFsMx95Ij3_KvSjhVvQQplxpw,36621
|
5
|
-
pyjallib/namingConfig.py,sha256=6Wyk3h1dFrzOslSoqjLftSUqt7U00tnR2WcgxYWVx5I,33969
|
6
|
-
pyjallib/p4module.py,sha256=hr5a7L3UMNUXaZoNU6Z0BHqJ-d28b7bYL0BEmvFi-84,22071
|
7
|
-
pyjallib/perforce.py,sha256=K_FAeDvecdaMT4INUcDluSB6k2NQ8R1NaddTzqLu-q0,24211
|
8
|
-
pyjallib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
pyjallib/reloadModules.py,sha256=RAEG3IxzJ0TlsjvnZwJt56JOkc2j8voqAnRbfQuZ44g,1151
|
10
|
-
pyjallib/ConfigFiles/namingConfig.json,sha256=Ov4bbVJb6qodPaooU63e11YUMGXXPWFAA4AQq1sLBYU,1486
|
11
|
-
pyjallib/max/__init__.py,sha256=1058Mvp_Ebf3DG_DVkAC4o_frQPq7F6-m-C-Ccme64k,1064
|
12
|
-
pyjallib/max/align.py,sha256=HKjCViQCuicGmtvHB6xxVv4BEGEBGtV2gO3NvR_6R2A,5183
|
13
|
-
pyjallib/max/anim.py,sha256=-shQeE0WeAeCefc8FoI63dNDLHhz0uzOJ4shp5AL_Cs,25135
|
14
|
-
pyjallib/max/autoClavicle.py,sha256=ZP2Ow1tJln-KC68s3hNJt4j3uvXQljS2kT2HA4kNgng,7746
|
15
|
-
pyjallib/max/bip.py,sha256=m6eA-rg-MghYSxbzj-YXa0KJFPm1wiOsOqyJu76_hlY,16967
|
16
|
-
pyjallib/max/bone.py,sha256=wfGGoLSxg9gSi9SkdwW2f90ncwYi0EnxathFuWFo9a4,33536
|
17
|
-
pyjallib/max/constraint.py,sha256=93g-X0aZHtZMKXVKr8xMjIhbKou61yc2b3ubQKJquBs,40589
|
18
|
-
pyjallib/max/groinBone.py,sha256=YViTe7d3lqk3F2tjmoPS310AentP5Ei2S5tp3NuxnOw,4150
|
19
|
-
pyjallib/max/header.py,sha256=K3DnsWatEMrrjTXf8gxAzcqtaMVWXH5TU12yX4L5IMM,2829
|
20
|
-
pyjallib/max/helper.py,sha256=WPoxSoHAFXmAPx_CRJFWBNXn4S2k04UK-1J9x6nIv84,18674
|
21
|
-
pyjallib/max/hip.py,sha256=regBNOwbM9AK4dsyZK6rHq0cXSvW0U-Fuxp07AEkznU,14172
|
22
|
-
pyjallib/max/layer.py,sha256=e9Mn8h7xf0oBYST3QIpyBpLMl8qpWTExO9Y6yH6rKc0,8795
|
23
|
-
pyjallib/max/link.py,sha256=J3z9nkP8ZxAh9yYhR16tjQFCJTCYZMSB0MGbSHfA7uI,2592
|
24
|
-
pyjallib/max/mirror.py,sha256=j8LnsXowyTINzvtWsvCNaDsQ6v7u2RjlY50R8v5JCuc,14517
|
25
|
-
pyjallib/max/morph.py,sha256=I8HRYx4NznL6GZL4CbT9iTv05SeaBW_mJJ4PzMxCBkw,12664
|
26
|
-
pyjallib/max/name.py,sha256=DcJt2td-N7vfUGyWazdGTD4-0JW-noa7z5nwc6SHm6I,15337
|
27
|
-
pyjallib/max/select.py,sha256=HMJD2WNX3zVBEeYrj0UX2YXM3fHNItfw6UtQSItNsoU,9487
|
28
|
-
pyjallib/max/skin.py,sha256=5mBzG2wSUxoGlkFeb9Ys8uUxOwuZRGeqUMTI9LiWWZU,41937
|
29
|
-
pyjallib/max/twistBone.py,sha256=lEjEo74eg_U7cvDT7yUiyn_XVIeaSV5L0jxMdG6eBY4,20305
|
30
|
-
pyjallib/max/volumePreserveBone.py,sha256=Fd5yjrR7XqLoXXrqwp3EwgRQGNFZ0k-rfkF0Rg3SoS8,7917
|
31
|
-
pyjallib/max/ConfigFiles/3DSMaxNamingConfig.json,sha256=PBUYawCELG0aLNRdTh6j-Yka4eNdmpF4P8iRyp0Ngpg,3717
|
32
|
-
pyjallib/max/macro/jal_macro_align.py,sha256=t0gQjybkHYAvPtjT5uWjUQd1vsXIsxOkdYfhFWduxJU,4270
|
33
|
-
pyjallib/max/macro/jal_macro_bone.py,sha256=QS492tskLrARGIFDmbKEwJw7122xJga0ZP5z8WVVRn8,12422
|
34
|
-
pyjallib/max/macro/jal_macro_constraint.py,sha256=0gpfan7hXES9jhnpZVlxWtCbqUCyGxjtSmVMbp7nUh8,4160
|
35
|
-
pyjallib/max/macro/jal_macro_helper.py,sha256=ODwAl4C6WK2UE45dqpfw90TgN5vDjLJvODvYeO8tj4o,12906
|
36
|
-
pyjallib/max/macro/jal_macro_link.py,sha256=xkgcCX0fJw4vLfMYybtfUklT3dgcO0tHfpt2X9BfWLw,1193
|
37
|
-
pyjallib/max/macro/jal_macro_select.py,sha256=-r24l84XmDEM4W6H0r1jOBErp3q0UxNrr0m9oAHSgkE,2289
|
38
|
-
pyjallib/max/ui/Container.py,sha256=QSk3oCqhfiR4aglSSkherRGAyPFqMRUt83L-0ENBz-s,5571
|
39
|
-
pyjallib-0.1.9.dist-info/METADATA,sha256=bStdJghGgF0w3fRQCOYLkZJ72WO-Krq61BrQl-gp6Cs,869
|
40
|
-
pyjallib-0.1.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
41
|
-
pyjallib-0.1.9.dist-info/RECORD,,
|
File without changes
|