vnai 2.1.1__py3-none-any.whl → 2.1.3__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 +78 -78
- vnai/beam/__init__.py +2 -2
- vnai/beam/metrics.py +72 -72
- vnai/beam/pulse.py +30 -30
- vnai/beam/quota.py +104 -104
- vnai/flow/__init__.py +1 -1
- vnai/flow/queue.py +54 -54
- vnai/flow/relay.py +160 -160
- vnai/scope/__init__.py +3 -3
- vnai/scope/profile.py +222 -222
- vnai/scope/promo.py +112 -117
- vnai/scope/state.py +73 -73
- {vnai-2.1.1.dist-info → vnai-2.1.3.dist-info}/METADATA +20 -20
- vnai-2.1.3.dist-info/RECORD +16 -0
- vnai-2.1.1.dist-info/RECORD +0 -16
- {vnai-2.1.1.dist-info → vnai-2.1.3.dist-info}/WHEEL +0 -0
- {vnai-2.1.1.dist-info → vnai-2.1.3.dist-info}/top_level.txt +0 -0
vnai/scope/promo.py
CHANGED
@@ -1,117 +1,112 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
import
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
logger=logging.
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
def periodic_display():
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
if
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
<p>
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
</div>
|
114
|
-
''';fallback[_F]='\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: [Sổ tay hướng dẫn](https://vnstocks.com/docs)\n* Cộng đồng: [Nhóm Facebook](https://facebook.com/groups/vnstock.official)\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 ';fallback[_E]='\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://facebook.com/groups/vnstock.official ║\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 ';fallback[_G]='👋 Chào mừng bạn đến với Vnstock! Tài liệu: https://vnstocks.com/onboard | Cộng đồng: https://facebook.com/groups/vnstock.official'
|
115
|
-
return fallback
|
116
|
-
manager=ContentManager()
|
117
|
-
def present(context:str=_H,ad_category:int=AdCategory.FREE)->_A:manager.present_content(context=context,ad_category=ad_category)
|
1
|
+
_G='init'
|
2
|
+
_F='terminal'
|
3
|
+
_E='markdown'
|
4
|
+
_D='html'
|
5
|
+
_C=True
|
6
|
+
_B=False
|
7
|
+
_A=None
|
8
|
+
import logging,requests
|
9
|
+
from datetime import datetime
|
10
|
+
import random,threading,time,urllib.parse
|
11
|
+
_vnii_check_attempted=_B
|
12
|
+
class AdCategory:FREE=0;MANDATORY=1;ANNOUNCEMENT=2;REFERRAL=3;FEATURE=4;GUIDE=5;SURVEY=6;PROMOTION=7;SECURITY=8;MAINTENANCE=9;WARNING=10
|
13
|
+
try:from vnii import lc_init
|
14
|
+
except ImportError:lc_init=_A
|
15
|
+
logger=logging.getLogger(__name__)
|
16
|
+
if not logger.hasHandlers():handler=logging.StreamHandler();handler.setFormatter(logging.Formatter('%(message)s'));logger.addHandler(handler);logger.setLevel(logging.ERROR)
|
17
|
+
class ContentManager:
|
18
|
+
_instance=_A;_lock=threading.Lock()
|
19
|
+
def __new__(cls):
|
20
|
+
with cls._lock:
|
21
|
+
if cls._instance is _A:cls._instance=super(ContentManager,cls).__new__(cls);cls._instance._initialize()
|
22
|
+
return cls._instance
|
23
|
+
def _initialize(self):
|
24
|
+
B='https://hq.vnstocks.com/content-delivery';A='vnii';self.content_base_url=B;global _vnii_check_attempted
|
25
|
+
if _vnii_check_attempted:return
|
26
|
+
_vnii_check_attempted=_C;import sys,importlib
|
27
|
+
try:
|
28
|
+
import importlib.metadata
|
29
|
+
try:
|
30
|
+
old_version=importlib.metadata.version(A);VNII_LATEST_VERSION='0.0.9';VNII_URL=f"https://github.com/vnstock-hq/licensing/releases/download/vnii-{VNII_LATEST_VERSION}/vnii-{VNII_LATEST_VERSION}.tar.gz";import subprocess
|
31
|
+
try:
|
32
|
+
subprocess.check_call([sys.executable,'-m','pip','install',f"vnii@{VNII_URL}"]);importlib.invalidate_caches()
|
33
|
+
if A in sys.modules:importlib.reload(sys.modules[A])
|
34
|
+
else:import vnii
|
35
|
+
new_version=importlib.metadata.version(A)
|
36
|
+
except Exception as e:logger.error(f"Lỗi khi cài đặt vnii: {e}");pass
|
37
|
+
except importlib.metadata.PackageNotFoundError:pass;self.is_paid_user=_B;return
|
38
|
+
except Exception as e:
|
39
|
+
logger.error(f"Lỗi khi kiểm tra/cài đặt vnii: {e}");user_msg=f"Không thể tự động cài đặt/cập nhật vnii. Vui lòng liên hệ admin hoặc hỗ trợ kỹ thuật của Vnstock để được trợ giúp. Chi tiết lỗi: {e}";logger.error(user_msg)
|
40
|
+
try:print(user_msg)
|
41
|
+
except Exception:pass
|
42
|
+
self.is_paid_user=_B;return
|
43
|
+
self.is_paid_user=_B
|
44
|
+
if lc_init is not _A:
|
45
|
+
try:
|
46
|
+
license_info=lc_init(repo_name='vnstock');status=license_info.get('status','').lower()
|
47
|
+
if'recognized and verified'in status:self.is_paid_user=_C
|
48
|
+
except Exception as e:pass
|
49
|
+
else:0
|
50
|
+
self.last_display=0;self.display_interval=86400;self.content_base_url=B;self.target_url='https://vnstocks.com/lp-khoa-hoc-python-chung-khoan';self.image_url='https://vnstocks.com/img/trang-chu-vnstock-python-api-phan-tich-giao-dich-chung-khoan.jpg';self._start_periodic_display()
|
51
|
+
def _start_periodic_display(self):
|
52
|
+
def periodic_display():
|
53
|
+
while _C:
|
54
|
+
if self.is_paid_user:break
|
55
|
+
sleep_time=random.randint(7200,21600);time.sleep(sleep_time);current_time=time.time()
|
56
|
+
if current_time-self.last_display>=self.display_interval:self.present_content(context='periodic')
|
57
|
+
else:0
|
58
|
+
thread=threading.Thread(target=periodic_display,daemon=_C);thread.start()
|
59
|
+
def fetch_remote_content(self,context:str=_G,html:bool=_C)->str:
|
60
|
+
if self.is_paid_user:return''
|
61
|
+
try:
|
62
|
+
params={'context':context,_D:'true'if html else'false'};url=f"{self.content_base_url}?{urllib.parse.urlencode(params)}";response=requests.get(url,timeout=3)
|
63
|
+
if response.status_code==200:return response.text
|
64
|
+
logger.error(f"Non-200 response fetching content: {response.status_code}");return
|
65
|
+
except Exception as e:logger.error(f"Failed to fetch remote content: {e}");return
|
66
|
+
def present_content(self,context:str=_G,ad_category:int=AdCategory.FREE)->_A:
|
67
|
+
C='jupyter';B='unknown';A='Hiển thị quảng cáo';environment=_A
|
68
|
+
if getattr(self,'is_paid_user',_B)and ad_category==AdCategory.FREE:return
|
69
|
+
self.last_display=time.time()
|
70
|
+
if environment is _A:
|
71
|
+
try:from vnai.scope.profile import inspector;environment=inspector.examine().get('environment',B)
|
72
|
+
except Exception as e:logger.error(f"Không detect được environment: {e}");environment=B
|
73
|
+
remote_content=self.fetch_remote_content(context=context,html=environment==C);fallback=self._generate_fallback_content(context)
|
74
|
+
if environment==C:
|
75
|
+
try:
|
76
|
+
from IPython.display import display,HTML,Markdown
|
77
|
+
if remote_content:display(HTML(remote_content))
|
78
|
+
else:
|
79
|
+
try:display(Markdown(fallback[_E]))
|
80
|
+
except Exception as e:display(HTML(fallback[_D]))
|
81
|
+
except Exception as e:pass
|
82
|
+
elif environment==_F:
|
83
|
+
if remote_content:logger.error(A)
|
84
|
+
else:logger.error(A)
|
85
|
+
else:logger.error(A)
|
86
|
+
def _generate_fallback_content(self,context):
|
87
|
+
A='simple';fallback={_D:'',_E:'',_F:'',A:''}
|
88
|
+
if context=='loop':fallback[_D]=f'''
|
89
|
+
<div style="border: 1px solid #e74c3c; padding: 15px; border-radius: 5px; margin: 10px 0;">
|
90
|
+
<h3 style="color: #e74c3c;">⚠️ Bạn đang sử dụng vòng lặp với quá nhiều requests</h3>
|
91
|
+
<p>Để tránh bị giới hạn tốc độ và tối ưu hiệu suất:</p>
|
92
|
+
<ul>
|
93
|
+
<li>Thêm thời gian chờ giữa các lần gọi API</li>
|
94
|
+
<li>Sử dụng xử lý theo batch thay vì lặp liên tục</li>
|
95
|
+
<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>
|
96
|
+
</ul>
|
97
|
+
</div>
|
98
|
+
''';fallback[_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 ';fallback[_F]='\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 ';fallback[A]='🚫 Đ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'
|
99
|
+
else:fallback[_D]=f'''
|
100
|
+
<div style="border: 1px solid #3498db; padding: 15px; border-radius: 5px; margin: 10px 0;">
|
101
|
+
<h3 style="color: #3498db;">👋 Chào mừng bạn đến với Vnstock!</h3>
|
102
|
+
<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>
|
103
|
+
<ul>
|
104
|
+
<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>
|
105
|
+
<li>Cộng đồng: <a href="https://www.facebook.com/groups/vnstock.official" style="color: #3498db;">vnstocks.com/community</a></li>
|
106
|
+
</ul>
|
107
|
+
<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>
|
108
|
+
</div>
|
109
|
+
''';fallback[_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: [Sổ tay hướng dẫn](https://vnstocks.com/docs)\n* Cộng đồng: [Nhóm Facebook](https://facebook.com/groups/vnstock.official)\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 ';fallback[_F]='\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://facebook.com/groups/vnstock.official ║\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 ';fallback[A]='👋 Chào mừng bạn đến với Vnstock! Tài liệu: https://vnstocks.com/onboard | Cộng đồng: https://facebook.com/groups/vnstock.official'
|
110
|
+
return fallback
|
111
|
+
manager=ContentManager()
|
112
|
+
def present(context:str=_G,ad_category:int=AdCategory.FREE)->_A:manager.present_content(context=context,ad_category=ad_category)
|
vnai/scope/state.py
CHANGED
@@ -1,74 +1,74 @@
|
|
1
|
-
_L='minimal'
|
2
|
-
_K='warnings'
|
3
|
-
_J='api_requests'
|
4
|
-
_I='last_error_time'
|
5
|
-
_H='startup_time'
|
6
|
-
_G='standard'
|
7
|
-
_F='function_calls'
|
8
|
-
_E='peak_memory'
|
9
|
-
_D='errors'
|
10
|
-
_C=True
|
11
|
-
_B=None
|
12
|
-
_A='execution_times'
|
13
|
-
import time,threading,json,os
|
14
|
-
from datetime import datetime
|
15
|
-
from pathlib import Path
|
16
|
-
class Tracker:
|
17
|
-
_instance=_B;_lock=threading.Lock()
|
18
|
-
def __new__(cls):
|
19
|
-
with cls._lock:
|
20
|
-
if cls._instance is _B:cls._instance=super(Tracker,cls).__new__(cls);cls._instance._initialize()
|
21
|
-
return cls._instance
|
22
|
-
def _initialize(self):self.metrics={_H:datetime.now().isoformat(),_F:0,_J:0,_D:0,_K:0};self.performance_metrics={_A:[],_I:_B,_E:0};self.privacy_level=_G;self.home_dir=Path.home();self.project_dir=self.home_dir/'.vnstock';self.project_dir.mkdir(exist_ok=_C);self.data_dir=self.project_dir/'data';self.data_dir.mkdir(exist_ok=_C);self.metrics_path=self.data_dir/'usage_metrics.json';self.privacy_config_path=self.project_dir/'config'/'privacy.json';os.makedirs(os.path.dirname(self.privacy_config_path),exist_ok=_C);self._load_metrics();self._load_privacy_settings();self._start_background_collector()
|
23
|
-
def _load_metrics(self):
|
24
|
-
if self.metrics_path.exists():
|
25
|
-
try:
|
26
|
-
with open(self.metrics_path,'r')as f:stored_metrics=json.load(f)
|
27
|
-
for(key,value)in stored_metrics.items():
|
28
|
-
if key in self.metrics:self.metrics[key]=value
|
29
|
-
except:pass
|
30
|
-
def _save_metrics(self):
|
31
|
-
try:
|
32
|
-
with open(self.metrics_path,'w')as f:json.dump(self.metrics,f)
|
33
|
-
except:pass
|
34
|
-
def _load_privacy_settings(self):
|
35
|
-
if self.privacy_config_path.exists():
|
36
|
-
try:
|
37
|
-
with open(self.privacy_config_path,'r')as f:settings=json.load(f);self.privacy_level=settings.get('level',_G)
|
38
|
-
except:pass
|
39
|
-
def setup_privacy(self,level=_B):
|
40
|
-
privacy_levels={_L:'Essential system data only',_G:'Performance metrics and errors','enhanced':'Detailed operation analytics'}
|
41
|
-
if level is _B:level=_G
|
42
|
-
if level not in privacy_levels:raise ValueError(f"Invalid privacy level: {level}. Choose from {', '.join(privacy_levels.keys())}")
|
43
|
-
self.privacy_level=level
|
44
|
-
with open(self.privacy_config_path,'w')as f:json.dump({'level':level},f)
|
45
|
-
return level
|
46
|
-
def get_privacy_level(self):return self.privacy_level
|
47
|
-
def _start_background_collector(self):
|
48
|
-
def collect_metrics():
|
49
|
-
while _C:
|
50
|
-
try:
|
51
|
-
import psutil;current_process=psutil.Process();memory_info=current_process.memory_info();memory_usage=memory_info.rss/1048576
|
52
|
-
if memory_usage>self.performance_metrics[_E]:self.performance_metrics[_E]=memory_usage
|
53
|
-
self._save_metrics()
|
54
|
-
except:pass
|
55
|
-
time.sleep(300)
|
56
|
-
thread=threading.Thread(target=collect_metrics,daemon=_C);thread.start()
|
57
|
-
def record(self,event_type,data=_B):
|
58
|
-
A='execution_time'
|
59
|
-
if self.privacy_level==_L and event_type!=_D:return _C
|
60
|
-
if event_type in self.metrics:self.metrics[event_type]+=1
|
61
|
-
else:self.metrics[event_type]=1
|
62
|
-
if event_type==_D:self.performance_metrics[_I]=datetime.now().isoformat()
|
63
|
-
if event_type==_F and data and A in data:
|
64
|
-
self.performance_metrics[_A].append(data[A])
|
65
|
-
if len(self.performance_metrics[_A])>100:self.performance_metrics[_A]=self.performance_metrics[_A][-100:]
|
66
|
-
if self.metrics[_F]%100==0 or event_type==_D:self._save_metrics()
|
67
|
-
return _C
|
68
|
-
def get_metrics(self):
|
69
|
-
avg_execution_time=0
|
70
|
-
if self.performance_metrics[_A]:avg_execution_time=sum(self.performance_metrics[_A])/len(self.performance_metrics[_A])
|
71
|
-
output=self.metrics.copy();output.update({'avg_execution_time':avg_execution_time,'peak_memory_mb':self.performance_metrics[_E],'uptime':(datetime.now()-datetime.fromisoformat(self.metrics[_H])).total_seconds(),'privacy_level':self.privacy_level});return output
|
72
|
-
def reset(self):self.metrics={_H:datetime.now().isoformat(),_F:0,_J:0,_D:0,_K:0};self.performance_metrics={_A:[],_I:_B,_E:0};self._save_metrics();return _C
|
73
|
-
tracker=Tracker()
|
1
|
+
_L='minimal'
|
2
|
+
_K='warnings'
|
3
|
+
_J='api_requests'
|
4
|
+
_I='last_error_time'
|
5
|
+
_H='startup_time'
|
6
|
+
_G='standard'
|
7
|
+
_F='function_calls'
|
8
|
+
_E='peak_memory'
|
9
|
+
_D='errors'
|
10
|
+
_C=True
|
11
|
+
_B=None
|
12
|
+
_A='execution_times'
|
13
|
+
import time,threading,json,os
|
14
|
+
from datetime import datetime
|
15
|
+
from pathlib import Path
|
16
|
+
class Tracker:
|
17
|
+
_instance=_B;_lock=threading.Lock()
|
18
|
+
def __new__(cls):
|
19
|
+
with cls._lock:
|
20
|
+
if cls._instance is _B:cls._instance=super(Tracker,cls).__new__(cls);cls._instance._initialize()
|
21
|
+
return cls._instance
|
22
|
+
def _initialize(self):self.metrics={_H:datetime.now().isoformat(),_F:0,_J:0,_D:0,_K:0};self.performance_metrics={_A:[],_I:_B,_E:0};self.privacy_level=_G;self.home_dir=Path.home();self.project_dir=self.home_dir/'.vnstock';self.project_dir.mkdir(exist_ok=_C);self.data_dir=self.project_dir/'data';self.data_dir.mkdir(exist_ok=_C);self.metrics_path=self.data_dir/'usage_metrics.json';self.privacy_config_path=self.project_dir/'config'/'privacy.json';os.makedirs(os.path.dirname(self.privacy_config_path),exist_ok=_C);self._load_metrics();self._load_privacy_settings();self._start_background_collector()
|
23
|
+
def _load_metrics(self):
|
24
|
+
if self.metrics_path.exists():
|
25
|
+
try:
|
26
|
+
with open(self.metrics_path,'r')as f:stored_metrics=json.load(f)
|
27
|
+
for(key,value)in stored_metrics.items():
|
28
|
+
if key in self.metrics:self.metrics[key]=value
|
29
|
+
except:pass
|
30
|
+
def _save_metrics(self):
|
31
|
+
try:
|
32
|
+
with open(self.metrics_path,'w')as f:json.dump(self.metrics,f)
|
33
|
+
except:pass
|
34
|
+
def _load_privacy_settings(self):
|
35
|
+
if self.privacy_config_path.exists():
|
36
|
+
try:
|
37
|
+
with open(self.privacy_config_path,'r')as f:settings=json.load(f);self.privacy_level=settings.get('level',_G)
|
38
|
+
except:pass
|
39
|
+
def setup_privacy(self,level=_B):
|
40
|
+
privacy_levels={_L:'Essential system data only',_G:'Performance metrics and errors','enhanced':'Detailed operation analytics'}
|
41
|
+
if level is _B:level=_G
|
42
|
+
if level not in privacy_levels:raise ValueError(f"Invalid privacy level: {level}. Choose from {', '.join(privacy_levels.keys())}")
|
43
|
+
self.privacy_level=level
|
44
|
+
with open(self.privacy_config_path,'w')as f:json.dump({'level':level},f)
|
45
|
+
return level
|
46
|
+
def get_privacy_level(self):return self.privacy_level
|
47
|
+
def _start_background_collector(self):
|
48
|
+
def collect_metrics():
|
49
|
+
while _C:
|
50
|
+
try:
|
51
|
+
import psutil;current_process=psutil.Process();memory_info=current_process.memory_info();memory_usage=memory_info.rss/1048576
|
52
|
+
if memory_usage>self.performance_metrics[_E]:self.performance_metrics[_E]=memory_usage
|
53
|
+
self._save_metrics()
|
54
|
+
except:pass
|
55
|
+
time.sleep(300)
|
56
|
+
thread=threading.Thread(target=collect_metrics,daemon=_C);thread.start()
|
57
|
+
def record(self,event_type,data=_B):
|
58
|
+
A='execution_time'
|
59
|
+
if self.privacy_level==_L and event_type!=_D:return _C
|
60
|
+
if event_type in self.metrics:self.metrics[event_type]+=1
|
61
|
+
else:self.metrics[event_type]=1
|
62
|
+
if event_type==_D:self.performance_metrics[_I]=datetime.now().isoformat()
|
63
|
+
if event_type==_F and data and A in data:
|
64
|
+
self.performance_metrics[_A].append(data[A])
|
65
|
+
if len(self.performance_metrics[_A])>100:self.performance_metrics[_A]=self.performance_metrics[_A][-100:]
|
66
|
+
if self.metrics[_F]%100==0 or event_type==_D:self._save_metrics()
|
67
|
+
return _C
|
68
|
+
def get_metrics(self):
|
69
|
+
avg_execution_time=0
|
70
|
+
if self.performance_metrics[_A]:avg_execution_time=sum(self.performance_metrics[_A])/len(self.performance_metrics[_A])
|
71
|
+
output=self.metrics.copy();output.update({'avg_execution_time':avg_execution_time,'peak_memory_mb':self.performance_metrics[_E],'uptime':(datetime.now()-datetime.fromisoformat(self.metrics[_H])).total_seconds(),'privacy_level':self.privacy_level});return output
|
72
|
+
def reset(self):self.metrics={_H:datetime.now().isoformat(),_F:0,_J:0,_D:0,_K:0};self.performance_metrics={_A:[],_I:_B,_E:0};self._save_metrics();return _C
|
73
|
+
tracker=Tracker()
|
74
74
|
def record(event_type,data=_B):return tracker.record(event_type,data)
|
@@ -1,20 +1,20 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: vnai
|
3
|
-
Version: 2.1.
|
4
|
-
Summary:
|
5
|
-
Author-email: Vnstock
|
6
|
-
License:
|
7
|
-
Project-URL: Homepage, https://vnstocks.com
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
9
|
-
Classifier: Operating System :: OS Independent
|
10
|
-
Classifier: Development Status :: 4 - Beta
|
11
|
-
Classifier: Intended Audience :: Developers
|
12
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
13
|
-
Requires-Python: >=3.7
|
14
|
-
Description-Content-Type: text/markdown
|
15
|
-
Requires-Dist: requests>=2.25.0
|
16
|
-
Requires-Dist: psutil>=5.8.0
|
17
|
-
Provides-Extra: dev
|
18
|
-
Requires-Dist: pytest>=6.0.0; extra == "dev"
|
19
|
-
|
20
|
-
# VnAI
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: vnai
|
3
|
+
Version: 2.1.3
|
4
|
+
Summary: Vnstock Analytics Interface
|
5
|
+
Author-email: Vnstock Analytics Team <support@vnstocks.com>
|
6
|
+
License: proprietary
|
7
|
+
Project-URL: Homepage, https://vnstocks.com
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
9
|
+
Classifier: Operating System :: OS Independent
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
11
|
+
Classifier: Intended Audience :: Developers
|
12
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
13
|
+
Requires-Python: >=3.7
|
14
|
+
Description-Content-Type: text/markdown
|
15
|
+
Requires-Dist: requests>=2.25.0
|
16
|
+
Requires-Dist: psutil>=5.8.0
|
17
|
+
Provides-Extra: dev
|
18
|
+
Requires-Dist: pytest>=6.0.0; extra == "dev"
|
19
|
+
|
20
|
+
# VnAI
|
@@ -0,0 +1,16 @@
|
|
1
|
+
vnai/__init__.py,sha256=TNcdB1eufYIVWWs25pdqVMMLtl5ReP4QbVw2zq7SwgY,5355
|
2
|
+
vnai/beam/__init__.py,sha256=l6jim5R4VhmlO4bMfJuTqyn6oXOWXwEOCuyJiYiyw6U,131
|
3
|
+
vnai/beam/metrics.py,sha256=eA2jcuyN9Pko7qsly3Izn633W_9K1cuS1FwoFgKg5m8,4200
|
4
|
+
vnai/beam/pulse.py,sha256=yEoeIWF-ETAU5yTLdX1bv24OkTy-HS5GeP4Zxu0KjV4,1915
|
5
|
+
vnai/beam/quota.py,sha256=8ATexinh_TRnu__gbv_QxBlp_yeev1sKfSCiCWe-aH8,10337
|
6
|
+
vnai/flow/__init__.py,sha256=fT-MfBTKjgc2u7OFmVK1j7YOtWehAeeYrmP98zuuV1M,81
|
7
|
+
vnai/flow/queue.py,sha256=8qGhKokzQ1YYGuT5iTf4AlPfdAhSz86MDcqHMWHsmEY,2300
|
8
|
+
vnai/flow/relay.py,sha256=4nKPUlPWkIZ2NmEjDYuhUsCHMsErnDixtajR4F8m2mE,9112
|
9
|
+
vnai/scope/__init__.py,sha256=5Ud3rS9ymUfGalWWWDyBiDcWj-w6bp3ls0HPj8wK0wQ,199
|
10
|
+
vnai/scope/profile.py,sha256=wqJ10Uy3n_oHtaVZincHAd7-Y_8VHRTiKyJ11S6I8Og,15207
|
11
|
+
vnai/scope/promo.py,sha256=4zJTFoXn5XZZ5rExgUwThGBW0YSO9ajouob0HkRZuzk,10137
|
12
|
+
vnai/scope/state.py,sha256=kl80wQWM59g0f9UIBIUc5S_ImyyIEsqwEy02QTnFhVU,3914
|
13
|
+
vnai-2.1.3.dist-info/METADATA,sha256=VuW6CDYVtjp3gn9M01H5zwx_RYwdIe3t6Y__3RvqmAs,682
|
14
|
+
vnai-2.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
15
|
+
vnai-2.1.3.dist-info/top_level.txt,sha256=4zI0qZHePCwvgSqXl4420sBcd0VzZn4MEcRsAIFae3k,5
|
16
|
+
vnai-2.1.3.dist-info/RECORD,,
|
vnai-2.1.1.dist-info/RECORD
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
vnai/__init__.py,sha256=CMpislNEQ5QTJkbY4pcI2or65l7kYzWdgDs7_RifvGA,5277
|
2
|
-
vnai/beam/__init__.py,sha256=MG_4FkhQZyuKeaoQQh-KaULhxcGu370lGR6FVV5blU4,129
|
3
|
-
vnai/beam/metrics.py,sha256=1tGV58wEIe4ZbK7yqQoeq4VzCSTJojg4aAChIyqBmgY,4128
|
4
|
-
vnai/beam/pulse.py,sha256=jatge9Di-g_o1TjM3yuq8cWtOROs2GHUlLkExDhSM90,1885
|
5
|
-
vnai/beam/quota.py,sha256=Ix5PoRMr2-2Y-y5QMn_TmE3ECjb_JVyNYyoQ5qGttHE,10233
|
6
|
-
vnai/flow/__init__.py,sha256=BURTo8cXicmqqTbeB0qfXwVole0oGDVp_UxRSeh4qfA,80
|
7
|
-
vnai/flow/queue.py,sha256=2Eb1kyC7QhRp-uDdya1QMUWvtD21cv5vncqHzTvAvMo,2246
|
8
|
-
vnai/flow/relay.py,sha256=UNFxt2W79XNkgHeFCxkeYNVym-x-8GuI0adSDGUbdyY,8952
|
9
|
-
vnai/scope/__init__.py,sha256=o7N7JjgSqIfQeDojgnxzV9gthEWL3YxxljnvRO9AXkQ,196
|
10
|
-
vnai/scope/profile.py,sha256=BHgX2yUQOMoJeUp_AaUWuc635bT1AJfw-FShNVRPikw,14985
|
11
|
-
vnai/scope/promo.py,sha256=Ts8z04npfMl99F-xiSB6_kYBiYpK0EYO5AjX7-CGmJI,12893
|
12
|
-
vnai/scope/state.py,sha256=IoVCPrDmZX822tS9Pk_JQvXpKcN8WogA1yZGa1d476Q,3841
|
13
|
-
vnai-2.1.1.dist-info/METADATA,sha256=Z__Y3kndRG1YOS4I_ppDGT97cIP_tAyL9l69NIee1mo,666
|
14
|
-
vnai-2.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
15
|
-
vnai-2.1.1.dist-info/top_level.txt,sha256=4zI0qZHePCwvgSqXl4420sBcd0VzZn4MEcRsAIFae3k,5
|
16
|
-
vnai-2.1.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|