vnai 2.0__py3-none-any.whl → 2.0.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.
- vnai/__init__.py +3 -1
- vnai/beam/quota.py +95 -25
- vnai/scope/profile.py +1 -1
- vnai/scope/promo.py +59 -39
- {vnai-2.0.dist-info → vnai-2.0.2.dist-info}/METADATA +10 -7
- {vnai-2.0.dist-info → vnai-2.0.2.dist-info}/RECORD +8 -8
- {vnai-2.0.dist-info → vnai-2.0.2.dist-info}/WHEEL +1 -1
- {vnai-2.0.dist-info → vnai-2.0.2.dist-info}/top_level.txt +0 -0
vnai/__init__.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
_L='default'
|
1
2
|
_K='standard'
|
2
3
|
_J='accepted_agreement'
|
3
4
|
_I='environment.json'
|
@@ -53,7 +54,8 @@ THÔNG TIN THIẾT BỊ: {json.dumps(A,indent=2)}
|
|
53
54
|
core=Core()
|
54
55
|
def tc_init(webhook_url=_B):return core.initialize(webhook_url)
|
55
56
|
def setup(webhook_url=_B):return core.initialize(webhook_url)
|
56
|
-
def optimize_execution(resource_type=
|
57
|
+
def optimize_execution(resource_type=_L):return optimize(resource_type)
|
58
|
+
def agg_execution(resource_type=_L):return optimize(resource_type,ad_cooldown=1500,content_trigger_threshold=100000)
|
57
59
|
def measure_performance(module_type='function'):return capture(module_type)
|
58
60
|
def accept_license_terms(terms_text=_B):
|
59
61
|
A=terms_text
|
vnai/beam/quota.py
CHANGED
@@ -1,37 +1,107 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
_G='resource_type'
|
2
|
+
_F=False
|
3
|
+
_E=True
|
4
|
+
_D=None
|
3
5
|
_C='default'
|
4
6
|
_B='hour'
|
5
7
|
_A='min'
|
6
|
-
import time,threading
|
8
|
+
import time,functools,threading
|
7
9
|
from collections import defaultdict
|
8
10
|
from datetime import datetime
|
11
|
+
class RateLimitExceeded(Exception):
|
12
|
+
def __init__(A,resource_type,limit_type=_A,current_usage=_D,limit_value=_D,retry_after=_D):
|
13
|
+
D=resource_type;B=retry_after;A.resource_type=D;A.limit_type=limit_type;A.current_usage=current_usage;A.limit_value=limit_value;A.retry_after=B;C=f"Bạn đã gửi quá nhiều request tới {D}. "
|
14
|
+
if B:C+=f"Vui lòng thử lại sau {round(B)} giây."
|
15
|
+
else:C+='Vui lòng thêm thời gian chờ giữa các lần gửi request.'
|
16
|
+
super().__init__(C)
|
9
17
|
class Guardian:
|
10
|
-
_instance=
|
18
|
+
_instance=_D;_lock=threading.Lock()
|
11
19
|
def __new__(A):
|
12
20
|
with A._lock:
|
13
|
-
if A._instance is
|
21
|
+
if A._instance is _D:A._instance=super(Guardian,A).__new__(A);A._instance._initialize()
|
14
22
|
return A._instance
|
15
|
-
def _initialize(A):A.resource_limits=defaultdict(lambda:defaultdict(int));A.usage_counters=defaultdict(lambda:defaultdict(list));A.resource_limits[_C]={_A:60,_B:
|
23
|
+
def _initialize(A):A.resource_limits=defaultdict(lambda:defaultdict(int));A.usage_counters=defaultdict(lambda:defaultdict(list));A.resource_limits[_C]={_A:60,_B:3000};A.resource_limits['TCBS']={_A:60,_B:3000};A.resource_limits['VCI']={_A:60,_B:3000};A.resource_limits['VCI.ext']={_A:600,_B:36000};A.resource_limits['VND.ext']={_A:600,_B:36000};A.resource_limits['CAF.ext']={_A:600,_B:36000};A.resource_limits['SPL.ext']={_A:600,_B:36000};A.resource_limits['VDS.ext']={_A:600,_B:36000};A.resource_limits['FAD.ext']={_A:600,_B:36000}
|
16
24
|
def verify(B,operation_id,resource_type=_C):
|
17
|
-
M='is_exceeded';L='current_usage';K='limit_value';J='limit_type';I='rate_limit';A=resource_type;
|
18
|
-
if O:from vnai.beam.metrics import collector as G;G.record(I,{
|
19
|
-
P=
|
20
|
-
if
|
21
|
-
B.usage_counters[A][_A].append(
|
25
|
+
M='is_exceeded';L='current_usage';K='limit_value';J='limit_type';I='rate_limit';A=resource_type;D=time.time();C=B.resource_limits.get(A,B.resource_limits[_C]);N=D-60;B.usage_counters[A][_A]=[A for A in B.usage_counters[A][_A]if A>N];F=len(B.usage_counters[A][_A]);O=F>=C[_A]
|
26
|
+
if O:from vnai.beam.metrics import collector as G;G.record(I,{_G:A,J:_A,K:C[_A],L:F,M:_E},priority='high');raise RateLimitExceeded(resource_type=A,limit_type=_A,current_usage=F,limit_value=C[_A],retry_after=60-D%60)
|
27
|
+
P=D-3600;B.usage_counters[A][_B]=[A for A in B.usage_counters[A][_B]if A>P];H=len(B.usage_counters[A][_B]);E=H>=C[_B];from vnai.beam.metrics import collector as G;G.record(I,{_G:A,J:_B if E else _A,K:C[_B]if E else C[_A],L:H if E else F,M:E})
|
28
|
+
if E:raise RateLimitExceeded(resource_type=A,limit_type=_B,current_usage=H,limit_value=C[_B],retry_after=3600-D%3600)
|
29
|
+
B.usage_counters[A][_A].append(D);B.usage_counters[A][_B].append(D);return _E
|
22
30
|
def usage(A,resource_type=_C):B=resource_type;D=time.time();C=A.resource_limits.get(B,A.resource_limits[_C]);E=D-60;F=D-3600;A.usage_counters[B][_A]=[A for A in A.usage_counters[B][_A]if A>E];A.usage_counters[B][_B]=[A for A in A.usage_counters[B][_B]if A>F];G=len(A.usage_counters[B][_A]);H=len(A.usage_counters[B][_B]);I=G/C[_A]*100 if C[_A]>0 else 0;J=H/C[_B]*100 if C[_B]>0 else 0;return max(I,J)
|
31
|
+
def get_limit_status(B,resource_type=_C):K='reset_in_seconds';J='remaining';I='percentage';H='limit';G='usage';C=resource_type;D=time.time();A=B.resource_limits.get(C,B.resource_limits[_C]);L=D-60;M=D-3600;E=len([A for A in B.usage_counters[C][_A]if A>L]);F=len([A for A in B.usage_counters[C][_B]if A>M]);return{_G:C,'minute_limit':{G:E,H:A[_A],I:E/A[_A]*100 if A[_A]>0 else 0,J:max(0,A[_A]-E),K:60-D%60},'hour_limit':{G:F,H:A[_B],I:F/A[_B]*100 if A[_B]>0 else 0,J:max(0,A[_B]-F),K:3600-D%3600}}
|
23
32
|
guardian=Guardian()
|
24
|
-
|
25
|
-
|
26
|
-
def A
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
if
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
class CleanErrorContext:
|
34
|
+
_last_message_time=0;_message_cooldown=5
|
35
|
+
def __enter__(A):return A
|
36
|
+
def __exit__(C,exc_type,exc_val,exc_tb):
|
37
|
+
A=exc_val
|
38
|
+
if exc_type is RateLimitExceeded:
|
39
|
+
B=time.time()
|
40
|
+
if B-CleanErrorContext._last_message_time>=CleanErrorContext._message_cooldown:print(f"\n⚠️ {str(A)}\n");CleanErrorContext._last_message_time=B
|
41
|
+
import sys;sys.exit(f"Rate limit exceeded. {str(A)} Process terminated.");return _F
|
42
|
+
return _F
|
43
|
+
def optimize(resource_type=_C,loop_threshold=10,time_window=5,ad_cooldown=150,content_trigger_threshold=3,max_retries=2,backoff_factor=2,debug=_F):
|
44
|
+
H=debug;G=ad_cooldown;F=resource_type;E=backoff_factor;D=max_retries;C=content_trigger_threshold;B=time_window;A=loop_threshold
|
45
|
+
if callable(F):I=F;return _create_wrapper(I,_C,A,B,G,C,D,E,H)
|
46
|
+
if A<2:raise ValueError(f"loop_threshold must be at least 2, got {A}")
|
47
|
+
if B<=0:raise ValueError(f"time_window must be positive, got {B}")
|
48
|
+
if C<1:raise ValueError(f"content_trigger_threshold must be at least 1, got {C}")
|
49
|
+
if D<0:raise ValueError(f"max_retries must be non-negative, got {D}")
|
50
|
+
if E<=0:raise ValueError(f"backoff_factor must be positive, got {E}")
|
51
|
+
def J(func):return _create_wrapper(func,F,A,B,G,C,D,E,H)
|
52
|
+
return J
|
53
|
+
def _create_wrapper(func,resource_type,loop_threshold,time_window,ad_cooldown,content_trigger_threshold,max_retries,backoff_factor,debug):
|
54
|
+
X=max_retries;W=content_trigger_threshold;P=time_window;K=resource_type;H=debug;A=func;B=[];I=0;E=0;F=_F;Q=time.time();c=1800
|
55
|
+
@functools.wraps(A)
|
56
|
+
def C(*d,**e):
|
57
|
+
b='timestamp';a='environment';V='error';O='function';N='loop';nonlocal I,E,F,Q;C=time.time();R=_F
|
58
|
+
if C-Q>c:F=_F;Q=C
|
59
|
+
G=0
|
60
|
+
while _E:
|
61
|
+
B.append(C)
|
62
|
+
while B and C-B[0]>P:B.pop(0)
|
63
|
+
S=len(B)>=loop_threshold
|
64
|
+
if H and S:print(f"[OPTIMIZE] Đã phát hiện vòng lặp cho {A.__name__}: {len(B)} lần gọi trong {P}s")
|
65
|
+
if S:
|
66
|
+
E+=1
|
67
|
+
if H:print(f"[OPTIMIZE] Số lần phát hiện vòng lặp liên tiếp: {E}/{W}")
|
68
|
+
else:E=0
|
69
|
+
f=E>=W and C-I>=ad_cooldown and not F
|
70
|
+
if f:
|
71
|
+
I=C;E=0;R=_E;F=_E
|
72
|
+
if H:print(f"[OPTIMIZE] Đã kích hoạt nội dung cho {A.__name__}")
|
73
|
+
try:
|
74
|
+
from vnai.scope.promo import manager as J
|
75
|
+
try:from vnai.scope.profile import inspector as T;U=T.examine().get(a,_D);J.present_content(environment=U,context=N)
|
76
|
+
except ImportError:J.present_content(context=N)
|
77
|
+
except ImportError:print(f"Phát hiện vòng lặp: Hàm '{A.__name__}' đang được gọi trong một vòng lặp")
|
78
|
+
except Exception as D:
|
79
|
+
if H:print(f"[OPTIMIZE] Lỗi khi hiển thị nội dung: {str(D)}")
|
80
|
+
try:
|
81
|
+
with CleanErrorContext():guardian.verify(A.__name__,K)
|
82
|
+
except RateLimitExceeded as D:
|
83
|
+
from vnai.beam.metrics import collector as L;L.record(V,{O:A.__name__,V:str(D),'context':'resource_verification',_G:K,'retry_attempt':G},priority='high')
|
84
|
+
if not F:
|
85
|
+
try:
|
86
|
+
from vnai.scope.promo import manager as J
|
87
|
+
try:from vnai.scope.profile import inspector as T;U=T.examine().get(a,_D);J.present_content(environment=U,context=N);F=_E;I=C
|
88
|
+
except ImportError:J.present_content(context=N);F=_E;I=C
|
89
|
+
except Exception:pass
|
90
|
+
if G<X:
|
91
|
+
M=backoff_factor**G;G+=1
|
92
|
+
if hasattr(D,'retry_after')and D.retry_after:M=min(M,D.retry_after)
|
93
|
+
if H:print(f"[OPTIMIZE] Đã đạt giới hạn tốc độ cho {A.__name__}, thử lại sau {M} giây (lần thử {G}/{X})")
|
94
|
+
time.sleep(M);continue
|
95
|
+
else:raise
|
96
|
+
g=time.time();Y=_F;Z=_D
|
97
|
+
try:h=A(*d,**e);Y=_E;return h
|
98
|
+
except Exception as D:Z=str(D);raise
|
99
|
+
finally:
|
100
|
+
i=time.time()-g
|
101
|
+
try:
|
102
|
+
from vnai.beam.metrics import collector as L;L.record(O,{O:A.__name__,_G:K,'execution_time':i,'success':Y,V:Z,'in_loop':S,'loop_depth':len(B),'content_triggered':R,b:datetime.now().isoformat(),'retry_count':G if G>0 else _D})
|
103
|
+
if R:L.record('ad_opportunity',{O:A.__name__,_G:K,'call_frequency':len(B)/P,'consecutive_loops':E,b:datetime.now().isoformat()})
|
104
|
+
except ImportError:pass
|
105
|
+
break
|
106
|
+
return C
|
107
|
+
def rate_limit_status(resource_type=_C):return guardian.get_limit_status(resource_type)
|
vnai/scope/profile.py
CHANGED
@@ -120,7 +120,7 @@ class Inspector:
|
|
120
120
|
def get_or_create_user_id(self):
|
121
121
|
if self._colab_auth_triggered:return self.machine_id
|
122
122
|
try:
|
123
|
-
from google.colab import drive;print('\n📋
|
123
|
+
from google.colab import drive;print('\n📋 Kết nối tài khoản Google Drive để lưu các thiết lập của dự án.');print('Dữ liệu phiên làm việc với Colab của bạn sẽ bị xóa nếu không lưu trữ vào Google Drive.\n');self._colab_auth_triggered=_A;drive.mount('/content/drive');id_path='/content/drive/MyDrive/.vnstock/user_id.txt'
|
124
124
|
if os.path.exists(id_path):
|
125
125
|
with open(id_path,'r')as f:return f.read().strip()
|
126
126
|
else:
|
vnai/scope/promo.py
CHANGED
@@ -1,56 +1,76 @@
|
|
1
|
-
|
1
|
+
_G='init'
|
2
|
+
_F='simple'
|
3
|
+
_E='markdown'
|
4
|
+
_D=True
|
5
|
+
_C=None
|
6
|
+
_B='terminal'
|
7
|
+
_A='html'
|
2
8
|
import requests
|
3
9
|
from datetime import datetime
|
4
|
-
import random,threading,time
|
10
|
+
import random,threading,time,urllib.parse
|
5
11
|
class ContentManager:
|
6
|
-
_instance=
|
12
|
+
_instance=_C;_lock=threading.Lock()
|
7
13
|
def __new__(A):
|
8
14
|
with A._lock:
|
9
|
-
if A._instance is
|
15
|
+
if A._instance is _C:A._instance=super(ContentManager,A).__new__(A);A._instance._initialize()
|
10
16
|
return A._instance
|
11
|
-
def _initialize(A):A.last_display=0;A.display_interval=86400;A.
|
17
|
+
def _initialize(A):A.last_display=0;A.display_interval=86400;A.content_base_url='https://vnstock-beam.hf.space/content-delivery';A.target_url='https://vnstocks.com/lp-khoa-hoc-python-chung-khoan';A.image_url='https://vnstocks.com/img/trang-chu-vnstock-python-api-phan-tich-giao-dich-chung-khoan.jpg';A._start_periodic_display()
|
12
18
|
def _start_periodic_display(A):
|
13
19
|
def B():
|
14
|
-
while
|
20
|
+
while _D:
|
15
21
|
B=random.randint(7200,21600);time.sleep(B);C=time.time()
|
16
|
-
if C-A.last_display>=A.display_interval:A.present_content()
|
17
|
-
C=threading.Thread(target=B,daemon=
|
18
|
-
def fetch_remote_content(B):
|
22
|
+
if C-A.last_display>=A.display_interval:A.present_content(context='periodic')
|
23
|
+
C=threading.Thread(target=B,daemon=_D);C.start()
|
24
|
+
def fetch_remote_content(B,context=_G,html=_D):
|
19
25
|
try:
|
20
|
-
A=requests.get(
|
26
|
+
C={'context':context,_A:'true'if html else'false'};D=f"{B.content_base_url}?{urllib.parse.urlencode(C)}";A=requests.get(D,timeout=3)
|
21
27
|
if A.status_code==200:return A.text
|
22
28
|
return
|
23
29
|
except:return
|
24
|
-
def present_content(
|
25
|
-
|
26
|
-
if
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
╔══════════════════════════════════════════════════════════╗
|
34
|
-
║ ║
|
35
|
-
║ 🚀 Phân tích dữ liệu & tạo bot chứng khoán K10 ║
|
36
|
-
║ ║
|
37
|
-
║ ✓ Khai giảng khóa mới từ 23/3/2025 ║
|
38
|
-
║ ✓ Tạo bot python đầu tư từ số 0 ║
|
39
|
-
║ ✓ Học 10 buổi chiều Chủ Nhật ║
|
40
|
-
║ ║
|
41
|
-
║ → Đăng ký ngay: {A.target_url} ║
|
42
|
-
║ ║
|
43
|
-
╚══════════════════════════════════════════════════════════╝
|
44
|
-
"""
|
45
|
-
if B=='jupyter':
|
30
|
+
def present_content(C,environment=_C,context=_G):
|
31
|
+
I='jupyter';H='unknown';E=context;A=environment;C.last_display=time.time()
|
32
|
+
if A is _C:
|
33
|
+
try:from vnai.scope.profile import inspector as J;A=J.examine().get('environment',H)
|
34
|
+
except:A=H
|
35
|
+
if A==I:B=C.fetch_remote_content(context=E,html=_D)
|
36
|
+
else:B=C.fetch_remote_content(context=E,html=False)
|
37
|
+
D=C._generate_fallback_content(E)
|
38
|
+
if A==I:
|
46
39
|
try:
|
47
|
-
from IPython.display import display as
|
48
|
-
if
|
40
|
+
from IPython.display import display as F,HTML as G,Markdown as K
|
41
|
+
if B:F(G(B))
|
49
42
|
else:
|
50
|
-
try:
|
51
|
-
except:
|
43
|
+
try:F(K(D[_E]))
|
44
|
+
except:F(G(D[_A]))
|
52
45
|
except:pass
|
53
|
-
elif
|
54
|
-
|
46
|
+
elif A==_B:
|
47
|
+
if B:print(B)
|
48
|
+
else:print(D[_B])
|
49
|
+
else:print(D[_F])
|
50
|
+
def _generate_fallback_content(B,context):
|
51
|
+
A={_A:'',_E:'',_B:'',_F:''}
|
52
|
+
if context=='loop':A[_A]=f'''
|
53
|
+
<div style="border: 1px solid #e74c3c; padding: 15px; border-radius: 5px; margin: 10px 0;">
|
54
|
+
<h3 style="color: #e74c3c;">⚠️ Bạn đang sử dụng vòng lặp với quá nhiều requests</h3>
|
55
|
+
<p>Để tránh bị giới hạn tốc độ và tối ưu hiệu suất:</p>
|
56
|
+
<ul>
|
57
|
+
<li>Thêm thời gian chờ giữa các lần gọi API</li>
|
58
|
+
<li>Sử dụng xử lý theo batch thay vì lặp liên tục</li>
|
59
|
+
<li>Tham gia gói tài trợ <a href="https://vnstocks.com/insiders-program" style="color: #3498db;">Vnstock Insider</a> để tăng 5X giới hạn API</li>
|
60
|
+
</ul>
|
61
|
+
</div>
|
62
|
+
''';A[_E]='\n## ⚠️ Bạn đang sử dụng vòng lặp với quá nhiều requests\n\nĐể tránh bị giới hạn tốc độ và tối ưu hiệu suất:\n* Thêm thời gian chờ giữa các lần gọi API\n* Sử dụng xử lý theo batch thay vì lặp liên tục\n* Tham gia gói tài trợ [Vnstock Insider](https://vnstocks.com/insiders-program) để tăng 5X giới hạn API\n ';A[_B]='\n╔═════════════════════════════════════════════════════════════════╗\n║ ║\n║ 🚫 ĐANG BỊ CHẶN BỞI GIỚI HẠN API? GIẢI PHÁP Ở ĐÂY! ║\n║ ║\n║ ✓ Tăng ngay 500% tốc độ gọi API - Không còn lỗi RateLimit ║\n║ ✓ Tiết kiệm 85% thời gian chờ đợi giữa các request ║\n║ ║\n║ ➤ NÂNG CẤP NGAY VỚI GÓI TÀI TRỢ VNSTOCK: ║\n║ https://vnstocks.com/insiders-program ║\n║ ║\n╚═════════════════════════════════════════════════════════════════╝\n ';A[_F]='🚫 Đang bị giới hạn API? Tăng tốc độ gọi API lên 500% với gói Vnstock Insider: https://vnstocks.com/insiders-program'
|
63
|
+
else:A[_A]=f'''
|
64
|
+
<div style="border: 1px solid #3498db; padding: 15px; border-radius: 5px; margin: 10px 0;">
|
65
|
+
<h3 style="color: #3498db;">👋 Chào mừng bạn đến với Vnstock!</h3>
|
66
|
+
<p>Cảm ơn bạn đã sử dụng thư viện phân tích chứng khoán #1 tại Việt Nam cho Python</p>
|
67
|
+
<ul>
|
68
|
+
<li>Tài liệu: <a href="https://vnstocks.com/docs/category/s%E1%BB%95-tay-h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn" style="color: #3498db;">vnstocks.com/docs</a></li>
|
69
|
+
<li>Cộng đồng: <a href="https://www.facebook.com/groups/vnstock.official" style="color: #3498db;">vnstocks.com/community</a></li>
|
70
|
+
</ul>
|
71
|
+
<p>Khám phá các tính năng mới nhất và tham gia cộng đồng để nhận hỗ trợ.</p>
|
72
|
+
</div>
|
73
|
+
''';A[_E]='\n## 👋 Chào mừng bạn đến với Vnstock!\n\nCảm ơn bạn đã sử dụng package phân tích chứng khoán #1 tại Việt Nam\n\n* Tài liệu: [vnstocks.com/docs](https://vnstocks.com/docs)\n* Cộng đồng: [vnstocks.com/community](https://vnstocks.com/community)\n\nKhám phá các tính năng mới nhất và tham gia cộng đồng để nhận hỗ trợ.\n ';A[_B]='\n╔══════════════════════════════════════════════════════════╗\n║ ║\n║ 👋 Chào mừng bạn đến với Vnstock! ║\n║ ║\n║ Cảm ơn bạn đã sử dụng package phân tích ║\n║ chứng khoán #1 tại Việt Nam ║\n║ ║\n║ ✓ Tài liệu: https://vnstocks.com/docs ║\n║ ✓ Cộng đồng: https://vnstocks.com/community ║\n║ ║\n║ Khám phá các tính năng mới nhất và tham gia ║\n║ cộng đồng để nhận hỗ trợ. ║\n║ ║\n╚══════════════════════════════════════════════════════════╝\n ';A[_F]='👋 Chào mừng bạn đến với Vnstock! Tài liệu: https://vnstocks.com/docs | Cộng đồng: https://vnstocks.com/community'
|
74
|
+
return A
|
55
75
|
manager=ContentManager()
|
56
|
-
def present():return manager.present_content()
|
76
|
+
def present(context=_G):return manager.present_content(context=context)
|
@@ -1,12 +1,12 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: vnai
|
3
|
-
Version: 2.0
|
3
|
+
Version: 2.0.2
|
4
4
|
Summary: System optimization and resource management toolkit
|
5
|
-
Home-page:
|
6
|
-
Author:
|
7
|
-
Author-email:
|
5
|
+
Home-page: https://github.com/yourusername/vnai
|
6
|
+
Author: Your Name
|
7
|
+
Author-email: your.email@example.com
|
8
|
+
License: MIT
|
8
9
|
Classifier: Programming Language :: Python :: 3
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
10
10
|
Classifier: Operating System :: OS Independent
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
12
12
|
Classifier: Intended Audience :: Developers
|
@@ -15,13 +15,16 @@ Requires-Python: >=3.7
|
|
15
15
|
Description-Content-Type: text/markdown
|
16
16
|
Requires-Dist: requests>=2.25.0
|
17
17
|
Requires-Dist: psutil>=5.8.0
|
18
|
-
Requires-Dist: cryptography>=3.4.0
|
19
18
|
Provides-Extra: dev
|
20
19
|
Requires-Dist: pytest>=6.0.0; extra == "dev"
|
21
20
|
Requires-Dist: black>=21.5b2; extra == "dev"
|
21
|
+
Dynamic: author
|
22
|
+
Dynamic: author-email
|
22
23
|
Dynamic: classifier
|
23
24
|
Dynamic: description
|
24
25
|
Dynamic: description-content-type
|
26
|
+
Dynamic: home-page
|
27
|
+
Dynamic: license
|
25
28
|
Dynamic: provides-extra
|
26
29
|
Dynamic: requires-dist
|
27
30
|
Dynamic: requires-python
|
@@ -1,16 +1,16 @@
|
|
1
|
-
vnai/__init__.py,sha256=
|
1
|
+
vnai/__init__.py,sha256=iS0LLz-J9MnC1m3aLPBPGfc7B36t2v4YX5lK4pRoiEU,4791
|
2
2
|
vnai/beam/__init__.py,sha256=MG_4FkhQZyuKeaoQQh-KaULhxcGu370lGR6FVV5blU4,129
|
3
3
|
vnai/beam/metrics.py,sha256=nVKoe0SJg0TNCPvAOaE99ZyBJ9Tw5WSRydyAObH8FrA,2709
|
4
4
|
vnai/beam/pulse.py,sha256=5e21Ky6rVKD57bf8BzSA2lGzwHhohansoQzggrnEpIE,1580
|
5
|
-
vnai/beam/quota.py,sha256=
|
5
|
+
vnai/beam/quota.py,sha256=zJWONvtd4pxYGDtdalrXHj1yBDasEzoQpMkENN38a70,7364
|
6
6
|
vnai/flow/__init__.py,sha256=BURTo8cXicmqqTbeB0qfXwVole0oGDVp_UxRSeh4qfA,80
|
7
7
|
vnai/flow/queue.py,sha256=pvC_HSjctR62Uzt4b3h3EANJXmrkKBm3iiNVIrlTnJA,1912
|
8
8
|
vnai/flow/relay.py,sha256=RU-paE3HVkgodPmNlAI8fAoVUcwufegY1WmsGL-sWpY,6676
|
9
9
|
vnai/scope/__init__.py,sha256=o7N7JjgSqIfQeDojgnxzV9gthEWL3YxxljnvRO9AXkQ,196
|
10
|
-
vnai/scope/profile.py,sha256=
|
11
|
-
vnai/scope/promo.py,sha256=
|
10
|
+
vnai/scope/profile.py,sha256=BHgX2yUQOMoJeUp_AaUWuc635bT1AJfw-FShNVRPikw,14985
|
11
|
+
vnai/scope/promo.py,sha256=5Q8VQszYdUaHt-3VPQrZsnxSSYgaXYG-oXnGridBM7U,7167
|
12
12
|
vnai/scope/state.py,sha256=JkVwJv8l_-ef201I_O1PHqFyp8KJ3VWyfmZnCltH18c,3283
|
13
|
-
vnai-2.0.dist-info/METADATA,sha256=
|
14
|
-
vnai-2.0.dist-info/WHEEL,sha256=
|
15
|
-
vnai-2.0.dist-info/top_level.txt,sha256=4zI0qZHePCwvgSqXl4420sBcd0VzZn4MEcRsAIFae3k,5
|
16
|
-
vnai-2.0.dist-info/RECORD,,
|
13
|
+
vnai-2.0.2.dist-info/METADATA,sha256=_jz71GfABM6GmUKnPCwZ4vc2iSwJEQOphpbozgitdDw,1017
|
14
|
+
vnai-2.0.2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
15
|
+
vnai-2.0.2.dist-info/top_level.txt,sha256=4zI0qZHePCwvgSqXl4420sBcd0VzZn4MEcRsAIFae3k,5
|
16
|
+
vnai-2.0.2.dist-info/RECORD,,
|
File without changes
|