Kekik 1.6.0__py3-none-any.whl → 1.6.2__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.

Potentially problematic release.


This version of Kekik might be problematic. Click here for more details.

@@ -11,7 +11,12 @@ class HexCodec:
11
11
  @staticmethod
12
12
  def decode(escaped_hex: str) -> str:
13
13
  """Kaçış dizileri içeren bir hex stringini UTF-8 formatındaki stringe dönüştürür."""
14
- hex_string = escaped_hex.replace("\\x", "").replace("\\X", "")
14
+ escaped_hex = escaped_hex.strip().replace("\\X", "\\x")
15
+
16
+ if isinstance(escaped_hex, str) and not escaped_hex.startswith(r"\x"):
17
+ return escaped_hex.encode("unicode_escape").decode("utf-8")
18
+
19
+ hex_string = escaped_hex.replace("\\x", "")
15
20
  byte_data = bytes.fromhex(hex_string)
16
21
 
17
22
  return byte_data.decode("utf-8")
Kekik/cache.py ADDED
@@ -0,0 +1,164 @@
1
+ # ! https://github.com/Fatal1ty/aiocached
2
+
3
+ import asyncio
4
+ from functools import wraps
5
+ from time import time
6
+
7
+ UNLIMITED = None
8
+
9
+ class Cache:
10
+ """
11
+ Basit in-memory cache yapısı.
12
+ TTL (time-to-live) süresi dolan veriler otomatik olarak temizlenir.
13
+ """
14
+ def __init__(self, ttl=UNLIMITED):
15
+ self._data = {}
16
+ self._ttl = ttl
17
+ self._times = {}
18
+
19
+ def _is_expired(self, key):
20
+ """Belirtilen key'in süresi dolduysa True döner."""
21
+ if self._ttl is UNLIMITED:
22
+ return False
23
+
24
+ timestamp = self._times.get(key)
25
+
26
+ return timestamp is not None and (time() - timestamp > self._ttl)
27
+
28
+ def remove_if_expired(self, key):
29
+ """
30
+ Eğer key'in cache süresi dolmuşsa, ilgili entry'yi temizler.
31
+ """
32
+ if self._is_expired(key):
33
+ self._data.pop(key, None)
34
+ self._times.pop(key, None)
35
+
36
+ def __getitem__(self, key):
37
+ self.remove_if_expired(key)
38
+ return self._data[key]
39
+
40
+ def __setitem__(self, key, value):
41
+ self._data[key] = value
42
+ if self._ttl is not UNLIMITED:
43
+ self._times[key] = time()
44
+
45
+
46
+ class AsyncCache(Cache):
47
+ """
48
+ Asenkron işlemleri destekleyen cache yapısı.
49
+ Aynı key için gelen eşzamanlı çağrılar, futures kullanılarak tek sonuç üzerinden paylaşılır.
50
+ """
51
+ def __init__(self, ttl=UNLIMITED):
52
+ super().__init__(ttl)
53
+ self.futures = {}
54
+
55
+ async def get(self, key):
56
+ """
57
+ Belirtilen key için cache'de saklanan değeri asenkron olarak döndürür.
58
+ Eğer key bulunamazsa, ilgili future üzerinden beklemeyi sağlar.
59
+ """
60
+ self.remove_if_expired(key)
61
+
62
+ try:
63
+ return self._data[key]
64
+ except KeyError as e:
65
+ future = self.futures.get(key)
66
+ if future:
67
+ await future
68
+ return future.result()
69
+
70
+ raise e
71
+
72
+ def remove_if_expired(self, key):
73
+ """
74
+ Belirtilen key'in süresi dolduysa, cache ve futures içerisinden temizler.
75
+ """
76
+ if self._ttl is not UNLIMITED and self._is_expired(key):
77
+ self._data.pop(key, None)
78
+ self._times.pop(key, None)
79
+ self.futures.pop(key, None)
80
+
81
+
82
+ def _sync_maybe_cache(func, key, result, unless):
83
+ """Senkron sonuç için cache kaydını oluşturur (unless koşuluna bakarak)."""
84
+ if unless is None or not unless(result):
85
+ func.__cache[key] = result
86
+
87
+
88
+ async def _async_compute_and_cache(func, key, unless, *args, **kwargs):
89
+ """
90
+ Asenkron fonksiyon sonucu hesaplandıktan sonra, sonucu cache’e ekler.
91
+ Eğer `unless` koşulu sağlanıyorsa cache kaydı atlanır.
92
+ """
93
+ cache = func.__cache
94
+ future = asyncio.Future()
95
+ cache.futures[key] = future
96
+
97
+ try:
98
+ result = await func(*args, **kwargs)
99
+ except Exception as exc:
100
+ cache.futures.pop(key, None)
101
+ future.cancel()
102
+ raise exc
103
+
104
+ future.set_result(result)
105
+
106
+ if unless is None or not unless(result):
107
+ cache[key] = result
108
+ else:
109
+ cache.futures.pop(key, None)
110
+
111
+ return result
112
+
113
+ def make_cache_key(args, kwargs):
114
+ """Fonksiyon argümanlarından cache için kullanılacak key’i oluşturur."""
115
+ return (args, tuple(sorted(kwargs.items())))
116
+
117
+
118
+ def kekik_cache(ttl=UNLIMITED, unless=None):
119
+ """
120
+ Bir fonksiyon veya coroutine'in sonucunu cache'ler.
121
+
122
+ :param ttl: Cache’in geçerlilik süresi (saniye). UNLIMITED ise süresizdir.
123
+ :param unless: Fonksiyonun sonucunu argüman olarak alan bir callable.
124
+ Eğer True dönerse, sonuç cache'e alınmaz.
125
+
126
+ Örnek kullanım:
127
+
128
+ @kekik_cache(ttl=15, unless=lambda res: res is None)
129
+ async def my_func(param):
130
+ ...
131
+ """
132
+ # Parametresiz kullanıldığında
133
+ if callable(ttl):
134
+ return kekik_cache(UNLIMITED, unless=unless)(ttl)
135
+
136
+ def decorator(func):
137
+ func.__cache = AsyncCache(ttl)
138
+
139
+ if asyncio.iscoroutinefunction(func):
140
+ @wraps(func)
141
+ async def async_wrapper(*args, **kwargs):
142
+ key = make_cache_key(args, kwargs)
143
+
144
+ try:
145
+ return await func.__cache.get(key)
146
+ except KeyError:
147
+ return await _async_compute_and_cache(func, key, unless, *args, **kwargs)
148
+
149
+ return async_wrapper
150
+ else:
151
+ @wraps(func)
152
+ def sync_wrapper(*args, **kwargs):
153
+ key = make_cache_key(args, kwargs)
154
+
155
+ try:
156
+ return func.__cache[key]
157
+ except KeyError:
158
+ result = func(*args, **kwargs)
159
+ _sync_maybe_cache(func, key, result, unless)
160
+ return result
161
+
162
+ return sync_wrapper
163
+
164
+ return decorator
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: Kekik
3
- Version: 1.6.0
3
+ Version: 1.6.2
4
4
  Summary: İşlerimizi kolaylaştıracak fonksiyonların el altında durduğu kütüphane..
