vnai 2.0.1__py3-none-any.whl → 2.0.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 +84 -54
- vnai/beam/__init__.py +0 -3
- vnai/beam/metrics.py +57 -32
- vnai/beam/pulse.py +36 -21
- vnai/beam/quota.py +143 -109
- vnai/flow/__init__.py +4 -2
- vnai/flow/queue.py +31 -20
- vnai/flow/relay.py +101 -64
- vnai/scope/__init__.py +4 -2
- vnai/scope/profile.py +205 -110
- vnai/scope/promo.py +96 -114
- vnai/scope/state.py +64 -38
- {vnai-2.0.1.dist-info → vnai-2.0.3.dist-info}/METADATA +3 -2
- vnai-2.0.3.dist-info/RECORD +16 -0
- {vnai-2.0.1.dist-info → vnai-2.0.3.dist-info}/WHEEL +1 -1
- vnai-2.0.1.dist-info/RECORD +0 -16
- {vnai-2.0.1.dist-info → vnai-2.0.3.dist-info}/top_level.txt +0 -0
vnai/scope/promo.py
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
# Content display mechanism for various environments
|
3
|
-
|
1
|
+
import logging
|
4
2
|
import requests
|
5
3
|
from datetime import datetime
|
6
4
|
import random
|
@@ -8,139 +6,120 @@ import threading
|
|
8
6
|
import time
|
9
7
|
import urllib.parse
|
10
8
|
|
9
|
+
logger = logging.getLogger(__name__)
|
10
|
+
if not logger.hasHandlers():
|
11
|
+
handler = logging.StreamHandler()
|
12
|
+
handler.setFormatter(logging.Formatter('%(message)s'))
|
13
|
+
logger.addHandler(handler)
|
14
|
+
logger.setLevel(logging.INFO)
|
15
|
+
|
11
16
|
class ContentManager:
|
12
|
-
"""Manages content display across different environments"""
|
13
|
-
|
14
17
|
_instance = None
|
15
18
|
_lock = threading.Lock()
|
16
|
-
|
19
|
+
|
17
20
|
def __new__(cls):
|
18
21
|
with cls._lock:
|
19
22
|
if cls._instance is None:
|
20
23
|
cls._instance = super(ContentManager, cls).__new__(cls)
|
21
24
|
cls._instance._initialize()
|
22
25
|
return cls._instance
|
23
|
-
|
26
|
+
|
24
27
|
def _initialize(self):
|
25
|
-
"""Initialize content manager"""
|
26
28
|
self.last_display = 0
|
27
|
-
self.display_interval = 24 * 3600
|
28
|
-
|
29
|
-
self.
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
self.display_interval = 24 * 3600
|
30
|
+
|
31
|
+
self.content_base_url = (
|
32
|
+
"https://vnstock-beam.hf.space/content-delivery"
|
33
|
+
)
|
34
|
+
self.target_url = (
|
35
|
+
"https://vnstocks.com/lp-khoa-hoc-python-chung-khoan"
|
36
|
+
)
|
37
|
+
self.image_url = (
|
38
|
+
"https://vnstocks.com/img/trang-chu-vnstock-python-api-phan-tich-giao-dich-chung-khoan.jpg"
|
39
|
+
)
|
40
|
+
|
33
41
|
self._start_periodic_display()
|
34
|
-
|
42
|
+
|
35
43
|
def _start_periodic_display(self):
|
36
|
-
"""Start thread for occasional content display"""
|
37
44
|
def periodic_display():
|
38
45
|
while True:
|
39
|
-
# Sleep for a random time between 2-6 hours
|
40
46
|
sleep_time = random.randint(2 * 3600, 6 * 3600)
|
41
47
|
time.sleep(sleep_time)
|
42
|
-
|
43
|
-
# Only show if enough time has passed since last display
|
48
|
+
|
44
49
|
current_time = time.time()
|
45
50
|
if current_time - self.last_display >= self.display_interval:
|
46
51
|
self.present_content(context="periodic")
|
47
|
-
|
48
|
-
# Start thread as daemon so it doesn't prevent program exit
|
52
|
+
|
49
53
|
thread = threading.Thread(target=periodic_display, daemon=True)
|
50
54
|
thread.start()
|
51
|
-
|
55
|
+
|
52
56
|
def fetch_remote_content(self, context="init", html=True):
|
53
|
-
"""
|
54
|
-
Fetch content from remote source
|
55
|
-
|
56
|
-
Args:
|
57
|
-
context (str): Context of the content request (init, loop, periodic, etc.)
|
58
|
-
html (bool): Whether to request HTML content (True) or plain text (False)
|
59
|
-
"""
|
60
57
|
try:
|
61
|
-
|
62
|
-
params = {
|
63
|
-
"context": context,
|
64
|
-
"html": "true" if html else "false"
|
65
|
-
}
|
58
|
+
params = {"context": context, "html": "true" if html else "false"}
|
66
59
|
url = f"{self.content_base_url}?{urllib.parse.urlencode(params)}"
|
67
|
-
|
60
|
+
|
68
61
|
response = requests.get(url, timeout=3)
|
69
62
|
if response.status_code == 200:
|
70
63
|
return response.text
|
64
|
+
logger.debug(f"Non-200 response fetching content: {response.status_code}")
|
71
65
|
return None
|
72
|
-
except:
|
66
|
+
except Exception as e:
|
67
|
+
logger.debug(f"Failed to fetch remote content: {e}")
|
73
68
|
return None
|
74
|
-
|
69
|
+
|
75
70
|
def present_content(self, environment=None, context="init"):
|
76
|
-
"""
|
77
|
-
Present content appropriate for the environment and context
|
78
|
-
|
79
|
-
Args:
|
80
|
-
environment (str): The display environment (jupyter, terminal, etc.)
|
81
|
-
context (str): The context for content (init, loop, periodic)
|
82
|
-
"""
|
83
|
-
# Update last display time
|
84
71
|
self.last_display = time.time()
|
85
|
-
|
86
|
-
# Get environment if not provided
|
72
|
+
|
87
73
|
if environment is None:
|
88
74
|
try:
|
89
75
|
from vnai.scope.profile import inspector
|
90
|
-
|
91
|
-
|
76
|
+
|
77
|
+
environment = (
|
78
|
+
inspector.examine().get("environment", "unknown")
|
79
|
+
)
|
80
|
+
except Exception:
|
92
81
|
environment = "unknown"
|
93
|
-
|
94
|
-
# Try to fetch remote content based on context and environment
|
82
|
+
|
95
83
|
if environment == "jupyter":
|
96
|
-
remote_content = self.fetch_remote_content(
|
84
|
+
remote_content = self.fetch_remote_content(
|
85
|
+
context=context, html=True
|
86
|
+
)
|
97
87
|
else:
|
98
|
-
remote_content = self.fetch_remote_content(
|
99
|
-
|
100
|
-
|
88
|
+
remote_content = self.fetch_remote_content(
|
89
|
+
context=context, html=False
|
90
|
+
)
|
91
|
+
|
101
92
|
fallback_content = self._generate_fallback_content(context)
|
102
|
-
|
103
|
-
# Display based on environment
|
93
|
+
|
104
94
|
if environment == "jupyter":
|
105
95
|
try:
|
106
96
|
from IPython.display import display, HTML, Markdown
|
97
|
+
|
107
98
|
if remote_content:
|
108
|
-
# Use remote content if available
|
109
99
|
display(HTML(remote_content))
|
110
100
|
else:
|
111
|
-
# Try markdown version first
|
112
101
|
try:
|
113
102
|
display(Markdown(fallback_content["markdown"]))
|
114
|
-
except:
|
115
|
-
# Fall back to HTML if markdown fails
|
103
|
+
except Exception:
|
116
104
|
display(HTML(fallback_content["html"]))
|
117
|
-
except:
|
118
|
-
|
119
|
-
|
120
|
-
|
105
|
+
except Exception as e:
|
106
|
+
logger.debug(f"Jupyter display failed: {e}")
|
107
|
+
|
121
108
|
elif environment == "terminal":
|
122
109
|
if remote_content:
|
123
|
-
|
110
|
+
logger.info(remote_content)
|
124
111
|
else:
|
125
|
-
|
126
|
-
|
112
|
+
logger.info(fallback_content["terminal"])
|
113
|
+
|
127
114
|
else:
|
128
|
-
|
129
|
-
|
130
|
-
|
115
|
+
logger.info(fallback_content["simple"])
|
116
|
+
|
131
117
|
def _generate_fallback_content(self, context):
|
132
|
-
"""
|
133
|
-
|
134
|
-
"html": "",
|
135
|
-
"markdown": "",
|
136
|
-
"terminal": "",
|
137
|
-
"simple": ""
|
138
|
-
}
|
139
|
-
|
118
|
+
fallback = {"html": "", "markdown": "", "terminal": "", "simple": ""}
|
119
|
+
|
140
120
|
if context == "loop":
|
141
|
-
|
142
|
-
|
143
|
-
fallback["html"] = f"""
|
121
|
+
fallback["html"] = (
|
122
|
+
f"""
|
144
123
|
<div style="border: 1px solid #e74c3c; padding: 15px; border-radius: 5px; margin: 10px 0;">
|
145
124
|
<h3 style="color: #e74c3c;">⚠️ Bạn đang sử dụng vòng lặp với quá nhiều requests</h3>
|
146
125
|
<p>Để tránh bị giới hạn tốc độ và tối ưu hiệu suất:</p>
|
@@ -151,8 +130,9 @@ class ContentManager:
|
|
151
130
|
</ul>
|
152
131
|
</div>
|
153
132
|
"""
|
154
|
-
|
155
|
-
fallback["markdown"] =
|
133
|
+
)
|
134
|
+
fallback["markdown"] = (
|
135
|
+
"""
|
156
136
|
## ⚠️ Bạn đang sử dụng vòng lặp với quá nhiều requests
|
157
137
|
|
158
138
|
Để tránh bị giới hạn tốc độ và tối ưu hiệu suất:
|
@@ -160,8 +140,9 @@ class ContentManager:
|
|
160
140
|
* Sử dụng xử lý theo batch thay vì lặp liên tục
|
161
141
|
* Tham gia gói tài trợ [Vnstock Insider](https://vnstocks.com/insiders-program) để tăng 5X giới hạn API
|
162
142
|
"""
|
163
|
-
|
164
|
-
fallback["terminal"] =
|
143
|
+
)
|
144
|
+
fallback["terminal"] = (
|
145
|
+
"""
|
165
146
|
╔═════════════════════════════════════════════════════════════════╗
|
166
147
|
║ ║
|
167
148
|
║ 🚫 ĐANG BỊ CHẶN BỞI GIỚI HẠN API? GIẢI PHÁP Ở ĐÂY! ║
|
@@ -173,13 +154,15 @@ class ContentManager:
|
|
173
154
|
║ https://vnstocks.com/insiders-program ║
|
174
155
|
║ ║
|
175
156
|
╚═════════════════════════════════════════════════════════════════╝
|
176
|
-
|
177
|
-
|
178
|
-
fallback["simple"] =
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
157
|
+
"""
|
158
|
+
)
|
159
|
+
fallback["simple"] = (
|
160
|
+
"🚫 Đang bị giới hạn API? Tăng tốc độ gọi API lên 500% với gói "
|
161
|
+
"Vnstock Insider: https://vnstocks.com/insiders-program"
|
162
|
+
)
|
163
|
+
else:
|
164
|
+
fallback["html"] = (
|
165
|
+
f"""
|
183
166
|
<div style="border: 1px solid #3498db; padding: 15px; border-radius: 5px; margin: 10px 0;">
|
184
167
|
<h3 style="color: #3498db;">👋 Chào mừng bạn đến với Vnstock!</h3>
|
185
168
|
<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>
|
@@ -190,19 +173,21 @@ class ContentManager:
|
|
190
173
|
<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>
|
191
174
|
</div>
|
192
175
|
"""
|
193
|
-
|
194
|
-
fallback["markdown"] =
|
176
|
+
)
|
177
|
+
fallback["markdown"] = (
|
178
|
+
"""
|
195
179
|
## 👋 Chào mừng bạn đến với Vnstock!
|
196
180
|
|
197
181
|
Cảm ơn bạn đã sử dụng package phân tích chứng khoán #1 tại Việt Nam
|
198
182
|
|
199
|
-
* Tài liệu: [
|
200
|
-
* Cộng đồng: [
|
183
|
+
* Tài liệu: [Sổ tay hướng dẫn](https://vnstocks.com/docs/category/s%E1%BB%95-tay-h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn)
|
184
|
+
* Cộng đồng: [Nhóm Facebook](https://www.facebook.com/groups/vnstock.official)
|
201
185
|
|
202
186
|
Khám phá các tính năng mới nhất và tham gia cộng đồng để nhận hỗ trợ.
|
203
|
-
|
204
|
-
|
205
|
-
fallback["terminal"] =
|
187
|
+
"""
|
188
|
+
)
|
189
|
+
fallback["terminal"] = (
|
190
|
+
"""
|
206
191
|
╔══════════════════════════════════════════════════════════╗
|
207
192
|
║ ║
|
208
193
|
║ 👋 Chào mừng bạn đến với Vnstock! ║
|
@@ -210,27 +195,24 @@ Khám phá các tính năng mới nhất và tham gia cộng đồng để nhậ
|
|
210
195
|
║ Cảm ơn bạn đã sử dụng package phân tích ║
|
211
196
|
║ chứng khoán #1 tại Việt Nam ║
|
212
197
|
║ ║
|
213
|
-
║ ✓ Tài liệu: https://vnstocks.com/docs
|
214
|
-
║ ✓ Cộng đồng: https://
|
198
|
+
║ ✓ Tài liệu: https://vnstocks.com/docs/category/s%E1%BB%95-tay-h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn ║
|
199
|
+
║ ✓ Cộng đồng: https://www.facebook.com/groups/vnstock.official ║
|
215
200
|
║ ║
|
216
201
|
║ Khám phá các tính năng mới nhất và tham gia ║
|
217
202
|
║ cộng đồng để nhận hỗ trợ. ║
|
218
203
|
║ ║
|
219
204
|
╚══════════════════════════════════════════════════════════╝
|
220
|
-
|
221
|
-
|
222
|
-
fallback["simple"] =
|
223
|
-
|
205
|
+
"""
|
206
|
+
)
|
207
|
+
fallback["simple"] = (
|
208
|
+
"👋 Chào mừng bạn đến với Vnstock! "
|
209
|
+
"Tài liệu: https://vnstocks.com/docs/tai-lieu/huong-dan-nhanh | "
|
210
|
+
"Cộng đồng: https://www.facebook.com/groups/vnstock.official"
|
211
|
+
)
|
224
212
|
return fallback
|
225
213
|
|
226
|
-
#
|
214
|
+
# Singleton instance
|
227
215
|
manager = ContentManager()
|
228
216
|
|
229
|
-
def present(context="init"):
|
230
|
-
"""
|
231
|
-
Public API to present content
|
232
|
-
|
233
|
-
Args:
|
234
|
-
context (str): Context for content presentation (init, loop, periodic)
|
235
|
-
"""
|
217
|
+
def present(context="init"): # module-level shortcut
|
236
218
|
return manager.present_content(context=context)
|
vnai/scope/state.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
##
|
2
|
+
|
3
|
+
##
|
4
|
+
|
3
5
|
|
4
6
|
import time
|
5
7
|
import threading
|
@@ -9,7 +11,7 @@ from datetime import datetime
|
|
9
11
|
from pathlib import Path
|
10
12
|
|
11
13
|
class Tracker:
|
12
|
-
|
14
|
+
#--
|
13
15
|
|
14
16
|
_instance = None
|
15
17
|
_lock = threading.Lock()
|
@@ -22,7 +24,7 @@ class Tracker:
|
|
22
24
|
return cls._instance
|
23
25
|
|
24
26
|
def _initialize(self):
|
25
|
-
|
27
|
+
#--
|
26
28
|
self.metrics = {
|
27
29
|
"startup_time": datetime.now().isoformat(),
|
28
30
|
"function_calls": 0,
|
@@ -39,7 +41,8 @@ class Tracker:
|
|
39
41
|
|
40
42
|
self.privacy_level = "standard"
|
41
43
|
|
42
|
-
|
44
|
+
##
|
45
|
+
|
43
46
|
self.home_dir = Path.home()
|
44
47
|
self.project_dir = self.home_dir / ".vnstock"
|
45
48
|
self.project_dir.mkdir(exist_ok=True)
|
@@ -48,26 +51,31 @@ class Tracker:
|
|
48
51
|
self.metrics_path = self.data_dir / "usage_metrics.json"
|
49
52
|
self.privacy_config_path = self.project_dir / 'config' / "privacy.json"
|
50
53
|
|
51
|
-
|
54
|
+
##
|
55
|
+
|
52
56
|
os.makedirs(os.path.dirname(self.privacy_config_path), exist_ok=True)
|
53
57
|
|
54
|
-
|
58
|
+
##
|
59
|
+
|
55
60
|
self._load_metrics()
|
56
61
|
|
57
|
-
|
62
|
+
##
|
63
|
+
|
58
64
|
self._load_privacy_settings()
|
59
65
|
|
60
|
-
|
66
|
+
##
|
67
|
+
|
61
68
|
self._start_background_collector()
|
62
69
|
|
63
70
|
def _load_metrics(self):
|
64
|
-
|
71
|
+
#--
|
65
72
|
if self.metrics_path.exists():
|
66
73
|
try:
|
67
74
|
with open(self.metrics_path, 'r') as f:
|
68
75
|
stored_metrics = json.load(f)
|
69
76
|
|
70
|
-
|
77
|
+
##
|
78
|
+
|
71
79
|
for key, value in stored_metrics.items():
|
72
80
|
if key in self.metrics:
|
73
81
|
self.metrics[key] = value
|
@@ -75,7 +83,7 @@ class Tracker:
|
|
75
83
|
pass
|
76
84
|
|
77
85
|
def _save_metrics(self):
|
78
|
-
|
86
|
+
#--
|
79
87
|
try:
|
80
88
|
with open(self.metrics_path, 'w') as f:
|
81
89
|
json.dump(self.metrics, f)
|
@@ -83,7 +91,7 @@ class Tracker:
|
|
83
91
|
pass
|
84
92
|
|
85
93
|
def _load_privacy_settings(self):
|
86
|
-
|
94
|
+
#--
|
87
95
|
if self.privacy_config_path.exists():
|
88
96
|
try:
|
89
97
|
with open(self.privacy_config_path, 'r') as f:
|
@@ -93,7 +101,7 @@ class Tracker:
|
|
93
101
|
pass
|
94
102
|
|
95
103
|
def setup_privacy(self, level=None):
|
96
|
-
|
104
|
+
#--
|
97
105
|
privacy_levels = {
|
98
106
|
"minimal": "Essential system data only",
|
99
107
|
"standard": "Performance metrics and errors",
|
@@ -101,90 +109,107 @@ class Tracker:
|
|
101
109
|
}
|
102
110
|
|
103
111
|
if level is None:
|
104
|
-
|
112
|
+
##
|
113
|
+
|
105
114
|
level = "standard"
|
106
115
|
|
107
116
|
if level not in privacy_levels:
|
108
117
|
raise ValueError(f"Invalid privacy level: {level}. Choose from {', '.join(privacy_levels.keys())}")
|
109
118
|
|
110
|
-
|
119
|
+
##
|
120
|
+
|
111
121
|
self.privacy_level = level
|
112
122
|
|
113
|
-
|
123
|
+
##
|
124
|
+
|
114
125
|
with open(self.privacy_config_path, "w") as f:
|
115
126
|
json.dump({"level": level}, f)
|
116
127
|
|
117
128
|
return level
|
118
129
|
|
119
130
|
def get_privacy_level(self):
|
120
|
-
|
131
|
+
#--
|
121
132
|
return self.privacy_level
|
122
133
|
|
123
134
|
def _start_background_collector(self):
|
124
|
-
|
135
|
+
#--
|
125
136
|
def collect_metrics():
|
126
137
|
while True:
|
127
138
|
try:
|
128
139
|
import psutil
|
129
140
|
|
130
|
-
|
141
|
+
##
|
142
|
+
|
131
143
|
current_process = psutil.Process()
|
132
144
|
memory_info = current_process.memory_info()
|
133
|
-
memory_usage = memory_info.rss / (1024 * 1024)
|
145
|
+
memory_usage = memory_info.rss / (1024 * 1024) ##
|
146
|
+
|
134
147
|
|
135
148
|
if memory_usage > self.performance_metrics["peak_memory"]:
|
136
149
|
self.performance_metrics["peak_memory"] = memory_usage
|
137
150
|
|
138
|
-
|
151
|
+
##
|
152
|
+
|
139
153
|
self._save_metrics()
|
140
154
|
|
141
155
|
except:
|
142
156
|
pass
|
143
157
|
|
144
|
-
time.sleep(300)
|
158
|
+
time.sleep(300) ##
|
159
|
+
|
145
160
|
|
146
|
-
|
161
|
+
##
|
162
|
+
|
147
163
|
thread = threading.Thread(target=collect_metrics, daemon=True)
|
148
164
|
thread.start()
|
149
165
|
|
150
166
|
def record(self, event_type, data=None):
|
151
|
-
|
152
|
-
|
167
|
+
#--
|
168
|
+
##
|
169
|
+
|
153
170
|
if self.privacy_level == "minimal" and event_type != "errors":
|
154
|
-
|
171
|
+
##
|
172
|
+
|
155
173
|
return True
|
156
174
|
|
157
|
-
|
175
|
+
##
|
176
|
+
|
158
177
|
if event_type in self.metrics:
|
159
178
|
self.metrics[event_type] += 1
|
160
179
|
else:
|
161
180
|
self.metrics[event_type] = 1
|
162
181
|
|
163
|
-
|
182
|
+
##
|
183
|
+
|
164
184
|
if event_type == "errors":
|
165
185
|
self.performance_metrics["last_error_time"] = datetime.now().isoformat()
|
166
186
|
|
167
|
-
|
187
|
+
##
|
188
|
+
|
168
189
|
if event_type == "function_calls" and data and "execution_time" in data:
|
169
|
-
|
190
|
+
##
|
191
|
+
|
170
192
|
self.performance_metrics["execution_times"].append(data["execution_time"])
|
171
193
|
if len(self.performance_metrics["execution_times"]) > 100:
|
172
194
|
self.performance_metrics["execution_times"] = self.performance_metrics["execution_times"][-100:]
|
173
195
|
|
174
|
-
|
196
|
+
##
|
197
|
+
|
175
198
|
if self.metrics["function_calls"] % 100 == 0 or event_type == "errors":
|
176
199
|
self._save_metrics()
|
177
200
|
|
178
201
|
return True
|
179
202
|
|
180
203
|
def get_metrics(self):
|
181
|
-
|
182
|
-
|
204
|
+
#--
|
205
|
+
##
|
206
|
+
|
183
207
|
avg_execution_time = 0
|
184
208
|
if self.performance_metrics["execution_times"]:
|
185
209
|
avg_execution_time = sum(self.performance_metrics["execution_times"]) / len(self.performance_metrics["execution_times"])
|
186
210
|
|
187
|
-
|
211
|
+
##
|
212
|
+
|
188
213
|
output = self.metrics.copy()
|
189
214
|
output.update({
|
190
215
|
"avg_execution_time": avg_execution_time,
|
@@ -196,7 +221,7 @@ class Tracker:
|
|
196
221
|
return output
|
197
222
|
|
198
223
|
def reset(self):
|
199
|
-
|
224
|
+
#--
|
200
225
|
self.metrics = {
|
201
226
|
"startup_time": datetime.now().isoformat(),
|
202
227
|
"function_calls": 0,
|
@@ -214,10 +239,11 @@ class Tracker:
|
|
214
239
|
self._save_metrics()
|
215
240
|
return True
|
216
241
|
|
217
|
-
|
242
|
+
##
|
243
|
+
|
218
244
|
tracker = Tracker()
|
219
245
|
|
220
246
|
|
221
247
|
def record(event_type, data=None):
|
222
|
-
|
248
|
+
#--
|
223
249
|
return tracker.record(event_type, data)
|
@@ -1,12 +1,12 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: vnai
|
3
|
-
Version: 2.0.
|
3
|
+
Version: 2.0.3
|
4
4
|
Summary: System optimization and resource management toolkit
|
5
5
|
Home-page: https://github.com/yourusername/vnai
|
6
6
|
Author: Your Name
|
7
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
|
@@ -24,6 +24,7 @@ Dynamic: classifier
|
|
24
24
|
Dynamic: description
|
25
25
|
Dynamic: description-content-type
|
26
26
|
Dynamic: home-page
|
27
|
+
Dynamic: license
|
27
28
|
Dynamic: provides-extra
|
28
29
|
Dynamic: requires-dist
|
29
30
|
Dynamic: requires-python
|
@@ -0,0 +1,16 @@
|
|
1
|
+
vnai/__init__.py,sha256=SF3HcEadrvSmtotBCy8a6637UwTFiSAaAN0Azi0X4qg,7219
|
2
|
+
vnai/beam/__init__.py,sha256=h19ZEQFnWTvqed0mpTcuQf-sT9XifWhfVbaobTEs91Q,131
|
3
|
+
vnai/beam/metrics.py,sha256=lNYEeav5kMm8SGnlsxwz6aD3fRzOytopHhUPkUx9Avs,5950
|
4
|
+
vnai/beam/pulse.py,sha256=-rN4tbcgNKmA74P2ThVkQqxabG0-UlhfRbFCyYPvKFw,2920
|
5
|
+
vnai/beam/quota.py,sha256=DRlqZpztppdFDJymuJS6VCKLHZrkI_PX8cUtStHDSFM,16934
|
6
|
+
vnai/flow/__init__.py,sha256=VW6R7c30M4q8PhOUqXyHwWlmk1BwPrYvcxtLFI0fWJo,91
|
7
|
+
vnai/flow/queue.py,sha256=0R6LjF6PSUz37JV2SnsOQMBHps3bG5c0BGfEOUIPhcA,3650
|
8
|
+
vnai/flow/relay.py,sha256=wIRojuZKQ5Jk1N-p2PkA9fkx-F7kwgVu0JIc0Iya5aw,13783
|
9
|
+
vnai/scope/__init__.py,sha256=yB0qWMlKd2ix5tFlBcRPX6SYR1O8Di0mwgQC15u8l2o,207
|
10
|
+
vnai/scope/profile.py,sha256=tIy39_FpcNKZCg3Dy5mgy0jdLQCH2FK2nfvUlTM72wM,26781
|
11
|
+
vnai/scope/promo.py,sha256=NlKcyadl6BlOr2TMlKkdri4dkm8xIoI_3Z05ErcVnGo,9930
|
12
|
+
vnai/scope/state.py,sha256=XUhuXNx1W6pce5vRY3IkSrR__MGetRo8lQt1bQIAOLM,6550
|
13
|
+
vnai-2.0.3.dist-info/METADATA,sha256=IlnWkYA8m9Rxjyfu7JCgpwJw0C7ldherJqhQnAdRrug,1017
|
14
|
+
vnai-2.0.3.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
|
15
|
+
vnai-2.0.3.dist-info/top_level.txt,sha256=4zI0qZHePCwvgSqXl4420sBcd0VzZn4MEcRsAIFae3k,5
|
16
|
+
vnai-2.0.3.dist-info/RECORD,,
|
vnai-2.0.1.dist-info/RECORD
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
vnai/__init__.py,sha256=iqCNvUVrP6JVFk5jBnCLpVyZdBSZkcfkzu64JNEijis,8895
|
2
|
-
vnai/beam/__init__.py,sha256=xKb_iu9aAPXCulI7dENrvqVIhelSD1mIqKE9Go3GAHw,200
|
3
|
-
vnai/beam/metrics.py,sha256=xVmVw93yhKeWzRZJurmrD9mWur16HyLJl_p1XqMwW_w,7187
|
4
|
-
vnai/beam/pulse.py,sha256=jp1YwjLaMhne2nYhM5PofveDsdrSp2YtewQ2jjE78Is,3470
|
5
|
-
vnai/beam/quota.py,sha256=I2rUC3z5s5ni9yTU8Vj7mpMA2uPGMT64s9PwbJUsr7s,20798
|
6
|
-
vnai/flow/__init__.py,sha256=K3OeabzAWGrdPgTAOlDqrJh2y9aQW2pgLZg8tblN3ho,147
|
7
|
-
vnai/flow/queue.py,sha256=b9YKUbiXDZRC3fVgEnA77EO0EMXAi8eCoBkHnAUI5Sc,4162
|
8
|
-
vnai/flow/relay.py,sha256=RtIPRZ3BlQd-XgTbisJg0iC1HqikAjHGyyo8aTj_fUw,15766
|
9
|
-
vnai/scope/__init__.py,sha256=overJZ_UiEfBRNcSieE1GPU_9X3oS4C5l6JeBaFFVxk,267
|
10
|
-
vnai/scope/profile.py,sha256=xKEqDAaeZvRZMn1YK8qS6ILz7DRYxRkd_IJxLm7O-cs,30738
|
11
|
-
vnai/scope/promo.py,sha256=bIVok3eW3GXGGu-OdDeMggrvC_JfpT6blYVJuj35k7s,11031
|
12
|
-
vnai/scope/state.py,sha256=LlcZNKBy2mcAnD765BO2Tlv3Zzbak2TOEz4RUPMCFZ8,7490
|
13
|
-
vnai-2.0.1.dist-info/METADATA,sha256=9gyeWPMPAoIUmQPeeyow2USwrGO3Ir8Q3ivMNalh40o,1038
|
14
|
-
vnai-2.0.1.dist-info/WHEEL,sha256=tTnHoFhvKQHCh4jz3yCn0WPTYIy7wXx3CJtJ7SJGV7c,91
|
15
|
-
vnai-2.0.1.dist-info/top_level.txt,sha256=4zI0qZHePCwvgSqXl4420sBcd0VzZn4MEcRsAIFae3k,5
|
16
|
-
vnai-2.0.1.dist-info/RECORD,,
|
File without changes
|