vnai 2.1.7__py3-none-any.whl → 2.1.8__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/state.py CHANGED
@@ -1,155 +1,222 @@
1
- import time
2
- import threading
3
- import json
4
- import os
5
- from datetime import datetime
6
- from pathlib import Path
7
-
8
- class Tracker:
9
- _instance = None
10
- _lock = threading.Lock()
11
-
12
- def __new__(cls):
13
- with cls._lock:
14
- if cls._instance is None:
15
- cls._instance = super(Tracker, cls).__new__(cls)
16
- cls._instance._initialize()
17
- return cls._instance
18
-
19
- def _initialize(self):
20
- self.metrics = {
21
- "startup_time": datetime.now().isoformat(),
22
- "function_calls": 0,
23
- "api_requests": 0,
24
- "errors": 0,
25
- "warnings": 0
26
- }
27
- self.performance_metrics = {
28
- "execution_times": [],
29
- "last_error_time": None,
30
- "peak_memory": 0
31
- }
32
- self.privacy_level ="standard"
33
- self.home_dir = Path.home()
34
- self.project_dir = self.home_dir /".vnstock"
35
- self.project_dir.mkdir(exist_ok=True)
36
- self.data_dir = self.project_dir /'data'
37
- self.data_dir.mkdir(exist_ok=True)
38
- self.metrics_path = self.data_dir /"usage_metrics.json"
39
- self.privacy_config_path = self.project_dir /'config' /"privacy.json"
40
- os.makedirs(os.path.dirname(self.privacy_config_path), exist_ok=True)
41
- self._load_metrics()
42
- self._load_privacy_settings()
43
- self._start_background_collector()
44
-
45
- def _load_metrics(self):
46
- if self.metrics_path.exists():
47
- try:
48
- with open(self.metrics_path,'r') as f:
49
- stored_metrics = json.load(f)
50
- for key, value in stored_metrics.items():
51
- if key in self.metrics:
52
- self.metrics[key] = value
53
- except:
54
- pass
55
-
56
- def _save_metrics(self):
57
- try:
58
- with open(self.metrics_path,'w') as f:
59
- json.dump(self.metrics, f)
60
- except:
61
- pass
62
-
63
- def _load_privacy_settings(self):
64
- if self.privacy_config_path.exists():
65
- try:
66
- with open(self.privacy_config_path,'r') as f:
67
- settings = json.load(f)
68
- self.privacy_level = settings.get("level","standard")
69
- except:
70
- pass
71
-
72
- def setup_privacy(self, level=None):
73
- privacy_levels = {
74
- "minimal":"Essential system data only",
75
- "standard":"Performance metrics and errors",
76
- "enhanced":"Detailed operation analytics"
77
- }
78
- if level is None:
79
- level ="standard"
80
- if level not in privacy_levels:
81
- raise ValueError(f"Invalid privacy level: {level}. Choose from {', '.join(privacy_levels.keys())}")
82
- self.privacy_level = level
83
- with open(self.privacy_config_path,"w") as f:
84
- json.dump({"level": level}, f)
85
- return level
86
-
87
- def get_privacy_level(self):
88
- return self.privacy_level
89
-
90
- def _start_background_collector(self):
91
- def collect_metrics():
92
- while True:
93
- try:
94
- import psutil
95
- current_process = psutil.Process()
96
- memory_info = current_process.memory_info()
97
- memory_usage = memory_info.rss / (1024 * 1024)
98
- if memory_usage > self.performance_metrics["peak_memory"]:
99
- self.performance_metrics["peak_memory"] = memory_usage
100
- self._save_metrics()
101
- except:
102
- pass
103
- time.sleep(300)
104
- thread = threading.Thread(target=collect_metrics, daemon=True)
105
- thread.start()
106
-
107
- def record(self, event_type, data=None):
108
- if self.privacy_level =="minimal" and event_type !="errors":
109
- return True
110
- if event_type in self.metrics:
111
- self.metrics[event_type] += 1
112
- else:
113
- self.metrics[event_type] = 1
114
- if event_type =="errors":
115
- self.performance_metrics["last_error_time"] = datetime.now().isoformat()
116
- if event_type =="function_calls" and data and"execution_time" in data:
117
- self.performance_metrics["execution_times"].append(data["execution_time"])
118
- if len(self.performance_metrics["execution_times"]) > 100:
119
- self.performance_metrics["execution_times"] = self.performance_metrics["execution_times"][-100:]
120
- if self.metrics["function_calls"] % 100 == 0 or event_type =="errors":
121
- self._save_metrics()
122
- return True
123
-
124
- def get_metrics(self):
125
- avg_execution_time = 0
126
- if self.performance_metrics["execution_times"]:
127
- avg_execution_time = sum(self.performance_metrics["execution_times"]) / len(self.performance_metrics["execution_times"])
128
- output = self.metrics.copy()
129
- output.update({
130
- "avg_execution_time": avg_execution_time,
131
- "peak_memory_mb": self.performance_metrics["peak_memory"],
132
- "uptime": (datetime.now() - datetime.fromisoformat(self.metrics["startup_time"])).total_seconds(),
133
- "privacy_level": self.privacy_level
134
- })
135
- return output
136
-
137
- def reset(self):
138
- self.metrics = {
139
- "startup_time": datetime.now().isoformat(),
140
- "function_calls": 0,
141
- "api_requests": 0,
142
- "errors": 0,
143
- "warnings": 0
144
- }
145
- self.performance_metrics = {
146
- "execution_times": [],
147
- "last_error_time": None,
148
- "peak_memory": 0
149
- }
150
- self._save_metrics()
151
- return True
152
- tracker = Tracker()
153
-
154
- def record(event_type, data=None):
155
- return tracker.record(event_type, data)
1
+ # vnai/scope/state.py
2
+
3
+ import time
4
+ import threading
5
+ import json
6
+ import os
7
+ from datetime import datetime
8
+ from pathlib import Path
9
+
10
+ class Tracker:
11
+ """Tracks system state and performance metrics"""
12
+
13
+ _instance = None
14
+ _lock = threading.Lock()
15
+
16
+ def __new__(cls):
17
+ with cls._lock:
18
+ if cls._instance is None:
19
+ cls._instance = super(Tracker, cls).__new__(cls)
20
+ cls._instance._initialize()
21
+ return cls._instance
22
+
23
+ def _initialize(self):
24
+ """Initialize tracker"""
25
+ self.metrics = {
26
+ "startup_time": datetime.now().isoformat(),
27
+ "function_calls": 0,
28
+ "api_requests": 0,
29
+ "errors": 0,
30
+ "warnings": 0
31
+ }
32
+
33
+ self.performance_metrics = {
34
+ "execution_times": [],
35
+ "last_error_time": None,
36
+ "peak_memory": 0
37
+ }
38
+
39
+ self.privacy_level = "standard"
40
+
41
+ # Setup data directory
42
+ self.home_dir = Path.home()
43
+ self.project_dir = self.home_dir / ".vnstock"
44
+ self.project_dir.mkdir(exist_ok=True)
45
+ self.data_dir = self.project_dir / 'data'
46
+ self.data_dir.mkdir(exist_ok=True)
47
+ self.metrics_path = self.data_dir / "usage_metrics.json"
48
+ self.privacy_config_path = self.project_dir / 'config' / "privacy.json"
49
+
50
+ # Create config directory if it doesn't exist
51
+ os.makedirs(os.path.dirname(self.privacy_config_path), exist_ok=True)
52
+
53
+ # Load existing metrics
54
+ self._load_metrics()
55
+
56
+ # Load privacy settings
57
+ self._load_privacy_settings()
58
+
59
+ # Start background metrics collector
60
+ self._start_background_collector()
61
+
62
+ def _load_metrics(self):
63
+ """Load metrics from file"""
64
+ if self.metrics_path.exists():
65
+ try:
66
+ with open(self.metrics_path, 'r') as f:
67
+ stored_metrics = json.load(f)
68
+
69
+ # Update metrics with stored values
70
+ for key, value in stored_metrics.items():
71
+ if key in self.metrics:
72
+ self.metrics[key] = value
73
+ except:
74
+ pass
75
+
76
+ def _save_metrics(self):
77
+ """Save metrics to file"""
78
+ try:
79
+ with open(self.metrics_path, 'w') as f:
80
+ json.dump(self.metrics, f)
81
+ except:
82
+ pass
83
+
84
+ def _load_privacy_settings(self):
85
+ """Load privacy settings"""
86
+ if self.privacy_config_path.exists():
87
+ try:
88
+ with open(self.privacy_config_path, 'r') as f:
89
+ settings = json.load(f)
90
+ self.privacy_level = settings.get("level", "standard")
91
+ except:
92
+ pass
93
+
94
+ def setup_privacy(self, level=None):
95
+ """Configure privacy level for data collection"""
96
+ privacy_levels = {
97
+ "minimal": "Essential system data only",
98
+ "standard": "Performance metrics and errors",
99
+ "enhanced": "Detailed operation analytics"
100
+ }
101
+
102
+ if level is None:
103
+ # Default level
104
+ level = "standard"
105
+
106
+ if level not in privacy_levels:
107
+ raise ValueError(f"Invalid privacy level: {level}. Choose from {', '.join(privacy_levels.keys())}")
108
+
109
+ # Store preference
110
+ self.privacy_level = level
111
+
112
+ # Store in configuration file
113
+ with open(self.privacy_config_path, "w") as f:
114
+ json.dump({"level": level}, f)
115
+
116
+ return level
117
+
118
+ def get_privacy_level(self):
119
+ """Get current privacy level"""
120
+ return self.privacy_level
121
+
122
+ def _start_background_collector(self):
123
+ """Start background metrics collection"""
124
+ def collect_metrics():
125
+ while True:
126
+ try:
127
+ import psutil
128
+
129
+ # Update peak memory
130
+ current_process = psutil.Process()
131
+ memory_info = current_process.memory_info()
132
+ memory_usage = memory_info.rss / (1024 * 1024) # MB
133
+
134
+ if memory_usage > self.performance_metrics["peak_memory"]:
135
+ self.performance_metrics["peak_memory"] = memory_usage
136
+
137
+ # Save metrics periodically
138
+ self._save_metrics()
139
+
140
+ except:
141
+ pass
142
+
143
+ time.sleep(300) # Run every 5 minutes
144
+
145
+ # Start thread
146
+ thread = threading.Thread(target=collect_metrics, daemon=True)
147
+ thread.start()
148
+
149
+ def record(self, event_type, data=None):
150
+ """Record an event"""
151
+ # Check privacy level
152
+ if self.privacy_level == "minimal" and event_type != "errors":
153
+ # In minimal mode, only track errors
154
+ return True
155
+
156
+ # Update counts
157
+ if event_type in self.metrics:
158
+ self.metrics[event_type] += 1
159
+ else:
160
+ self.metrics[event_type] = 1
161
+
162
+ # Special handling for errors
163
+ if event_type == "errors":
164
+ self.performance_metrics["last_error_time"] = datetime.now().isoformat()
165
+
166
+ # Special handling for function calls with timing data
167
+ if event_type == "function_calls" and data and "execution_time" in data:
168
+ # Keep up to 100 latest execution times
169
+ self.performance_metrics["execution_times"].append(data["execution_time"])
170
+ if len(self.performance_metrics["execution_times"]) > 100:
171
+ self.performance_metrics["execution_times"] = self.performance_metrics["execution_times"][-100:]
172
+
173
+ # Save if metrics change significantly
174
+ if self.metrics["function_calls"] % 100 == 0 or event_type == "errors":
175
+ self._save_metrics()
176
+
177
+ return True
178
+
179
+ def get_metrics(self):
180
+ """Get current metrics"""
181
+ # Calculate derived metrics
182
+ avg_execution_time = 0
183
+ if self.performance_metrics["execution_times"]:
184
+ avg_execution_time = sum(self.performance_metrics["execution_times"]) / len(self.performance_metrics["execution_times"])
185
+
186
+ # Add derived metrics to output
187
+ output = self.metrics.copy()
188
+ output.update({
189
+ "avg_execution_time": avg_execution_time,
190
+ "peak_memory_mb": self.performance_metrics["peak_memory"],
191
+ "uptime": (datetime.now() - datetime.fromisoformat(self.metrics["startup_time"])).total_seconds(),
192
+ "privacy_level": self.privacy_level
193
+ })
194
+
195
+ return output
196
+
197
+ def reset(self):
198
+ """Reset metrics"""
199
+ self.metrics = {
200
+ "startup_time": datetime.now().isoformat(),
201
+ "function_calls": 0,
202
+ "api_requests": 0,
203
+ "errors": 0,
204
+ "warnings": 0
205
+ }
206
+
207
+ self.performance_metrics = {
208
+ "execution_times": [],
209
+ "last_error_time": None,
210
+ "peak_memory": 0
211
+ }
212
+
213
+ self._save_metrics()
214
+ return True
215
+
216
+ # Create singleton instance
217
+ tracker = Tracker()
218
+
219
+
220
+ def record(event_type, data=None):
221
+ """Record an event"""
222
+ return tracker.record(event_type, data)
@@ -1,20 +1,20 @@
1
- Metadata-Version: 2.4
2
- Name: vnai
3
- Version: 2.1.7
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
1
+ Metadata-Version: 2.4
2
+ Name: vnai
3
+ Version: 2.1.8
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=fZQKQSpvzFX9aum8kjJyZieGQnmEzWIbzLLgpaQvVQM,7996
2
+ vnai/beam/__init__.py,sha256=Ibfpu8ulgVw1E6ew5kaE1Z69V6mGxwYy6SRa0-DFivk,156
3
+ vnai/beam/metrics.py,sha256=TEBgrwrJbL7D3dlBVo9qdq9qEgqQKXef_otNMXqwm6E,8606
4
+ vnai/beam/pulse.py,sha256=SuzA_ZL_FGEHFNrLZOvXbSJSKn8pGsehNwmaADw9DyY,3427
5
+ vnai/beam/quota.py,sha256=dTbtOP82XSzLaNksPlW-2qnrnQgyvMI8KAH3GKPPQqE,21363
6
+ vnai/flow/__init__.py,sha256=xKOTxRtAkDekfJaQtx-zN1-5pxQdF_oAEcsK-DXGM2k,136
7
+ vnai/flow/queue.py,sha256=KcA20u-WiEPVV-knburw86t6ynuKXsv_Kwd-gJE5zT0,4138
8
+ vnai/flow/relay.py,sha256=Ar_GlGhUvTU1w8ByAMxKGjh6468MXTYY0haAGi4WKnE,16647
9
+ vnai/scope/__init__.py,sha256=overJZ_UiEfBRNcSieE1GPU_9X3oS4C5l6JeBaFFVxk,267
10
+ vnai/scope/profile.py,sha256=5DKB8_ImpAruJQ0V_jPs98PVZ1uyr0QyN3zjBbUfPSI,30706
11
+ vnai/scope/promo.py,sha256=EjdzmWuKozSauzcZo7C4K0OAMK7YOj49L1hwOhoezqE,16841
12
+ vnai/scope/state.py,sha256=7u-jH3TKXFo7Y5vUZUMhRM1_2YA9wXuHIat0rvhFgBc,7466
13
+ vnai-2.1.8.dist-info/METADATA,sha256=XpGL3ogyO6rZ9sLg8xi1axISrzZ2boCQ6cPW32Ly2qI,662
14
+ vnai-2.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
+ vnai-2.1.8.dist-info/top_level.txt,sha256=4zI0qZHePCwvgSqXl4420sBcd0VzZn4MEcRsAIFae3k,5
16
+ vnai-2.1.8.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- vnai/__init__.py,sha256=IPw89g9Ar7TnXHXq9YVU2Sa1EyCgP-udw7Qbfpi95UU,6226
2
- vnai/beam/__init__.py,sha256=Of7ydx35u4gTOBCYXxDwTfDAZVyIpbds09dXX0hJh-w,133
3
- vnai/beam/metrics.py,sha256=p0WzO1a5MvXm98KyyshLzB4FCk-5ERh7JN65IxVB0I0,6441
4
- vnai/beam/pulse.py,sha256=WTdjJ8mr2fvtPEZcoyzVO9Nv8jt2QPCjOZjCh7CB4Ww,2563
5
- vnai/beam/quota.py,sha256=6DQdA7qwft1VWsscjpxUGyA59PEGmUY2mnGomj2aDRE,14748
6
- vnai/flow/__init__.py,sha256=d96OtNAJeYEYYW_3ZZXbGh8NWbVK3cd78lsub9m9--Q,82
7
- vnai/flow/queue.py,sha256=LBuaiAdfaOfbOL_1oxapEKlNav7qGdUk8BQdfJTxMyA,3322
8
- vnai/flow/relay.py,sha256=e7H_MSNm0AYwDeY0AeHCptl2vuD1NCRUvmsGWNmQK2c,13515
9
- vnai/scope/__init__.py,sha256=VVFWdhAVGYJY-4CykgyhjsqoL17WlbRjVk3CZYAN7S4,200
10
- vnai/scope/profile.py,sha256=R_xM5DyDEZ6ju9CwTAv_iXDHx4Dhqd7b1lCeAmlj-lc,22145
11
- vnai/scope/promo.py,sha256=lnoZJL5smBc1SF49bkCMMCrgzv5NnrIIAMbSqyTGmYI,13003
12
- vnai/scope/state.py,sha256=Y8eZNVtG31E7Jv-RtHdDLkRRKbfCK8czbbyKp65065k,5543
13
- vnai-2.1.7.dist-info/METADATA,sha256=Gw9R_X7XNv055XKhXZeHKOhstdtfBT88greichRFK9w,682
14
- vnai-2.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
- vnai-2.1.7.dist-info/top_level.txt,sha256=4zI0qZHePCwvgSqXl4420sBcd0VzZn4MEcRsAIFae3k,5
16
- vnai-2.1.7.dist-info/RECORD,,
File without changes