5
5
  Home-page: https://github.com/keyiflerolsun/Kekik
6
6
  Author: keyiflerolsun
@@ -26,6 +26,17 @@ Requires-Dist: simplejson
26
26
  Requires-Dist: rich
27
27
  Requires-Dist: tabulate
28
28
  Requires-Dist: pycryptodome
29
+ Dynamic: author
30
+ Dynamic: author-email
31
+ Dynamic: classifier
32
+ Dynamic: description
33
+ Dynamic: description-content-type
34
+ Dynamic: home-page
35
+ Dynamic: keywords
36
+ Dynamic: license
37
+ Dynamic: requires-dist
38
+ Dynamic: requires-python
39
+ Dynamic: summary
29
40
 
30
41
  # <img src="https://www.akashtrehan.com/assets/images/emoji/terminal.png" height="42" align="center"> Kekik
31
42
 
@@ -2,6 +2,7 @@ Kekik/BIST.py,sha256=gFvEFdLGgsxUq33AkqOr5pVGsSm9jR0v6DVwoSzhX7w,1375
2
2
  Kekik/Domain2IP.py,sha256=dMDatPElTMfLORzC_QN9znex8Se1eid3EPsxAe5S1aQ,4851
3
3
  Kekik/Nesne.py,sha256=33pp49cZkRCoa0aUFfzVMpx5FSJchSdiKhm97Nkol1Q,7020
4
4
  Kekik/__init__.py,sha256=Iy-O4c_DuY2ttQJv6j7xoVk3IS9EcC0Aqx3vhFvCgd8,1057
