xython 4.3.9__tar.gz → 4.3.10__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.
Files changed (29) hide show
  1. {xython-4.3.9/src/xython.egg-info → xython-4.3.10}/PKG-INFO +1 -1
  2. {xython-4.3.9 → xython-4.3.10}/pyproject.toml +1 -1
  3. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_color.py +174 -10
  4. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_edge.py +35 -0
  5. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_excel.py +403 -128
  6. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_outlook.py +569 -87
  7. xython-4.3.10/src/xython/xy_re.py +1041 -0
  8. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_time.py +181 -25
  9. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_util.py +255 -59
  10. {xython-4.3.9 → xython-4.3.10/src/xython.egg-info}/PKG-INFO +1 -1
  11. xython-4.3.9/src/xython/xy_re.py +0 -1097
  12. {xython-4.3.9 → xython-4.3.10}/MANIFEST.in +0 -0
  13. {xython-4.3.9 → xython-4.3.10}/README.md +0 -0
  14. {xython-4.3.9 → xython-4.3.10}/requirements.txt +0 -0
  15. {xython-4.3.9 → xython-4.3.10}/setup.cfg +0 -0
  16. {xython-4.3.9 → xython-4.3.10}/src/xython/__init__.py +0 -0
  17. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_auto.py +0 -0
  18. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_chrome.py +0 -0
  19. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_common.py +0 -0
  20. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_db.py +0 -0
  21. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_excel_event.py +0 -0
  22. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_hwp.py +0 -0
  23. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_list.py +0 -0
  24. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_map.py +0 -0
  25. {xython-4.3.9 → xython-4.3.10}/src/xython/xy_word.py +0 -0
  26. {xython-4.3.9 → xython-4.3.10}/src/xython.egg-info/SOURCES.txt +0 -0
  27. {xython-4.3.9 → xython-4.3.10}/src/xython.egg-info/dependency_links.txt +0 -0
  28. {xython-4.3.9 → xython-4.3.10}/src/xython.egg-info/requires.txt +0 -0
  29. {xython-4.3.9 → xython-4.3.10}/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.9
3
+ Version: 4.3.10
4
4
  Summary: xython package
5
5
  Author-email: "SJ.Park" <sjpkorea@naver.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "xython"
7
- version = "4.3.9"
7
+ version = "4.3.10"
8
8
  description = "xython package"
9
9
  readme = {file = "README.md", content-type = "text/markdown"}
10
10
  requires-python = ">=3.8"
@@ -1210,7 +1210,7 @@ class xy_color:
1210
1210
  return result
1211
1211
 
1212
1212
  def rgb_to_hex(self, input_rgb, option="#"):
1213
- return change_rgb_to_hex(input_rgb, option)
1213
+ return self.change_rgb_to_hex(input_rgb, option)
1214
1214
 
1215
1215
  def change_rgb_to_hex(self, input_rgb, option="#"):
1216
1216
  """
@@ -1406,15 +1406,8 @@ class xy_color:
1406
1406
  return result
1407
1407
 
1408
1408
  def change_xcolor_to_hex(self, input_xcolor):
1409
- """
1410
- xcolor값을 16진수인 hex로 변경하는 것
1411
- xcolor형식 : 12, "red", "red45", "red++"
1412
-
1413
- :param input_xcolor: solor형태의 색깔입력, (12, "red", "red45", "red++")
1414
- :return:
1415
- """
1416
- my_rgb_color = self.change_xcolor_to_rgb(input_xcolor)
1417
- result = self.xcolor_alpha_to_rgba(my_rgb_color)
1409
+ rgb = self.change_xcolor_to_rgb(input_xcolor)
1410
+ result = self.change_rgb_to_hex(rgb)
1418
1411
  return result
1419
1412
 
1420
1413
  def change_xcolor_to_hsl(self, input_xcolor):
@@ -2504,3 +2497,174 @@ class xy_color:
2504
2497
  """
2505
2498
  return self.xcolor_to_rgbint(input_xcolor)
2506
2499
 
