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.
- kekik-1.6.3/Kekik/cache.py +191 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik.egg-info/PKG-INFO +13 -2
- {kekik-1.6.1 → kekik-1.6.3}/Kekik.egg-info/SOURCES.txt +1 -0
- {kekik-1.6.1 → kekik-1.6.3}/PKG-INFO +13 -2
- {kekik-1.6.1 → kekik-1.6.3}/setup.py +1 -1
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/BIST.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/Domain2IP.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/Nesne.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/AESManager.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/CryptoJS.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/HexCodec.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/NaysHash.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/Packer.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/StringCodec.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/Sifreleme/__init__.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/__init__.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/cli.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/csv2dict.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/dict2csv.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/dict2json.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/dosya2set.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/dosya_indir.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/hwid_kontrol.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/kisi_ver/__init__.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/kisi_ver/biyografiler.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/kisi_ver/isimler.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/kisi_ver/soyisimler.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/link_islemleri.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/list2html.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/liste_fetis.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/mail_gonder.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/okunabilir_byte.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/proxy_ver.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/qr_ver.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/ses_fetis.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/slugify.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/terminal_baslik.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/txt_fetis.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/unicode_tr.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik/zaman_donustur.py +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik.egg-info/dependency_links.txt +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik.egg-info/entry_points.txt +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik.egg-info/requires.txt +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/Kekik.egg-info/top_level.txt +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/LICENSE +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/MANIFEST.in +0 -0
- {kekik-1.6.1 → kekik-1.6.3}/README.md +0 -0
- {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
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: Kekik
|
|
3
|
-
Version: 1.6.
|
|
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
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: Kekik
|
|
3
|
-
Version: 1.6.
|
|
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.
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|