xython 4.6.3__tar.gz → 4.7.1__tar.gz
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.
- {xython-4.6.3/src/xython.egg-info → xython-4.7.1}/PKG-INFO +67 -57
- {xython-4.6.3 → xython-4.7.1}/README.md +66 -56
- {xython-4.6.3 → xython-4.7.1}/pyproject.toml +1 -1
- {xython-4.6.3 → xython-4.7.1}/src/xython/__init__.py +3 -3
- xython-4.7.1/src/xython/alias_installer.py +119 -0
- xython-4.7.1/src/xython/locales_loader.py +53 -0
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_auto.py +69 -683
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_chrome.py +17 -1
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_color.py +772 -836
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_common.py +498 -478
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_db.py +28 -89
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_edge.py +101 -721
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_excel.py +1925 -2703
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_hwp.py +63 -470
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_list.py +24 -71
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_map.py +23 -49
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_outlook.py +434 -474
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_re.py +278 -532
- xython-4.7.1/src/xython/xy_time.py +3824 -0
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_util.py +701 -71
- xython-4.7.1/src/xython/xy_word.py +6265 -0
- {xython-4.6.3 → xython-4.7.1/src/xython.egg-info}/PKG-INFO +67 -57
- {xython-4.6.3 → xython-4.7.1}/src/xython.egg-info/SOURCES.txt +2 -1
- xython-4.6.3/requirements.txt +0 -0
- xython-4.6.3/src/xython/xy_time.py +0 -5915
- xython-4.6.3/src/xython/xy_word.py +0 -6707
- {xython-4.6.3 → xython-4.7.1}/MANIFEST.in +0 -0
- {xython-4.6.3 → xython-4.7.1}/setup.cfg +0 -0
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_excel_event.py +0 -0
- {xython-4.6.3 → xython-4.7.1}/src/xython/xy_manual.py +0 -0
- {xython-4.6.3 → xython-4.7.1}/src/xython.egg-info/dependency_links.txt +0 -0
- {xython-4.6.3 → xython-4.7.1}/src/xython.egg-info/requires.txt +0 -0
- {xython-4.6.3 → xython-4.7.1}/src/xython.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xython
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.7.1
|
|
4
4
|
Summary: xython package
|
|
5
5
|
Author-email: "SJ.Park" <sjpkorea@naver.com>
|
|
6
6
|
License: MIT
|
|
@@ -19,31 +19,16 @@ Requires-Dist: pymsgbox
|
|
|
19
19
|
Requires-Dist: pywintypes
|
|
20
20
|
Requires-Dist: win32ui
|
|
21
21
|
|
|
22
|
-
#
|
|
23
|
-
> - _easy_start.py를 새로 만들어서 사용하기 쉽게 각 모듈을 만들도록 하였읍니다<br>
|
|
24
|
-
> - from xython.xy_easy_start import load; xy = load()<br>
|
|
25
|
-
> - 위와같이 하면, 별도 객체를 만들지 않아도 사용가능하게 만듦<br>
|
|
26
|
-
> - 자세한 사항은 각 참고 자료를 보시면 됩니다. 기존과같이 하여도 작동을 합니다<br>
|
|
27
|
-
# 4.4.1 (2026-05-24)
|
|
28
|
-
> - 각 모듈의 이름을 xy를 맨앞으로 넣는다 (xyexcel, xytime 등)<br>
|
|
29
|
-
> - 매번 들어가는 함수의 이름들은 과감히 제거를 함 (예: for_range, _value 등)<br>
|
|
30
|
-
> - 여러가지를 전체적으로 변경함<br>
|
|
31
|
-
|
|
32
|
-
# 4.3.8을 기준으로 각 모듈이름을 변경함 (2026-05-16)
|
|
33
|
-
> - 의존성을 줄이기위하여 일부 패키지를 줄이도록 변경<br>
|
|
34
|
-
> - 자동으로 uploader를 사용해서 적용중<br>
|
|
35
|
-
> - 패키지의 일부는 없애고, web용 모듈을 추가함<br>
|
|
36
|
-
|
|
37
|
-
# 4.0.0을 기준으로 각 모듈이름을 변경함 (2025-03-26)
|
|
38
|
-
> - 쉽게 : **xy_** 접두어로 모든 모듈이름을 변경<br>
|
|
39
|
-
> - 공통 변수모듈 : **xy_xommon**으로 변경<br>
|
|
40
|
-
> - 공통변수이름을 vars => **xvar**로 변경<br>
|
|
41
|
-
|
|
42
|
-
# About xython Package
|
|
22
|
+
# xython Package에 대하여
|
|
43
23
|
|
|
44
24
|
>**Functional Programming for Excel, Hwp, Word, Outlook, Color, Etc by win32com<br>
|
|
45
25
|
It can handle for Excel, Hwp, Word, Outlook, Color, Etc by xython**
|
|
46
26
|
|
|
27
|
+
업무자동화를 위해 Excel, Word, Outlook등을 사용하기 편하게 하기 위해 만든것으로
|
|
28
|
+
각 함수가 독립적인 형태의 결과물이 나오는 함수형으로 만드는 프로그램입니다
|
|
29
|
+
- Python을 사용합니다
|
|
30
|
+
- pywin32를 사용합니다
|
|
31
|
+
- 초보자를 위한 GUI로 사용하는 것과 코딩이 가능한 2가지 방법이 있읍니다
|
|
47
32
|
|
|
48
33
|
## xython 패키지는 함수형 프로그램 이다
|
|
49
34
|
|
|
@@ -72,11 +57,10 @@ It can handle for Excel, Hwp, Word, Outlook, Color, Etc by xython**
|
|
|
72
57
|
|
|
73
58
|
### official website
|
|
74
59
|
> oficial document : **https://sjpkorea.github.io/xython.github.io/**<br>
|
|
75
|
-
> oficial
|
|
60
|
+
> oficial pypi : **https://pypi.org/project/xython/ (Korean base)**<br>
|
|
76
61
|
|
|
77
62
|
|
|
78
63
|
## components about xython package (패키지의 구성)
|
|
79
|
-
**easy wrapper** for belows;
|
|
80
64
|
|
|
81
65
|
| 번호 | xython package | 설명 |
|
|
82
66
|
|----|----------------|---------------------------------------------------|
|
|
@@ -95,7 +79,7 @@ It can handle for Excel, Hwp, Word, Outlook, Color, Etc by xython**
|
|
|
95
79
|
| 13 | xy_util | utilities (**for common use**) |
|
|
96
80
|
| 14 | xy_auto | for Keyboard & Mouse control (**for common use**) |
|
|
97
81
|
| 15 | xy_edge | for edge |
|
|
98
|
-
| 16 | xy_common | 기본 자료
|
|
82
|
+
| 16 | xy_common | xython패키지에 공통으로 사용되는 기본 자료 |
|
|
99
83
|
|
|
100
84
|
|
|
101
85
|
## xython 각 모듈의 간략한 설명
|
|
@@ -309,37 +293,63 @@ selenium을 기반으로 사용하기 쉽도록 만든 것
|
|
|
309
293
|
|
|
310
294
|
### 메소드의 이름규칙
|
|
311
295
|
|
|
312
|
-
| 모듈
|
|
313
|
-
|
|
314
|
-
| add
|
|
315
|
-
| append
|
|
316
|
-
| change
|
|
317
|
-
| check
|
|
318
|
-
| control
|
|
319
|
-
| delete
|
|
320
|
-
| draw
|
|
321
|
-
| fill
|
|
322
|
-
| find
|
|
323
|
-
| get
|
|
324
|
-
| index
|
|
325
|
-
| input
|
|
326
|
-
| input_dic
|
|
327
|
-
| input_l1d
|
|
328
|
-
| input_l2d
|
|
329
|
-
| input_value
|
|
330
|
-
| insert
|
|
331
|
-
| make
|
|
332
|
-
| move
|
|
333
|
-
| new
|
|
334
|
-
| obj
|
|
335
|
-
| paint
|
|
336
|
-
| pick
|
|
337
|
-
| read
|
|
338
|
-
| replace
|
|
339
|
-
| search
|
|
340
|
-
| select
|
|
341
|
-
| set
|
|
342
|
-
| split
|
|
343
|
-
| write
|
|
296
|
+
| 모듈 | 설명 |
|
|
297
|
+
|----------------|-------------------------------------------------|
|
|
298
|
+
| add | 기존에 있는것의 일반적인 끝에 넣는 것 |
|
|
299
|
+
| append | 맨끝에 추가할 때 |
|
|
300
|
+
| change | 입력값을 바꾸는 목적 |
|
|
301
|
+
| check | 확인 |
|
|
302
|
+
| control | 어느 영역안에서 조정을 할 때 |
|
|
303
|
+
| delete | 삭제하기 |
|
|
304
|
+
| draw | 선을 그을 때 사용 |
|
|
305
|
+
| fill | 넣기 |
|
|
306
|
+
| find | 찾기 |
|
|
307
|
+
| get | 입력값이 없는 조건에서의 자료를 갖고올때 , read를 제외한 모든 자료를 갖고올 때 |
|
|
308
|
+
| index | 몇번째의 순서대로 어떤 것을 하는 것 |
|
|
309
|
+
| input | 내부적으로 어떤 값을 넣을 때 |
|
|
310
|
+
| input_dic | 사전형식일 때 |
|
|
311
|
+
| input_l1d, l1d | 1차원 리스트가 입력값일 때 |
|
|
312
|
+
| input_l2d, l2d | 2차원 리스트가 입력값일 때 |
|
|
313
|
+
| input_value | 숫자형의 자료가 입력될때 |
|
|
314
|
+
| insert | 내가 원하는위치에 넣는 것 |
|
|
315
|
+
| make | 만들기 |
|
|
316
|
+
| move | 이동하기 |
|
|
317
|
+
| new | 새로운것을 만드는 개념 |
|
|
318
|
+
| obj | 객체를 뜻함 |
|
|
319
|
+
| paint | 영역에 색칠하는 것 |
|
|
320
|
+
| pick | 여러개중에서 하나를 갖고올 때 |
|
|
321
|
+
| read | 입력값이 있으면서 어떤 자료를 갖고올 때 사용, 보여지는 자료의 값을 갖고올 때 |
|
|
322
|
+
| replace | 바꾸기 |
|
|
323
|
+
| search | 찾기 |
|
|
324
|
+
| select | 어떤 영역을 선택할 때 |
|
|
325
|
+
| set | 입력값이 특별한것없이 자료를 설정하는 것, 설정값을 변경할 때 |
|
|
326
|
+
| split | 분리하기 |
|
|
327
|
+
| write | 눈에 보이는 것 |
|
|
328
|
+
|
|
329
|
+
## 주요 버전에 대한 변경내용 설명
|
|
330
|
+
|
|
331
|
+
### 4.6.3 (2026-09-27)
|
|
332
|
+
> - 전체적으로 함수의 이름을 변경함<br>
|
|
333
|
+
> - xy_re에 추가적인 기능이 가능하도록 기능추가<br>
|
|
334
|
+
> - manul부분만 별도로 하기위해 기본 형태 마련<br>
|
|
335
|
+
|
|
336
|
+
### 4.5.1 (2026-05-28)
|
|
337
|
+
> - _easy_start.py를 새로 만들어서 사용하기 쉽게 각 모듈을 만들도록 하였읍니다<br>
|
|
338
|
+
> - from xython.xy_easy_start import load; xy = load()<br>
|
|
339
|
+
> - 위와같이 하면, 별도 객체를 만들지 않아도 사용가능하게 만듦<br>
|
|
340
|
+
> - 자세한 사항은 각 참고 자료를 보시면 됩니다. 기존과같이 하여도 작동을 합니다<br>
|
|
341
|
+
### 4.4.1 (2026-05-24)
|
|
342
|
+
> - 각 모듈의 이름을 xy를 맨앞으로 넣는다 (xyexcel, xytime 등)<br>
|
|
343
|
+
> - 매번 들어가는 함수의 이름들은 과감히 제거를 함 (예: for_range, _value 등)<br>
|
|
344
|
+
> - 여러가지를 전체적으로 변경함<br>
|
|
344
345
|
|
|
346
|
+
### 4.3.8을 기준으로 각 모듈이름을 변경함 (2026-05-16)
|
|
347
|
+
> - 의존성을 줄이기위하여 일부 패키지를 줄이도록 변경<br>
|
|
348
|
+
> - 자동으로 uploader를 사용해서 적용중<br>
|
|
349
|
+
> - 패키지의 일부는 없애고, web용 모듈을 추가함<br>
|
|
350
|
+
|
|
351
|
+
### 4.0.0을 기준으로 각 모듈이름을 변경함 (2025-03-26)
|
|
352
|
+
> - 쉽게 : **xy_** 접두어로 모든 모듈이름을 변경<br>
|
|
353
|
+
> - 공통 변수모듈 : **xy_xommon**으로 변경<br>
|
|
354
|
+
> - 공통변수이름을 vars => **xvar**로 변경<br>
|
|
345
355
|
|
|
@@ -1,28 +1,13 @@
|
|
|
1
|
-
#
|
|
2
|
-
> - _easy_start.py를 새로 만들어서 사용하기 쉽게 각 모듈을 만들도록 하였읍니다<br>
|
|
3
|
-
> - from xython.xy_easy_start import load; xy = load()<br>
|
|
4
|
-
> - 위와같이 하면, 별도 객체를 만들지 않아도 사용가능하게 만듦<br>
|
|
5
|
-
> - 자세한 사항은 각 참고 자료를 보시면 됩니다. 기존과같이 하여도 작동을 합니다<br>
|
|
6
|
-
# 4.4.1 (2026-05-24)
|
|
7
|
-
> - 각 모듈의 이름을 xy를 맨앞으로 넣는다 (xyexcel, xytime 등)<br>
|
|
8
|
-
> - 매번 들어가는 함수의 이름들은 과감히 제거를 함 (예: for_range, _value 등)<br>
|
|
9
|
-
> - 여러가지를 전체적으로 변경함<br>
|
|
10
|
-
|
|
11
|
-
# 4.3.8을 기준으로 각 모듈이름을 변경함 (2026-05-16)
|
|
12
|
-
> - 의존성을 줄이기위하여 일부 패키지를 줄이도록 변경<br>
|
|
13
|
-
> - 자동으로 uploader를 사용해서 적용중<br>
|
|
14
|
-
> - 패키지의 일부는 없애고, web용 모듈을 추가함<br>
|
|
15
|
-
|
|
16
|
-
# 4.0.0을 기준으로 각 모듈이름을 변경함 (2025-03-26)
|
|
17
|
-
> - 쉽게 : **xy_** 접두어로 모든 모듈이름을 변경<br>
|
|
18
|
-
> - 공통 변수모듈 : **xy_xommon**으로 변경<br>
|
|
19
|
-
> - 공통변수이름을 vars => **xvar**로 변경<br>
|
|
20
|
-
|
|
21
|
-
# About xython Package
|
|
1
|
+
# xython Package에 대하여
|
|
22
2
|
|
|
23
3
|
>**Functional Programming for Excel, Hwp, Word, Outlook, Color, Etc by win32com<br>
|
|
24
4
|
It can handle for Excel, Hwp, Word, Outlook, Color, Etc by xython**
|
|
25
5
|
|
|
6
|
+
업무자동화를 위해 Excel, Word, Outlook등을 사용하기 편하게 하기 위해 만든것으로
|
|
7
|
+
각 함수가 독립적인 형태의 결과물이 나오는 함수형으로 만드는 프로그램입니다
|
|
8
|
+
- Python을 사용합니다
|
|
9
|
+
- pywin32를 사용합니다
|
|
10
|
+
- 초보자를 위한 GUI로 사용하는 것과 코딩이 가능한 2가지 방법이 있읍니다
|
|
26
11
|
|
|
27
12
|
## xython 패키지는 함수형 프로그램 이다
|
|
28
13
|
|
|
@@ -51,11 +36,10 @@ It can handle for Excel, Hwp, Word, Outlook, Color, Etc by xython**
|
|
|
51
36
|
|
|
52
37
|
### official website
|
|
53
38
|
> oficial document : **https://sjpkorea.github.io/xython.github.io/**<br>
|
|
54
|
-
> oficial
|
|
39
|
+
> oficial pypi : **https://pypi.org/project/xython/ (Korean base)**<br>
|
|
55
40
|
|
|
56
41
|
|
|
57
42
|
## components about xython package (패키지의 구성)
|
|
58
|
-
**easy wrapper** for belows;
|
|
59
43
|
|
|
60
44
|
| 번호 | xython package | 설명 |
|
|
61
45
|
|----|----------------|---------------------------------------------------|
|
|
@@ -74,7 +58,7 @@ It can handle for Excel, Hwp, Word, Outlook, Color, Etc by xython**
|
|
|
74
58
|
| 13 | xy_util | utilities (**for common use**) |
|
|
75
59
|
| 14 | xy_auto | for Keyboard & Mouse control (**for common use**) |
|
|
76
60
|
| 15 | xy_edge | for edge |
|
|
77
|
-
| 16 | xy_common | 기본 자료
|
|
61
|
+
| 16 | xy_common | xython패키지에 공통으로 사용되는 기본 자료 |
|
|
78
62
|
|
|
79
63
|
|
|
80
64
|
## xython 각 모듈의 간략한 설명
|
|
@@ -288,37 +272,63 @@ selenium을 기반으로 사용하기 쉽도록 만든 것
|
|
|
288
272
|
|
|
289
273
|
### 메소드의 이름규칙
|
|
290
274
|
|
|
291
|
-
| 모듈
|
|
292
|
-
|
|
293
|
-
| add
|
|
294
|
-
| append
|
|
295
|
-
| change
|
|
296
|
-
| check
|
|
297
|
-
| control
|
|
298
|
-
| delete
|
|
299
|
-
| draw
|
|
300
|
-
| fill
|
|
301
|
-
| find
|
|
302
|
-
| get
|
|
303
|
-
| index
|
|
304
|
-
| input
|
|
305
|
-
| input_dic
|
|
306
|
-
| input_l1d
|
|
307
|
-
| input_l2d
|
|
308
|
-
| input_value
|
|
309
|
-
| insert
|
|
310
|
-
| make
|
|
311
|
-
| move
|
|
312
|
-
| new
|
|
313
|
-
| obj
|
|
314
|
-
| paint
|
|
315
|
-
| pick
|
|
316
|
-
| read
|
|
317
|
-
| replace
|
|
318
|
-
| search
|
|
319
|
-
| select
|
|
320
|
-
| set
|
|
321
|
-
| split
|
|
322
|
-
| write
|
|
275
|
+
| 모듈 | 설명 |
|
|
276
|
+
|----------------|-------------------------------------------------|
|
|
277
|
+
| add | 기존에 있는것의 일반적인 끝에 넣는 것 |
|
|
278
|
+
| append | 맨끝에 추가할 때 |
|
|
279
|
+
| change | 입력값을 바꾸는 목적 |
|
|
280
|
+
| check | 확인 |
|
|
281
|
+
| control | 어느 영역안에서 조정을 할 때 |
|
|
282
|
+
| delete | 삭제하기 |
|
|
283
|
+
| draw | 선을 그을 때 사용 |
|
|
284
|
+
| fill | 넣기 |
|
|
285
|
+
| find | 찾기 |
|
|
286
|
+
| get | 입력값이 없는 조건에서의 자료를 갖고올때 , read를 제외한 모든 자료를 갖고올 때 |
|
|
287
|
+
| index | 몇번째의 순서대로 어떤 것을 하는 것 |
|
|
288
|
+
| input | 내부적으로 어떤 값을 넣을 때 |
|
|
289
|
+
| input_dic | 사전형식일 때 |
|
|
290
|
+
| input_l1d, l1d | 1차원 리스트가 입력값일 때 |
|
|
291
|
+
| input_l2d, l2d | 2차원 리스트가 입력값일 때 |
|
|
292
|
+
| input_value | 숫자형의 자료가 입력될때 |
|
|
293
|
+
| insert | 내가 원하는위치에 넣는 것 |
|
|
294
|
+
| make | 만들기 |
|
|
295
|
+
| move | 이동하기 |
|
|
296
|
+
| new | 새로운것을 만드는 개념 |
|
|
297
|
+
| obj | 객체를 뜻함 |
|
|
298
|
+
| paint | 영역에 색칠하는 것 |
|
|
299
|
+
| pick | 여러개중에서 하나를 갖고올 때 |
|
|
300
|
+
| read | 입력값이 있으면서 어떤 자료를 갖고올 때 사용, 보여지는 자료의 값을 갖고올 때 |
|
|
301
|
+
| replace | 바꾸기 |
|
|
302
|
+
| search | 찾기 |
|
|
303
|
+
| select | 어떤 영역을 선택할 때 |
|
|
304
|
+
| set | 입력값이 특별한것없이 자료를 설정하는 것, 설정값을 변경할 때 |
|
|
305
|
+
| split | 분리하기 |
|
|
306
|
+
| write | 눈에 보이는 것 |
|
|
307
|
+
|
|
308
|
+
## 주요 버전에 대한 변경내용 설명
|
|
309
|
+
|
|
310
|
+
### 4.6.3 (2026-09-27)
|
|
311
|
+
> - 전체적으로 함수의 이름을 변경함<br>
|
|
312
|
+
> - xy_re에 추가적인 기능이 가능하도록 기능추가<br>
|
|
313
|
+
> - manul부분만 별도로 하기위해 기본 형태 마련<br>
|
|
314
|
+
|
|
315
|
+
### 4.5.1 (2026-05-28)
|
|
316
|
+
> - _easy_start.py를 새로 만들어서 사용하기 쉽게 각 모듈을 만들도록 하였읍니다<br>
|
|
317
|
+
> - from xython.xy_easy_start import load; xy = load()<br>
|
|
318
|
+
> - 위와같이 하면, 별도 객체를 만들지 않아도 사용가능하게 만듦<br>
|
|
319
|
+
> - 자세한 사항은 각 참고 자료를 보시면 됩니다. 기존과같이 하여도 작동을 합니다<br>
|
|
320
|
+
### 4.4.1 (2026-05-24)
|
|
321
|
+
> - 각 모듈의 이름을 xy를 맨앞으로 넣는다 (xyexcel, xytime 등)<br>
|
|
322
|
+
> - 매번 들어가는 함수의 이름들은 과감히 제거를 함 (예: for_range, _value 등)<br>
|
|
323
|
+
> - 여러가지를 전체적으로 변경함<br>
|
|
323
324
|
|
|
325
|
+
### 4.3.8을 기준으로 각 모듈이름을 변경함 (2026-05-16)
|
|
326
|
+
> - 의존성을 줄이기위하여 일부 패키지를 줄이도록 변경<br>
|
|
327
|
+
> - 자동으로 uploader를 사용해서 적용중<br>
|
|
328
|
+
> - 패키지의 일부는 없애고, web용 모듈을 추가함<br>
|
|
329
|
+
|
|
330
|
+
### 4.0.0을 기준으로 각 모듈이름을 변경함 (2025-03-26)
|
|
331
|
+
> - 쉽게 : **xy_** 접두어로 모든 모듈이름을 변경<br>
|
|
332
|
+
> - 공통 변수모듈 : **xy_xommon**으로 변경<br>
|
|
333
|
+
> - 공통변수이름을 vars => **xvar**로 변경<br>
|
|
324
334
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# __init__.py
|
|
2
|
-
# Copyright (C)
|
|
2
|
+
# Copyright (C) 2025 (sjpkorea@naver.com) and contributors
|
|
3
|
+
|
|
3
4
|
|
|
4
|
-
#https://blog.naver.com/xython
|
|
5
5
|
import inspect
|
|
6
6
|
import os
|
|
7
7
|
import sys
|
|
8
8
|
|
|
9
|
-
__version__ = '4.
|
|
9
|
+
__version__ = '4.3.5' #1
|
|
10
10
|
real_path = os.path.dirname(os.path.abspath(__file__)).replace("\\","/") #2
|
|
11
11
|
sys.path.append(real_path)
|
|
12
12
|
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
alias_installer.py (개선판 - 각 모듈의 호출부는 그대로 두면 됨)
|
|
4
|
+
|
|
5
|
+
방식: 인스턴스마다 alias 를 setattr 하지 않고, __getattr__ 에서 '처음 쓸 때' 만든다.
|
|
6
|
+
- 인스턴스 생성이 가볍다 (280개 wrapper 를 매번 만들지 않음)
|
|
7
|
+
- alias -> 원본 역방향 표를 (모듈, 언어) 단위로 1번만 만들고 캐시
|
|
8
|
+
- 만든 wrapper 는 클래스 단위로 캐시하고, 인스턴스에는 바인딩만 한다
|
|
9
|
+
(인스턴스 __dict__ 가 깨끗해서 pickle / copy.deepcopy 도 안전)
|
|
10
|
+
- functools.wraps 로 원본 시그니처 유지 -> help(), IDE 에서 인자 목록이 보인다
|
|
11
|
+
- make_dir_fallback 을 쓰면 dir()/탭 자동완성에도 alias 가 보인다
|
|
12
|
+
"""
|
|
13
|
+
import difflib, types
|
|
14
|
+
import functools
|
|
15
|
+
from functools import lru_cache
|
|
16
|
+
|
|
17
|
+
from .locales_loader import load_locales_for_module
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _normalize_langs(lang):
|
|
21
|
+
if lang is None:
|
|
22
|
+
return ()
|
|
23
|
+
if isinstance(lang, str):
|
|
24
|
+
return (lang,)
|
|
25
|
+
return tuple(lang)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def build_combined_doc(orig_name, locales, active_langs):
|
|
29
|
+
"""여러 언어의 doc 을 순서대로 이어 붙인 docstring 생성."""
|
|
30
|
+
lines = []
|
|
31
|
+
for lang in active_langs:
|
|
32
|
+
doc = locales.get(lang, {}).get("docs", {}).get(orig_name)
|
|
33
|
+
if doc:
|
|
34
|
+
lines.append(f"[{lang}] {doc}")
|
|
35
|
+
return "\n".join(lines) if lines else None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@lru_cache(maxsize=None)
|
|
39
|
+
def _alias_table(module_name, langs):
|
|
40
|
+
"""(alias -> 원본이름) 역방향 표와 locales 를 반환. langs 는 tuple."""
|
|
41
|
+
locales = load_locales_for_module(module_name, langs)
|
|
42
|
+
reverse = {}
|
|
43
|
+
for lg in langs:
|
|
44
|
+
for orig, alias in locales[lg]["aliases"].items():
|
|
45
|
+
if alias and alias != orig: # 빈 문자열(미번역)은 무시
|
|
46
|
+
reverse.setdefault(alias, orig) # 충돌 시 앞쪽 언어가 우선
|
|
47
|
+
return reverse, locales
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@lru_cache(maxsize=None)
|
|
51
|
+
def _make_alias_function(owner_cls, module_name, orig_name, alias_name, langs):
|
|
52
|
+
orig_func = getattr(owner_cls, orig_name, None)
|
|
53
|
+
if orig_func is None or not callable(orig_func):
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
_, locales = _alias_table(module_name, langs)
|
|
57
|
+
doc = build_combined_doc(orig_name, locales, langs) or orig_func.__doc__
|
|
58
|
+
|
|
59
|
+
@functools.wraps(orig_func)
|
|
60
|
+
def wrapper(self, *args, **kwargs):
|
|
61
|
+
return orig_func(self, *args, **kwargs)
|
|
62
|
+
|
|
63
|
+
wrapper.__name__ = alias_name
|
|
64
|
+
wrapper.__qualname__ = f"{owner_cls.__name__}.{alias_name}"
|
|
65
|
+
wrapper.__doc__ = doc
|
|
66
|
+
return wrapper
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# alias_installer.py
|
|
70
|
+
def install_instance_aliases(instance, module_name, active_langs):
|
|
71
|
+
langs = _normalize_langs(active_langs)
|
|
72
|
+
reverse, _ = _alias_table(module_name, langs) # JSON 캐시 데움
|
|
73
|
+
owner_cls = type(instance)
|
|
74
|
+
for alias_name in reverse:
|
|
75
|
+
# 클래스에 이미 있으면(@alias 로 등록된 것) 건너뜀 → 충돌 방지
|
|
76
|
+
if hasattr(owner_cls, alias_name):
|
|
77
|
+
continue
|
|
78
|
+
func = _make_alias_function(owner_cls, module_name,
|
|
79
|
+
reverse[alias_name], alias_name, langs)
|
|
80
|
+
if func is not None:
|
|
81
|
+
# 인스턴스에 바인딩 (인스턴스마다 wrapper 1개씩 생김 — 비용 있음)
|
|
82
|
+
setattr(instance, alias_name, types.MethodType(func, instance))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def make_getattr_fallback(module_name):
|
|
86
|
+
"""클래스에 `__getattr__ = make_getattr_fallback("xy_time")` 로 붙인다."""
|
|
87
|
+
def _getattr(self, name):
|
|
88
|
+
if name.startswith("__") and name.endswith("__"):
|
|
89
|
+
raise AttributeError(name)
|
|
90
|
+
|
|
91
|
+
langs = _normalize_langs(self.__dict__.get("lang"))
|
|
92
|
+
msg = f"'{type(self).__name__}' object has no attribute '{name}'"
|
|
93
|
+
|
|
94
|
+
if langs:
|
|
95
|
+
reverse, _ = _alias_table(module_name, langs)
|
|
96
|
+
orig = reverse.get(name)
|
|
97
|
+
if orig is not None:
|
|
98
|
+
func = _make_alias_function(type(self), module_name, orig, name, langs)
|
|
99
|
+
if func is not None:
|
|
100
|
+
return func.__get__(self, type(self))
|
|
101
|
+
close = difflib.get_close_matches(name, reverse, n=1)
|
|
102
|
+
if close:
|
|
103
|
+
msg += f". Did you mean '{close[0]}'?"
|
|
104
|
+
|
|
105
|
+
raise AttributeError(msg)
|
|
106
|
+
|
|
107
|
+
return _getattr
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def make_dir_fallback(module_name):
|
|
111
|
+
"""(선택) 클래스에 `__dir__ = make_dir_fallback("xy_time")` 를 붙이면 자동완성에 alias 가 보인다."""
|
|
112
|
+
def _dir(self):
|
|
113
|
+
names = set(object.__dir__(self))
|
|
114
|
+
langs = _normalize_langs(self.__dict__.get("lang"))
|
|
115
|
+
if langs:
|
|
116
|
+
names.update(_alias_table(module_name, langs)[0])
|
|
117
|
+
return sorted(names)
|
|
118
|
+
|
|
119
|
+
return _dir
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
locales_loader.py
|
|
4
|
+
|
|
5
|
+
locales/{lang}/{module_name}.json 을 읽어서 dict 로 반환.
|
|
6
|
+
- aliases : {원본함수명: 언어별이름}
|
|
7
|
+
- docs : {원본함수명: 언어별설명}
|
|
8
|
+
"""
|
|
9
|
+
import json
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
_LOCALES_DIR = os.path.join(os.path.dirname(__file__), "locales")
|
|
13
|
+
_cache = {}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def load_locale(module_name, lang):
|
|
17
|
+
key = (module_name, lang)
|
|
18
|
+
if key in _cache:
|
|
19
|
+
return _cache[key]
|
|
20
|
+
|
|
21
|
+
path = os.path.join(_LOCALES_DIR, lang, f"{module_name}.json")
|
|
22
|
+
if not os.path.exists(path):
|
|
23
|
+
_cache[key] = {"aliases": {}, "docs": {}}
|
|
24
|
+
return _cache[key]
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
# utf-8-sig: 윈도우 메모장/일부 에디터가 붙이는 BOM 이 있어도 읽힌다
|
|
28
|
+
with open(path, "r", encoding="utf-8-sig") as f:
|
|
29
|
+
data = json.load(f)
|
|
30
|
+
except json.JSONDecodeError as e:
|
|
31
|
+
raise ValueError(f"locale 파일 JSON 오류: {path} ({e})") from e
|
|
32
|
+
|
|
33
|
+
result = {
|
|
34
|
+
"aliases": data.get("aliases", {}),
|
|
35
|
+
"docs": data.get("docs", {}),
|
|
36
|
+
}
|
|
37
|
+
_cache[key] = result
|
|
38
|
+
return result
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def load_locales_for_module(module_name, langs):
|
|
42
|
+
return {lang: load_locale(module_name, lang) for lang in langs}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def clear_cache():
|
|
46
|
+
"""JSON 을 고친 뒤 재시작 없이 다시 읽고 싶을 때 (GUI/테스트용)."""
|
|
47
|
+
_cache.clear()
|
|
48
|
+
try:
|
|
49
|
+
from .alias_installer import _alias_table, _make_alias_function
|
|
50
|
+
_alias_table.cache_clear()
|
|
51
|
+
_make_alias_function.cache_clear()
|
|
52
|
+
except ImportError:
|
|
53
|
+
pass
|