2500
+ def get_text_color_for_background(self, bg_rgb):
2501
+ """
2502
+ 배경색이 주어지면 텍스트를 흰색/검정 중 어느 쪽으로 할지 자동 결정
2503
+ WCAG 명도 기준 사용
2504
+ """
2505
+ r, g, b = [x / 255 for x in bg_rgb]
2506
+ luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b
2507
+ return [255, 255, 255] if luminance < 0.5 else [0, 0, 0]
2508
+
2509
+ def get_contrast_ratio(self, rgb1, rgb2):
2510
+ """
2511
+ 두 색의 WCAG 명암비 계산 (1~21)
2512
+ 4.5 이상이면 텍스트로 사용 가능 (AA 기준)
2513
+ """
2514
+ def lum(rgb):
2515
+ c = [x / 255 for x in rgb]
2516
+ c = [x / 12.92 if x <= 0.04045 else ((x + 0.055) / 1.055) ** 2.4 for x in c]
2517
+ return 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2]
2518
+ l1, l2 = lum(rgb1), lum(rgb2)
2519
+ lighter, darker = max(l1, l2), min(l1, l2)
2520
+ return round((lighter + 0.05) / (darker + 0.05), 2)
2521
+
2522
+ def hex_to_rgb(self, hex_color):
2523
+ """
2524
+ "#ff5733" 또는 "ff5733" → [255, 87, 51]
2525
+ """
2526
+ hex_color = hex_color.lstrip("#")
2527
+ return [int(hex_color[i:i+2], 16) for i in (0, 2, 4)]
2528
+
2529
+ def hex_to_hsl(self, hex_color):
2530
+ """
2531
+ hex → hsl 직접 변환
2532
+ """
2533
+ return self.rgb_to_hsl(self.hex_to_rgb(hex_color))
2534
+
2535
+ def rgb_to_cmyk(self, input_rgb):
2536
+ """
2537
+ RGB → CMYK 변환 (인쇄용)
2538
+ 반환: [c, m, y, k] (0~100 정수)
2539
+ """
2540
+ r, g, b = [x / 255 for x in input_rgb]
2541
+ k = 1 - max(r, g, b)
2542
+ if k == 1:
2543
+ return [0, 0, 0, 100]
2544
+ c = (1 - r - k) / (1 - k)
2545
+ m = (1 - g - k) / (1 - k)
2546
+ y = (1 - b - k) / (1 - k)
2547
+ return [round(c*100), round(m*100), round(y*100), round(k*100)]
2548
+
2549
+ def cmyk_to_rgb(self, c, m, y, k):
2550
+ """
2551
+ CMYK → RGB 변환
2552
+ 입력: 0~100 정수
2553
+ """
2554
+ c, m, y, k = c/100, m/100, y/100, k/100
2555
+ r = int(255 * (1 - c) * (1 - k))
2556
+ g = int(255 * (1 - m) * (1 - k))
2557
+ b = int(255 * (1 - y) * (1 - k))
2558
+ return [r, g, b]
2559
+
2560
+ def rgb_to_hsv(self, input_rgb):
2561
+ """
2562
+ RGB → HSV 변환 (포토샵 등에서 사용하는 방식)
2563
+ 반환: [h(0~360), s(0~100), v(0~100)]
2564
+ """
2565
+ r, g, b = [x / 255 for x in input_rgb]
2566
+ mx, mn = max(r, g, b), min(r, g, b)
2567
+ v = mx
2568
+ s = 0 if mx == 0 else (mx - mn) / mx
2569
+ if mx == mn:
2570
+ h = 0
2571
+ elif mx == r:
2572
+ h = (60 * ((g - b) / (mx - mn))) % 360
2573
+ elif mx == g:
2574
+ h = 60 * ((b - r) / (mx - mn)) + 120
2575
+ else:
2576
+ h = 60 * ((r - g) / (mx - mn)) + 240
2577
+ return [round(h), round(s * 100), round(v * 100)]
2578
+
2579
+ def get_analogous_colors(self, input_xcolor, angle=30, count=2):
2580
+ """
2581
+ 유사색 생성 (색상환에서 ±angle도 이내의 색)
2582
+ count=2이면 양쪽 1개씩, count=4이면 양쪽 2개씩
2583
+ 반환: [[rgb...], ...]
2584
+ """
2585
+ hsl = self._change_xcolor_to_hsl(input_xcolor)
2586
+ result = []
2587
+ for i in range(1, count // 2 + 1):
2588
+ for sign in [-1, 1]:
2589
+ new_h = (hsl[0] + sign * angle * i) % 360
2590
+ result.append(self.hsl_to_rgb([new_h, hsl[1], hsl[2]]))
2591
+ return result
2592
+
2593
+ def get_triadic_colors(self, input_xcolor):
2594
+ """
2595
+ 3색 배색 (120도 간격)
2596
+ """
2597
+ hsl = self._change_xcolor_to_hsl(input_xcolor)
2598
+ return [self.hsl_to_rgb([(hsl[0] + i * 120) % 360, hsl[1], hsl[2]]) for i in range(3)]
2599
+
2600
+ def get_split_complementary_colors(self, input_xcolor, angle=150):
2601
+ """
2602
+ 분리 보색 (보색에서 ±30도)
2603
+ """
2604
+ hsl = self._change_xcolor_to_hsl(input_xcolor)
2605
+ h = hsl[0]
2606
+ return [
2607
+ self.hsl_to_rgb([h, hsl[1], hsl[2]]),
2608
+ self.hsl_to_rgb([(h + angle) % 360, hsl[1], hsl[2]]),
2609
+ self.hsl_to_rgb([(h - angle) % 360, hsl[1], hsl[2]]),
2610
+ ]
2611
+
2612
+ def get_monochromatic_colors(self, input_xcolor, count=5):
2613
+ """
2614
+ 단색 배색: 같은 색상(H)에서 명도만 달리한 count개 색
2615
+ """
2616
+ hsl = self._change_xcolor_to_hsl(input_xcolor)
2617
+ step = 100 // (count + 1)
2618
+ return [self.hsl_to_rgb([hsl[0], hsl[1], step * (i + 1)]) for i in range(count)]
2619
+
2620
+ def is_dark_color(self, input_rgb):
2621
+ """
2622
+ 어두운 색인지 여부 (True/False)
2623
+ luminance 0.5 기준
2624
+ """
2625
+ r, g, b = [x / 255 for x in input_rgb]
2626
+ luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b
2627
+ return luminance < 0.5
2628
+
2629
+ def is_warm_color(self, input_rgb):
2630
+ """
2631
+ 따뜻한 색(빨강~노랑 계열)인지 여부
2632
+ HSL 기준 H가 0~60 또는 300~360이면 따뜻한 색
2633
+ """
2634
+ hsl = self.rgb_to_hsl(input_rgb)
2635
+ h = hsl[0]
2636
+ return h <= 60 or h >= 300
2637
+
2638
+ def get_color_temperature(self, input_rgb):
2639
+ """
2640
+ 색 온도 분류 반환: "warm" / "cool" / "neutral"
2641
+ """
2642
+ hsl = self.rgb_to_hsl(input_rgb)
2643
+ h = hsl[0]
2644
+ if h <= 60 or h >= 300:
2645
+ return "warm"
2646
+ elif 150 <= h <= 270:
2647
+ return "cool"
2648
+ else:
2649
+ return "neutral"
2650
+
2651
+ def get_color_info(self, input_rgb):
2652
+ """
2653
+ RGB 색상의 종합 정보를 딕셔너리로 반환
2654
+ {"rgb", "hsl", "hsv", "hex", "cmyk", "is_dark", "temperature"}
2655
+ """
2656
+ return {
2657
+ "rgb": input_rgb,
2658
+ "hsl": self.rgb_to_hsl(input_rgb),
2659
+ "hsv": self.rgb_to_hsv(input_rgb),
2660
+ "hex": self.change_rgb_to_hex(input_rgb),
2661
+ "cmyk": self.rgb_to_cmyk(input_rgb),
2662
+ "is_dark": self.is_dark_color(input_rgb),
2663
+ "temperature": self.get_color_temperature(input_rgb),
2664
+ }
2665
+
2666
+
2667
+
2668
+
2669
+
2670
+
@@ -2955,3 +2955,38 @@ class xy_edge:
2955
2955
  else:
2956
2956
  print("❌ PDF 데이터를 생성하지 못했습니다.")
2957
2957
 
2958
+
2959
+ def write_by_xpath(self, xpath: str, value: str) -> bool:
2960
+ try:
2961
+ element = self.page.ele(f'xpath:{xpath}')
2962
+
2963
+ if element is None:
2964
+ print(f"[ERROR] 요소를 찾을 수 없습니다: {xpath}")
2965
+ return False
2966
+
2967
+ element.clear() # 기존 내용 초기화
2968
+ element.input(value) # 값 입력
2969
+
2970
+ print(f"[OK] 입력 완료")
2971
+ return True
2972
+
2973
+ except Exception as e:
2974
+ print(f"[ERROR] 입력 실패 - {e}")
2975
+ return False
2976
+
2977
+ def write_by_id(self, element_id: str, value: str) -> bool:
2978
+ try:
2979
+ element = self.page.ele(f'#{element_id}')
2980
+ if element is None:
2981
+ print(f"[ERROR] 요소를 찾을 수 없습니다: #{element_id}")
2982
+ return False
2983
+
2984
+ element.clear()
2985
+ element.input(value)
2986
+
2987
+ print(f"[OK] 입력 완료")
2988
+ return True
2989
+
2990
+ except Exception as e:
2991
+ print(f"[ERROR] 입력 실패 - {e}")
2992
+ return False