Kekik 1.6.1__tar.gz → 1.6.3__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.

Potentially problematic release.


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

Files changed (48) hide show
  1. kekik-1.6.3/Kekik/cache.py +191 -0
  2. {kekik-1.6.1 → kekik-1.6.3}/Kekik.egg-info/PKG-INFO +13 -2
  3. {kekik-1.6.1 → kekik-1.6.3}/Kekik.egg-info/SOURCES.txt +1 -0
  4. {kekik-1.6.1 → kekik-1.6.3}/PKG-INFO +13 -2
  5. {kekik-1.6.1 → kekik-1.6.3}/setup.py +1 -1
  6. {kekik-1.6.1 → kekik-1.6.3}/Kekik/BIST.py +0 -0
  7. {kekik-1.6.1 → kekik-1.6.3}/Kekik/Domain2IP.py +0 -0
  8. {kekik-1.6.1 → kekik-1.6.3}/Kekik/Nesne.py +0 -0
  9. {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/AESManager.py +0 -0
  10. {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/CryptoJS.py +0 -0
  11. {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/HexCodec.py +0 -0
  12. {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/NaysHash.py +0 -0
  13. {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/Packer.py +0 -0
  14. {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/StringCodec.py +0 -0
  15. {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/__init__.py +0 -0
  16. {kekik-1.6.1 → kekik-1.6.3}/Kekik/__init__.py +0 -0
  17. {kekik-1.6.1 → kekik-1.6.3}/Kekik/cli.py +0 -0
  18. {kekik-1.6.1 → kekik-1.6.3}/Kekik/csv2dict.py +0 -0
  19. {kekik-1.6.1 → kekik-1.6.3}/Kekik/dict2csv.py +0 -0
  20. {kekik-1.6.1 → kekik-1.6.3}/Kekik/dict2json.py +0 -0
  21. {kekik-1.6.1 → kekik-1.6.3}/Kekik/dosya2set.py +0 -0
  22. {kekik-1.6.1 → kekik-1.6.3}/Kekik/dosya_indir.py +0 -0
  23. {kekik-1.6.1 → kekik-1.6.3}/Kekik/hwid_kontrol.py +0 -0
  24. {kekik-1.6.1 → kekik-1.6.3}/Kekik/kisi_ver/__init__.py +0 -0
  25. {kekik-1.6.1 → kekik-1.6.3}/Kekik/kisi_ver/biyografiler.py +0 -0
  26. {kekik-1.6.1 → kekik-1.6.3}/Kekik/kisi_ver/isimler.py +0 -0
  27. {kekik-1.6.1 → kekik-1.6.3}/Kekik/kisi_ver/soyisimler.py +0 -0
  28. {kekik-1.6.1 → kekik-1.6.3}/Kekik/link_islemleri.py +0 -0
  29. {kekik-1.6.1 → kekik-1.6.3}/Kekik/list2html.py +0 -0
  30. {kekik-1.6.1 → kekik-1.6.3}/Kekik/liste_fetis.py +0 -0
  31. {kekik-1.6.1 → kekik-1.6.3}/Kekik/mail_gonder.py +0 -0
  32. {kekik-1.6.1 → kekik-1.6.3}/Kekik/okunabilir_byte.py +0 -0
  33. {kekik-1.6.1 → kekik-1.6.3}/Kekik/proxy_ver.py +0 -0
  34. {kekik-1.6.1 → kekik-1.6.3}/Kekik/qr_ver.py +0 -0
  35. {kekik-1.6.1 → kekik-1.6.3}/Kekik/ses_fetis.py +0 -0
  36. {kekik-1.6.1 → kekik-1.6.3}/Kekik/slugify.py +0 -0
  37. {kekik-1.6.1 → kekik-1.6.3}/Kekik/terminal_baslik.py +0 -0
  38. {kekik-1.6.1 → kekik-1.6.3}/Kekik/txt_fetis.py +0 -0
  39. {kekik-1.6.1 → kekik-1.6.3}/Kekik/unicode_tr.py +0 -0
  40. {kekik-1.6.1 → kekik-1.6.3}/Kekik/zaman_donustur.py +0 -0
  41. {kekik-1.6.1 → kekik-1.6.3}/Kekik.egg-info/dependency_links.txt +0 -0
  42. {kekik-1.6.1 → kekik-1.6.3}/Kekik.egg-info/entry_points.txt +0 -0
  43. {kekik-1.6.1 → kekik-1.6.3}/Kekik.egg-info/requires.txt +0 -0
  44. {kekik-1.6.1 → kekik-1.6.3}/Kekik.egg-info/top_level.txt +0 -0
  45. {kekik-1.6.1 → kekik-1.6.3}/LICENSE +0 -0
  46. {kekik-1.6.1 → kekik-1.6.3}/MANIFEST.in +0 -0
  47. {kekik-1.6.1 → kekik-1.6.3}/README.md +0 -0
  48. {kekik-1.6.1 → kekik-1.6.3}/setup.cfg +0 -0
@@ -0,0 +1,191 @@
1
+ # ! https://github.com/Fatal1ty/aiocached
2
+
3
+ import asyncio
4
+ from functools import wraps
5
+ from time import time
6
+ from hashlib import md5
7
+ from urllib.parse import urlencode
8
+
9
+ UNLIMITED = None
10
+
11
+ class Cache:
12
+ """
13
+ Basit in-memory cache yapısı.
14
+ TTL (time-to-live) süresi dolan veriler otomatik olarak temizlenir.
15
+ """
16
+ def __init__(self, ttl=UNLIMITED):
17
+ self._data = {}
18
+ self._ttl = ttl
19
+ self._times = {}
20
+
21
+ def _is_expired(self, key):
22
+ """Belirtilen key'in süresi dolduysa True döner."""
23
+ if self._ttl is UNLIMITED:
24
+ return False
25
+
26
+ timestamp = self._times.get(key)
27
+
28
+ return timestamp is not None and (time() - timestamp > self._ttl)
29
+
30
+ def remove_if_expired(self, key):
31
+ """
32
+ Eğer key'in cache süresi dolmuşsa, ilgili entry'yi temizler.
33
+ """
34
+ if self._is_expired(key):
35
+ self._data.pop(key, None)
36
+ self._times.pop(key, None)
37
+
38
+ def __getitem__(self, key):
39
+ self.remove_if_expired(key)
40
+ return self._data[key]
41
+
42
+ def __setitem__(self, key, value):
43
+ self._data[key] = value
44
+ if self._ttl is not UNLIMITED:
45
+ self._times[key] = time()
46
+
47
+
48
+ class AsyncCache(Cache):
49
+ """
50
+ Asenkron işlemleri destekleyen cache yapısı.
51
+ Aynı key için gelen eşzamanlı çağrılar, futures kullanılarak tek sonuç üzerinden paylaşılır.
52
+ """
53
+ def __init__(self, ttl=UNLIMITED):
54
+ super().__init__(ttl)
55
+ self.futures = {}
56
+
57
+ async def get(self, key):
58
+ """
59
+ Belirtilen key için cache'de saklanan değeri asenkron olarak döndürür.
60
+ Eğer key bulunamazsa, ilgili future üzerinden beklemeyi sağlar.
61
+ """
62
+ self.remove_if_expired(key)
63
+
64
+ try:
65
+ return self._data[key]
66
+ except KeyError as e:
67
+ future = self.futures.get(key)
68
+ if future:
69
+ await future
70
+ return future.result()
71
+
72
+ raise e
73
+
74
+ def remove_if_expired(self, key):
75
+ """
76
+ Belirtilen key'in süresi dolduysa, cache ve futures içerisinden temizler.
77
+ """
78
+ if self._ttl is not UNLIMITED and self._is_expired(key):
79
+ self._data.pop(key, None)
80
+ self._times.pop(key, None)
81
+ self.futures.pop(key, None)
82
+
83
+
84
+ def _sync_maybe_cache(func, key, result, unless):
85
+ """Senkron sonuç için cache kaydını oluşturur (unless koşuluna bakarak)."""
86
+ if unless is None or not unless(result):
87
+ func.__cache[key] = result
88
+
89
+
90
+ async def _async_compute_and_cache(func, key, unless, *args, **kwargs):
91
+ """
92
+ Asenkron fonksiyon sonucu hesaplandıktan sonra, sonucu cache’e ekler.
93
+ Eğer `unless` koşulu sağlanıyorsa cache kaydı atlanır.
94
+ """
95
+ cache = func.__cache
96
+ future = asyncio.Future()
97
+ cache.futures[key] = future
98
+
99
+ try:
100
+ result = await func(*args, **kwargs)
101
+ except Exception as exc:
102
+ cache.futures.pop(key, None)
103
+ future.cancel()
104
+ raise exc
105
+
106
+ future.set_result(result)
107
+
108
+ if unless is None or not unless(result):
109
+ cache[key] = result
110
+ else:
111
+ cache.futures.pop(key, None)
112
+
113
+ return result
114
+
115
+ async def make_cache_key(args, kwargs, is_fastapi=False):
116
+ """
117
+ Cache key'ini oluşturur.
118
+
119
+ :param is_fastapi (bool): Eğer True ise, ilk argümanın bir FastAPI Request nesnesi olduğu varsayılır.
120
+ Bu durumda, cache key, request nesnesinin URL yolunu (request.url.path) ve
121
+ isteğe ait verilerden (GET istekleri için query parametreleri; diğer istekler için JSON veya form verileri)
122
+ elde edilen verinin URL uyumlu halinin md5 hash'inin birleşiminden oluşturulur.
123
+ Böylece, aynı URL ve aynı istek verileri için her seferinde aynı cache key üretilecektir.
124
+ Eğer False ise, cache key args ve kwargs değerlerinden, sıralı bir tuple olarak oluşturulur.
125
+ """
126
+ if not is_fastapi:
127
+ return (args, tuple(sorted(kwargs.items())))
128
+
129
+ request = args[0] if args else kwargs.get("request")
130
+
131
+ if request.method == "GET":
132
+ veri = dict(request.query_params) if request.query_params else None
133
+ else:
134
+ try:
135
+ veri = await request.json()
136
+ except Exception:
137
+ form_data = await request.form()
138
+ veri = dict(form_data.items())
139
+
140
+ args_hash = md5(urlencode(veri).encode()).hexdigest() if veri else ""
141
+ return f"{request.url.path}?{args_hash}"
142
+
143
+
144
+ def kekik_cache(ttl=UNLIMITED, unless=None, is_fastapi=False):
145
+ """
146
+ Bir fonksiyon veya coroutine'in sonucunu cache'ler.
147
+
148
+ :param ttl: Cache’in geçerlilik süresi (saniye). UNLIMITED ise süresizdir.
149
+ :param unless: Fonksiyonun sonucunu argüman olarak alan bir callable.
150
+ Eğer True dönerse, sonuç cache'e alınmaz.
151
+ :param is_fastapi: Eğer True ise, cache key'i oluştururken FastAPI request nesnesine özel şekilde davranır.
152
+
153
+ Örnek kullanım:
154
+
155
+ @kekik_cache(ttl=15, unless=lambda res: res is None)
156
+ async def bakalim(param):
157
+ ...
158
+ """
159
+ # Parametresiz kullanıldığında
160
+ if callable(ttl):
161
+ return kekik_cache(UNLIMITED, unless=unless, is_fastapi=is_fastapi)(ttl)
162
+
163
+ def decorator(func):
164
+ func.__cache = AsyncCache(ttl)
165
+
166
+ if asyncio.iscoroutinefunction(func):
167
+ @wraps(func)
168
+ async def async_wrapper(*args, **kwargs):
169
+ key = await make_cache_key(args, kwargs, is_fastapi)
170
+
171
+ try:
172
+ return await func.__cache.get(key)
173
+ except KeyError:
174
+ return await _async_compute_and_cache(func, key, unless, *args, **kwargs)
175
+
176
+ return async_wrapper
177
+ else:
178
+ @wraps(func)
179
+ def sync_wrapper(*args, **kwargs):
180
+ key = (args, tuple(sorted(kwargs.items())))
181
+
182
+ try:
183
+ return func.__cache[key]
184
+ except KeyError:
185
+ result = func(*args, **kwargs)
186
+ _sync_maybe_cache(func, key, result, unless)
187
+ return result
188
+
189
+ return sync_wrapper
190
+
191
+ return decorator
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: Kekik
3
- Version: 1.6.1
3
+ Version: 1.6.3
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
 
@@ -6,6 +6,7 @@ Kekik/BIST.py
6
6
  Kekik/Domain2IP.py
7
7
  Kekik/Nesne.py
8
8
  Kekik/__init__.py
9
+ Kekik/cache.py
9
10
  Kekik/cli.py
10
11
  Kekik/csv2dict.py
11
12
  Kekik/dict2csv.py
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: Kekik
3
- Version: 1.6.1
3
+ Version: 1.6.3
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
 
@@ -6,7 +6,7 @@ from io import open
6
6
  setup(
7
7
  # ? Genel Bilgiler
8
8
  name = "Kekik",
9
- version = "1.6.1",
9
+ version = "1.6.3",
10
10
  url = "https://github.com/keyiflerolsun/Kekik",
11
11
  description = "İşlerimizi kolaylaştıracak fonksiyonların el altında durduğu kütüphane..",
12
12
  keywords = ["Kekik", "KekikAkademi", "keyiflerolsun"],
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes