vnai 2.1.1__py3-none-any.whl → 2.1.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/scope/promo.py CHANGED
@@ -1,117 +1,112 @@
1
- _H='init'
2
- _G='simple'
3
- _F='markdown'
4
- _E='terminal'
5
- _D='html'
6
- _C=True
7
- _B=False
8
- _A=None
9
- import logging,requests
10
- from datetime import datetime
11
- import random,threading,time,urllib.parse
12
- _vnii_check_attempted=_B
13
- class AdCategory:FREE=0;MANDATORY=1;ANNOUNCEMENT=2;REFERRAL=3;FEATURE=4;GUIDE=5;SURVEY=6;PROMOTION=7;SECURITY=8;MAINTENANCE=9;WARNING=10
14
- try:from vnii import lc_init
15
- except ImportError:lc_init=_A
16
- logger=logging.getLogger(__name__)
17
- if not logger.hasHandlers():handler=logging.StreamHandler();handler.setFormatter(logging.Formatter('%(message)s'));logger.addHandler(handler);logger.setLevel(logging.INFO)
18
- class ContentManager:
19
- _instance=_A;_lock=threading.Lock()
20
- def __new__(cls):
21
- with cls._lock:
22
- if cls._instance is _A:cls._instance=super(ContentManager,cls).__new__(cls);cls._instance._initialize()
23
- return cls._instance
24
- def _initialize(self):
25
- A='vnii';global _vnii_check_attempted
26
- if _vnii_check_attempted:return
27
- _vnii_check_attempted=_C;import sys,importlib
28
- try:
29
- import importlib.metadata
30
- try:
31
- 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";logger.debug(f"Đã phát hiện vnii version {old_version}. Đang cập nhật lên bản mới nhất...");import subprocess;subprocess.check_call([sys.executable,'-m','pip','install',f"vnii@{VNII_URL}"]);importlib.invalidate_caches()
32
- if A in sys.modules:importlib.reload(sys.modules[A])
33
- else:import vnii
34
- new_version=importlib.metadata.version(A);logger.debug(f"Đã cập nhật vnii lên version {new_version}")
35
- except importlib.metadata.PackageNotFoundError:logger.debug('Không phát hiện vnii trên hệ thống. Luôn coi là free user, không kiểm tra license.');self.is_paid_user=_B;return
36
- except Exception as e:
37
- logger.warning(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)
38
- try:print(user_msg)
39
- except Exception:pass
40
- self.is_paid_user=_B;return
41
- self.is_paid_user=_B;logger.debug('[promo] Bắt đầu kiểm tra trạng thái paid user với vnii...')
42
- if lc_init is not _A:
43
- try:
44
- license_info=lc_init(repo_name='vnstock');logger.debug(f"[promo] license_info trả về: {license_info}");status=license_info.get('status','').lower()
45
- if'recognized and verified'in status:self.is_paid_user=_C;logger.debug('[promo] Đã xác nhận paid user từ vnii. Sẽ không hiện quảng cáo.')
46
- else:logger.debug(f"[promo] Không xác nhận được paid user từ vnii. Status: {status}")
47
- except Exception as e:logger.warning(f"[promo] Không thể kiểm tra trạng thái sponsor: {e}. Sẽ coi là free user và hiện quảng cáo.")
48
- else:logger.debug('[promo] Không tìm thấy module vnii. Luôn coi là free user và hiện quảng cáo.')
49
- self.last_display=0;self.display_interval=86400;self.content_base_url='https://hq.vnstocks.com/static';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';logger.debug(f"[promo] is_paid_user = {self.is_paid_user}");self._start_periodic_display()
50
- def _start_periodic_display(self):
51
- logger.debug('[promo] Khởi tạo thread hiển thị quảng cáo định kỳ...')
52
- def periodic_display():
53
- logger.debug('[promo] Thread quảng cáo bắt đầu chạy.')
54
- while _C:
55
- if self.is_paid_user:logger.debug('[promo] Đang là paid user trong thread. Không hiện quảng cáo, dừng thread.');break
56
- sleep_time=random.randint(7200,21600);logger.debug(f"[promo] Thread quảng cáo sẽ ngủ {sleep_time//3600} giờ...");time.sleep(sleep_time);current_time=time.time();logger.debug(f"[promo] Kiểm tra điều kiện hiện quảng cáo: time since last_display = {current_time-self.last_display}s")
57
- if current_time-self.last_display>=self.display_interval:logger.debug("[promo] Đã đủ thời gian, sẽ gọi present_content(context='periodic')");self.present_content(context='periodic')
58
- else:logger.debug('[promo] Chưa đủ thời gian, chưa hiện quảng cáo.')
59
- thread=threading.Thread(target=periodic_display,daemon=_C);thread.start()
60
- def fetch_remote_content(self,context:str=_H,html:bool=_C)->str:
61
- if self.is_paid_user:logger.debug('Paid user detected. Skip fetching remote content (ads).');return''
62
- try:
63
- 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)
64
- if response.status_code==200:return response.text
65
- logger.debug(f"Non-200 response fetching content: {response.status_code}");return
66
- except Exception as e:logger.debug(f"Failed to fetch remote content: {e}");return
67
- def present_content(self,context:str=_H,ad_category:int=AdCategory.FREE)->_A:
68
- C='jupyter';B='unknown';A='is_paid_user';environment=_A;logger.debug(f"[promo] Gọi present_content(context={context}, ad_category={ad_category}). is_paid_user = {getattr(self,A,_A)}")
69
- if getattr(self,A,_B)and ad_category==AdCategory.FREE:logger.debug('[promo] Đang là paid user và ad_category là FREE. Không hiện quảng cáo.');return
70
- if logger.level<=logging.DEBUG:logger.debug(f"[promo] Sẽ hiển thị quảng cáo với context={context}, ad_category={ad_category}")
71
- self.last_display=time.time()
72
- if environment is _A:
73
- try:from vnai.scope.profile import inspector;environment=inspector.examine().get('environment',B);logger.debug(f"[promo] Đã detect environment: {environment}")
74
- except Exception as e:logger.debug(f"[promo] Không detect được environment: {e}");environment=B
75
- remote_content=self.fetch_remote_content(context=context,html=environment==C);logger.debug(f"[promo] remote_content = {bool(remote_content)} (None -> False, có nội dung -> True)");fallback=self._generate_fallback_content(context);logger.debug(f"[promo] fallback keys: {list(fallback.keys())}")
76
- if environment==C:
77
- logger.debug('[promo] Đang ở môi trường Jupyter, sẽ thử display HTML/Markdown.')
78
- try:
79
- from IPython.display import display,HTML,Markdown
80
- if remote_content:logger.debug('[promo] Hiển thị quảng cáo bằng HTML từ remote_content.');display(HTML(remote_content))
81
- else:
82
- logger.debug('[promo] Không có remote_content, thử display fallback Markdown/HTML.')
83
- try:display(Markdown(fallback[_F]))
84
- except Exception as e:logger.debug(f"[promo] Lỗi khi display Markdown: {e}, fallback HTML.");display(HTML(fallback[_D]))
85
- except Exception as e:logger.debug(f"[promo] Jupyter display failed: {e}")
86
- elif environment==_E:
87
- logger.debug('[promo] Đang ở môi trường terminal, sẽ log quảng cáo ra logger.')
88
- if remote_content:logger.debug('[promo] Hiển thị quảng cáo bằng remote_content cho terminal.');logger.debug(remote_content)
89
- else:logger.debug('[promo] Không remote_content, hiển thị fallback terminal.');logger.debug(fallback[_E])
90
- else:logger.debug(f"[promo] Môi trường khác ({environment}), hiển thị fallback simple.");logger.debug(fallback[_G])
91
- def _generate_fallback_content(self,context):
92
- fallback={_D:'',_F:'',_E:'',_G:''}
93
- if context=='loop':fallback[_D]=f'''
94
- <div style="border: 1px solid #e74c3c; padding: 15px; border-radius: 5px; margin: 10px 0;">
95
- <h3 style="color: #e74c3c;">⚠️ Bạn đang sử dụng vòng lặp với quá nhiều requests</h3>
96
- <p>Để tránh bị giới hạn tốc độ và tối ưu hiệu suất:</p>
97
- <ul>
98
- <li>Thêm thời gian chờ giữa các lần gọi API</li>
99
- <li>Sử dụng xử lý theo batch thay vì lặp liên tục</li>
100
- <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>
101
- </ul>
102
- </div>
103
- ''';fallback[_F]='\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[_E]='\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[_G]='🚫 Đ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'
104
- else:fallback[_D]=f'''
105
- <div style="border: 1px solid #3498db; padding: 15px; border-radius: 5px; margin: 10px 0;">
106
- <h3 style="color: #3498db;">👋 Chào mừng bạn đến với Vnstock!</h3>
107
- <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>
108
- <ul>
109
- <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>
110
- <li>Cộng đồng: <a href="https://www.facebook.com/groups/vnstock.official" style="color: #3498db;">vnstocks.com/community</a></li>
111
- </ul>
112
- <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>
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
+ A='vnii';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='https://hq.vnstocks.com/content-delivery';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ử theo batch thay 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 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.1
4
- Summary: System optimization and resource management toolkit
5
- Author-email: Vnstock HQ <support@vnstocks.com>
6
- License: MIT
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.2
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=pi0dYQGPEIEicNPPNZFgui8B1MVXdlVRV8fJmUQj8XE,10109
12
+ vnai/scope/state.py,sha256=kl80wQWM59g0f9UIBIUc5S_ImyyIEsqwEy02QTnFhVU,3914
13
+ vnai-2.1.2.dist-info/METADATA,sha256=eSVsfIIFN_pip8WyrKu06YJQNX8J1_elcLfr5if7OGQ,682
14
+ vnai-2.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
+ vnai-2.1.2.dist-info/top_level.txt,sha256=4zI0qZHePCwvgSqXl4420sBcd0VzZn4MEcRsAIFae3k,5
16
+ vnai-2.1.2.dist-info/RECORD,,
@@ -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