5
+ Kekik/cache.py,sha256=n15Ltoh068iFPK3ANDLz11eisOQXHLwUQA2eB3hjiiY,4861
5
6
  Kekik/cli.py,sha256=I--MV8-okBSUYAaV4fRsMeB2n57OJITrgbEnK1OdTPY,3648
6
7
  Kekik/csv2dict.py,sha256=HO0AgREXE0yM7cL4OwqpkCGm2pz31RTb0mhnTg6gdwo,423
7
8
  Kekik/dict2csv.py,sha256=AcGvEg9i5MXtwMwg7WiDxOj8h9LldNjjcRiWFwA9XJU,560
@@ -24,7 +25,7 @@ Kekik/unicode_tr.py,sha256=OUHfbVyKrt0IckyVy-d92gY3JZVkqgBpMZJLon2rCi0,1092
24
25
  Kekik/zaman_donustur.py,sha256=x-h85vS9D_xJ0jJO9svjIX8gCKYyGb_03AIzUjMk7tI,595
25
26
  Kekik/Sifreleme/AESManager.py,sha256=eYgbHANtYrWFJgLeUuj63tlL0Yn8gyPCJYbXfWlpNbo,2389
26
27
  Kekik/Sifreleme/CryptoJS.py,sha256=qDlgTaSXcs5jF4DNmjuwK5CL3VL1P7xyJzDTof1--As,3126
27
- Kekik/Sifreleme/HexCodec.py,sha256=DXd9Kyj6iqNvNRELe3GJVTrFPm-QKX2jFMXdnCpaeq4,702
28
+ Kekik/Sifreleme/HexCodec.py,sha256=fB1ZGBYCQLUUiZNXqn0sxYhEMhxPoyC1BPYkRJ5G7hY,900
28
29
  Kekik/Sifreleme/NaysHash.py,sha256=CJVlyHCXSv8JN8fitF2LQHLcd-opY6zergcgmX3pj_Y,2234
29
30
  Kekik/Sifreleme/Packer.py,sha256=4DWFMyhqsZvVKIUjZNruR8RwHSjuPKJi8WDCUTBGWCQ,2600
30
31
  Kekik/Sifreleme/StringCodec.py,sha256=5kmFLN7g2c_ENxD491lAlH0AGtW7tIy5h5KPHEuTzyM,1426
@@ -33,9 +34,9 @@ Kekik/kisi_ver/__init__.py,sha256=gH613YZC3ziE7f67dViefRSuwDwsHyVvXHpM5CzZ2q4,13
33
34
  Kekik/kisi_ver/biyografiler.py,sha256=5Xv1ixaDGHGtl5Nf92jo9dPgF3jDXOGEPmWgoEsn9j8,189486
34
35
  Kekik/kisi_ver/isimler.py,sha256=zHVimWL_4TvoLE3qzWQslDBc8-IJZSB02s0vRwsVM1g,88066
35
36
  Kekik/kisi_ver/soyisimler.py,sha256=YQJYp2SjENgwOaCa9mmShxPYeeUll2cq8Vox-d8_kB8,78485
36
- Kekik-1.6.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
37
- Kekik-1.6.0.dist-info/METADATA,sha256=9IqQ609umsySmXc9mC7NwPrHL5e9M1jX5gSQQjwgphY,43727
38
- Kekik-1.6.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
39
- Kekik-1.6.0.dist-info/entry_points.txt,sha256=yjBifxtRlqfg8lPkH4Bu-urSa5ecptCHsuth-DcyWcg,59
40
- Kekik-1.6.0.dist-info/top_level.txt,sha256=NotddscfgxawvuRyAa7xkgnMhyteFDcBxb5aU5GY3BM,6
41
- Kekik-1.6.0.dist-info/RECORD,,
37
+ Kekik-1.6.2.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
38
+ Kekik-1.6.2.dist-info/METADATA,sha256=6ZwkPdUXWuo-lBZTi2r0EyGfALiayeDYAeaJMVEu8bk,43959
39
+ Kekik-1.6.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
40
+ Kekik-1.6.2.dist-info/entry_points.txt,sha256=yjBifxtRlqfg8lPkH4Bu-urSa5ecptCHsuth-DcyWcg,59
41
+ Kekik-1.6.2.dist-info/top_level.txt,sha256=NotddscfgxawvuRyAa7xkgnMhyteFDcBxb5aU5GY3BM,6
42
+ Kekik-1.6.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (72.1.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
File without changes