tree-sitter-analyzer 0.1.0__py3-none-any.whl → 0.1.1__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.
Potentially problematic release.
This version of tree-sitter-analyzer might be problematic. Click here for more details.
- tree_sitter_analyzer/interfaces/cli.py +1 -1
- tree_sitter_analyzer/mcp/server.py +45 -8
- tree_sitter_analyzer/utils.py +98 -22
- {tree_sitter_analyzer-0.1.0.dist-info → tree_sitter_analyzer-0.1.1.dist-info}/METADATA +1 -1
- {tree_sitter_analyzer-0.1.0.dist-info → tree_sitter_analyzer-0.1.1.dist-info}/RECORD +7 -7
- tree_sitter_analyzer-0.1.1.dist-info/entry_points.txt +8 -0
- tree_sitter_analyzer-0.1.0.dist-info/entry_points.txt +0 -8
- {tree_sitter_analyzer-0.1.0.dist-info → tree_sitter_analyzer-0.1.1.dist-info}/WHEEL +0 -0
|
@@ -51,7 +51,7 @@ Examples:
|
|
|
51
51
|
# Get framework information
|
|
52
52
|
tree-sitter-analyzer info
|
|
53
53
|
|
|
54
|
-
For more information, visit: https://github.com/
|
|
54
|
+
For more information, visit: https://github.com/aimasteracc/tree-sitter-analyzer
|
|
55
55
|
"""
|
|
56
56
|
)
|
|
57
57
|
|
|
@@ -209,7 +209,10 @@ class TreeSitterAnalyzerMCPServer:
|
|
|
209
209
|
raise ValueError(f"Unknown tool: {name}")
|
|
210
210
|
|
|
211
211
|
except Exception as e:
|
|
212
|
-
|
|
212
|
+
try:
|
|
213
|
+
logger.error(f"Tool call error for {name}: {e}")
|
|
214
|
+
except (ValueError, OSError):
|
|
215
|
+
pass # Silently ignore logging errors during shutdown
|
|
213
216
|
return [
|
|
214
217
|
TextContent(
|
|
215
218
|
type="text",
|
|
@@ -258,11 +261,17 @@ class TreeSitterAnalyzerMCPServer:
|
|
|
258
261
|
raise ValueError(f"Resource not found: {uri}")
|
|
259
262
|
|
|
260
263
|
except Exception as e:
|
|
261
|
-
|
|
264
|
+
try:
|
|
265
|
+
logger.error(f"Resource read error for {uri}: {e}")
|
|
266
|
+
except (ValueError, OSError):
|
|
267
|
+
pass # Silently ignore logging errors during shutdown
|
|
262
268
|
raise
|
|
263
269
|
|
|
264
270
|
self.server = server
|
|
265
|
-
|
|
271
|
+
try:
|
|
272
|
+
logger.info("MCP server created successfully")
|
|
273
|
+
except (ValueError, OSError):
|
|
274
|
+
pass # Silently ignore logging errors during shutdown
|
|
266
275
|
return server
|
|
267
276
|
|
|
268
277
|
def set_project_path(self, project_path: str) -> None:
|
|
@@ -273,7 +282,10 @@ class TreeSitterAnalyzerMCPServer:
|
|
|
273
282
|
project_path: Path to the project directory
|
|
274
283
|
"""
|
|
275
284
|
self.project_stats_resource.set_project_path(project_path)
|
|
276
|
-
|
|
285
|
+
try:
|
|
286
|
+
logger.info(f"Set project path to: {project_path}")
|
|
287
|
+
except (ValueError, OSError):
|
|
288
|
+
pass # Silently ignore logging errors during shutdown
|
|
277
289
|
|
|
278
290
|
async def run(self) -> None:
|
|
279
291
|
"""
|
|
@@ -293,14 +305,27 @@ class TreeSitterAnalyzerMCPServer:
|
|
|
293
305
|
capabilities=MCP_INFO["capabilities"],
|
|
294
306
|
)
|
|
295
307
|
|
|
296
|
-
|
|
308
|
+
try:
|
|
309
|
+
logger.info(f"Starting MCP server: {self.name} v{self.version}")
|
|
310
|
+
except (ValueError, OSError):
|
|
311
|
+
pass # Silently ignore logging errors during shutdown
|
|
297
312
|
|
|
298
313
|
try:
|
|
299
314
|
async with stdio_server() as (read_stream, write_stream):
|
|
300
315
|
await server.run(read_stream, write_stream, options)
|
|
301
316
|
except Exception as e:
|
|
302
|
-
|
|
317
|
+
# Use safe logging to avoid I/O errors during shutdown
|
|
318
|
+
try:
|
|
319
|
+
logger.error(f"Server error: {e}")
|
|
320
|
+
except (ValueError, OSError):
|
|
321
|
+
pass # Silently ignore logging errors during shutdown
|
|
303
322
|
raise
|
|
323
|
+
finally:
|
|
324
|
+
# Safe cleanup
|
|
325
|
+
try:
|
|
326
|
+
logger.info("MCP server shutting down")
|
|
327
|
+
except (ValueError, OSError):
|
|
328
|
+
pass # Silently ignore logging errors during shutdown
|
|
304
329
|
|
|
305
330
|
|
|
306
331
|
async def main() -> None:
|
|
@@ -309,10 +334,22 @@ async def main() -> None:
|
|
|
309
334
|
server = TreeSitterAnalyzerMCPServer()
|
|
310
335
|
await server.run()
|
|
311
336
|
except KeyboardInterrupt:
|
|
312
|
-
|
|
337
|
+
try:
|
|
338
|
+
logger.info("Server stopped by user")
|
|
339
|
+
except (ValueError, OSError):
|
|
340
|
+
pass # Silently ignore logging errors during shutdown
|
|
313
341
|
except Exception as e:
|
|
314
|
-
|
|
342
|
+
try:
|
|
343
|
+
logger.error(f"Server failed: {e}")
|
|
344
|
+
except (ValueError, OSError):
|
|
345
|
+
pass # Silently ignore logging errors during shutdown
|
|
315
346
|
sys.exit(1)
|
|
347
|
+
finally:
|
|
348
|
+
# Ensure clean shutdown
|
|
349
|
+
try:
|
|
350
|
+
logger.info("MCP server shutdown complete")
|
|
351
|
+
except (ValueError, OSError):
|
|
352
|
+
pass # Silently ignore logging errors during shutdown
|
|
316
353
|
|
|
317
354
|
|
|
318
355
|
if __name__ == "__main__":
|
tree_sitter_analyzer/utils.py
CHANGED
|
@@ -8,6 +8,7 @@ Provides logging, debugging, and common utility functions.
|
|
|
8
8
|
|
|
9
9
|
import logging
|
|
10
10
|
import sys
|
|
11
|
+
import atexit
|
|
11
12
|
from functools import wraps
|
|
12
13
|
from typing import Any, Optional
|
|
13
14
|
|
|
@@ -33,7 +34,8 @@ def setup_logger(
|
|
|
33
34
|
logger = logging.getLogger(name)
|
|
34
35
|
|
|
35
36
|
if not logger.handlers: # Avoid duplicate handlers
|
|
36
|
-
handler
|
|
37
|
+
# Create a safe handler that won't fail on closed streams
|
|
38
|
+
handler = SafeStreamHandler(sys.stdout)
|
|
37
39
|
formatter = logging.Formatter(
|
|
38
40
|
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
39
41
|
)
|
|
@@ -44,28 +46,97 @@ def setup_logger(
|
|
|
44
46
|
return logger
|
|
45
47
|
|
|
46
48
|
|
|
49
|
+
class SafeStreamHandler(logging.StreamHandler):
|
|
50
|
+
"""
|
|
51
|
+
A StreamHandler that safely handles closed streams
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def emit(self, record):
|
|
55
|
+
"""
|
|
56
|
+
Emit a record, safely handling closed streams
|
|
57
|
+
"""
|
|
58
|
+
try:
|
|
59
|
+
# Check if stream is closed before writing
|
|
60
|
+
if hasattr(self.stream, 'closed') and self.stream.closed:
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
# Check if we can write to the stream
|
|
64
|
+
if not hasattr(self.stream, 'write'):
|
|
65
|
+
return
|
|
66
|
+
|
|
67
|
+
super().emit(record)
|
|
68
|
+
except (ValueError, OSError, AttributeError):
|
|
69
|
+
# Silently ignore I/O errors during shutdown
|
|
70
|
+
pass
|
|
71
|
+
except Exception:
|
|
72
|
+
# For any other unexpected errors, use handleError
|
|
73
|
+
self.handleError(record)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def setup_safe_logging_shutdown():
|
|
77
|
+
"""
|
|
78
|
+
Setup safe logging shutdown to prevent I/O errors
|
|
79
|
+
"""
|
|
80
|
+
def cleanup_logging():
|
|
81
|
+
"""Clean up logging handlers safely"""
|
|
82
|
+
try:
|
|
83
|
+
# Get all loggers
|
|
84
|
+
loggers = [logging.getLogger()] + [
|
|
85
|
+
logging.getLogger(name) for name in logging.Logger.manager.loggerDict
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
for logger in loggers:
|
|
89
|
+
for handler in logger.handlers[:]:
|
|
90
|
+
try:
|
|
91
|
+
handler.close()
|
|
92
|
+
logger.removeHandler(handler)
|
|
93
|
+
except:
|
|
94
|
+
pass
|
|
95
|
+
except:
|
|
96
|
+
pass
|
|
97
|
+
|
|
98
|
+
# Register cleanup function
|
|
99
|
+
atexit.register(cleanup_logging)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# Setup safe shutdown on import
|
|
103
|
+
setup_safe_logging_shutdown()
|
|
104
|
+
|
|
105
|
+
|
|
47
106
|
# Global logger instance
|
|
48
107
|
logger = setup_logger()
|
|
49
108
|
|
|
50
109
|
|
|
51
110
|
def log_info(message: str, *args: Any, **kwargs: Any) -> None:
|
|
52
111
|
"""Log info message"""
|
|
53
|
-
|
|
112
|
+
try:
|
|
113
|
+
logger.info(message, *args, **kwargs)
|
|
114
|
+
except (ValueError, OSError):
|
|
115
|
+
pass # Silently ignore I/O errors
|
|
54
116
|
|
|
55
117
|
|
|
56
118
|
def log_warning(message: str, *args: Any, **kwargs: Any) -> None:
|
|
57
119
|
"""Log warning message"""
|
|
58
|
-
|
|
120
|
+
try:
|
|
121
|
+
logger.warning(message, *args, **kwargs)
|
|
122
|
+
except (ValueError, OSError):
|
|
123
|
+
pass # Silently ignore I/O errors
|
|
59
124
|
|
|
60
125
|
|
|
61
126
|
def log_error(message: str, *args: Any, **kwargs: Any) -> None:
|
|
62
127
|
"""Log error message"""
|
|
63
|
-
|
|
128
|
+
try:
|
|
129
|
+
logger.error(message, *args, **kwargs)
|
|
130
|
+
except (ValueError, OSError):
|
|
131
|
+
pass # Silently ignore I/O errors
|
|
64
132
|
|
|
65
133
|
|
|
66
134
|
def log_debug(message: str, *args: Any, **kwargs: Any) -> None:
|
|
67
135
|
"""Log debug message"""
|
|
68
|
-
|
|
136
|
+
try:
|
|
137
|
+
logger.debug(message, *args, **kwargs)
|
|
138
|
+
except (ValueError, OSError):
|
|
139
|
+
pass # Silently ignore I/O errors
|
|
69
140
|
|
|
70
141
|
|
|
71
142
|
def suppress_output(func: Any) -> Any:
|
|
@@ -79,14 +150,16 @@ def suppress_output(func: Any) -> Any:
|
|
|
79
150
|
|
|
80
151
|
# Redirect stdout to suppress prints
|
|
81
152
|
old_stdout = sys.stdout
|
|
82
|
-
sys.stdout = (
|
|
83
|
-
open("/dev/null", "w") if sys.platform != "win32" else open("nul", "w")
|
|
84
|
-
)
|
|
85
|
-
|
|
86
153
|
try:
|
|
154
|
+
sys.stdout = (
|
|
155
|
+
open("/dev/null", "w") if sys.platform != "win32" else open("nul", "w")
|
|
156
|
+
)
|
|
87
157
|
result = func(*args, **kwargs)
|
|
88
158
|
finally:
|
|
89
|
-
|
|
159
|
+
try:
|
|
160
|
+
sys.stdout.close()
|
|
161
|
+
except:
|
|
162
|
+
pass
|
|
90
163
|
sys.stdout = old_stdout
|
|
91
164
|
|
|
92
165
|
return result
|
|
@@ -133,7 +206,7 @@ def create_performance_logger(name: str) -> logging.Logger:
|
|
|
133
206
|
perf_logger = logging.getLogger(f"{name}.performance")
|
|
134
207
|
|
|
135
208
|
if not perf_logger.handlers:
|
|
136
|
-
handler =
|
|
209
|
+
handler = SafeStreamHandler()
|
|
137
210
|
formatter = logging.Formatter("%(asctime)s - PERF - %(message)s")
|
|
138
211
|
handler.setFormatter(formatter)
|
|
139
212
|
perf_logger.addHandler(handler)
|
|
@@ -152,16 +225,19 @@ def log_performance(
|
|
|
152
225
|
details: Optional[dict] = None,
|
|
153
226
|
) -> None:
|
|
154
227
|
"""Log performance metrics"""
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
228
|
+
try:
|
|
229
|
+
message = f"{operation}"
|
|
230
|
+
if execution_time is not None:
|
|
231
|
+
message += f": {execution_time:.4f}s"
|
|
232
|
+
if details:
|
|
233
|
+
if isinstance(details, dict):
|
|
234
|
+
detail_str = ", ".join([f"{k}: {v}" for k, v in details.items()])
|
|
235
|
+
else:
|
|
236
|
+
detail_str = str(details)
|
|
237
|
+
message += f" - {detail_str}"
|
|
238
|
+
perf_logger.info(message)
|
|
239
|
+
except (ValueError, OSError):
|
|
240
|
+
pass # Silently ignore I/O errors
|
|
165
241
|
|
|
166
242
|
|
|
167
243
|
def setup_performance_logger() -> logging.Logger:
|
|
@@ -170,7 +246,7 @@ def setup_performance_logger() -> logging.Logger:
|
|
|
170
246
|
|
|
171
247
|
# Add handler if not already configured
|
|
172
248
|
if not perf_logger.handlers:
|
|
173
|
-
handler =
|
|
249
|
+
handler = SafeStreamHandler()
|
|
174
250
|
formatter = logging.Formatter("%(asctime)s - Performance - %(message)s")
|
|
175
251
|
handler.setFormatter(formatter)
|
|
176
252
|
perf_logger.addHandler(handler)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tree-sitter-analyzer
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: Extensible multi-language code analyzer framework using Tree-sitter with dynamic plugin architecture
|
|
5
5
|
Project-URL: Homepage, https://github.com/aimasteracc/tree-sitter-analyzer
|
|
6
6
|
Project-URL: Documentation, https://github.com/aimasteracc/tree-sitter-analyzer#readme
|
|
@@ -12,7 +12,7 @@ tree_sitter_analyzer/models.py,sha256=2JZAQXM4nJVu7rfnsZFwpvPpv8fpk0POVHKCKeOMLM
|
|
|
12
12
|
tree_sitter_analyzer/output_manager.py,sha256=dh_yfAmvn-XuF7RP5DM5vnqHGRzBUDOsuiVvTjcaOwg,8769
|
|
13
13
|
tree_sitter_analyzer/query_loader.py,sha256=KrpNnf-plrtymDAfUF6ukw8ELtGWnqhikwPLW_z9vY8,10225
|
|
14
14
|
tree_sitter_analyzer/table_formatter.py,sha256=FpYywpJOkXv3FfHEDFSWjfP5ZFa1WJZ6QqN_H0YtUC4,18274
|
|
15
|
-
tree_sitter_analyzer/utils.py,sha256=
|
|
15
|
+
tree_sitter_analyzer/utils.py,sha256=mL-TexPDTmapE3x7UErVQEJjXWn613KibPbZwgTpkd0,8332
|
|
16
16
|
tree_sitter_analyzer/cli/__init__.py,sha256=zCYwQW0hKFfZ4w-qoSOnqVKZGtdZ-ziH60Ax0QBE2iQ,886
|
|
17
17
|
tree_sitter_analyzer/cli/__main__.py,sha256=Sa02Ye57FhkDVTlGrb6U3m9V6II_TIuyzoQIwZtBkZ0,254
|
|
18
18
|
tree_sitter_analyzer/cli/info_commands.py,sha256=B9fBryAJ2Ctt-wo8Tko86BKOfFCCBPhAWz9vz_3r1fs,4521
|
|
@@ -37,7 +37,7 @@ tree_sitter_analyzer/formatters/formatter_factory.py,sha256=_jw9Emd7t0vM3DroJwBx
|
|
|
37
37
|
tree_sitter_analyzer/formatters/java_formatter.py,sha256=HmbQJgYsswg3whZ61p-M_CuHxg72yY-EtszOBVnjsw8,11285
|
|
38
38
|
tree_sitter_analyzer/formatters/python_formatter.py,sha256=Fz84SHDExP2nSx3Iq43XbbY8Z9dWYQj5zJS9cmPLysA,9898
|
|
39
39
|
tree_sitter_analyzer/interfaces/__init__.py,sha256=YrVFjBhhOkcJ4bRGmQnRBHwOSyPUsBLVy77Bc9eUYC8,303
|
|
40
|
-
tree_sitter_analyzer/interfaces/cli.py,sha256=
|
|
40
|
+
tree_sitter_analyzer/interfaces/cli.py,sha256=hTAIFew7yq9a9ejWnyGnwFHqadzckWXT-EaX-Q-La7I,17832
|
|
41
41
|
tree_sitter_analyzer/interfaces/cli_adapter.py,sha256=0lxm8dQuzTohlXptFq2bZEjnL7YAmOnli2iN3C8V0TA,11461
|
|
42
42
|
tree_sitter_analyzer/interfaces/mcp_adapter.py,sha256=vZcZy5FRYrSjJkRvdyu28OtqoESwiXkTqH9Nv7irRqM,6515
|
|
43
43
|
tree_sitter_analyzer/interfaces/mcp_server.py,sha256=3zj02Ur00ceJvKSG5bkuxlU2bHLaiCWjW2367dNPlLM,16907
|
|
@@ -45,7 +45,7 @@ tree_sitter_analyzer/languages/__init__.py,sha256=MAZEb-ifvdttqAQts_n3Cj9jtMd1cy
|
|
|
45
45
|
tree_sitter_analyzer/languages/java_plugin.py,sha256=2VdS2ZoNhd8q-Dqlc08vpfhoGqpN-vqEkRkFF4uuczE,46174
|
|
46
46
|
tree_sitter_analyzer/languages/python_plugin.py,sha256=to_mg-x4nJZO27i7geP5sTmHCLXiv2_gjFCCPB0ELZU,28839
|
|
47
47
|
tree_sitter_analyzer/mcp/__init__.py,sha256=QX4WA9HrxASLW1q-aVKhmXyONBy__2X9jOj9YctEj9Q,783
|
|
48
|
-
tree_sitter_analyzer/mcp/server.py,sha256=
|
|
48
|
+
tree_sitter_analyzer/mcp/server.py,sha256=wOG1NQpty_8cVe_vmgO87m--mAdxjZDonLv6zLcp9Bk,13622
|
|
49
49
|
tree_sitter_analyzer/mcp/resources/__init__.py,sha256=caWz1n3l22IaxBZ1plSjIUfroassWNNDRWEwEp1vaMw,1490
|
|
50
50
|
tree_sitter_analyzer/mcp/resources/code_file_resource.py,sha256=p3XrTAHPasl92f7mdiWnRv2nl338GPeKlYdCIzLyYqg,6541
|
|
51
51
|
tree_sitter_analyzer/mcp/resources/project_stats_resource.py,sha256=CkvfOSr7Bk6mJlJt-MkXw3kmUC0VAAsw8w1-AcGO0ek,19854
|
|
@@ -72,7 +72,7 @@ tree_sitter_analyzer/queries/java.py,sha256=hmaj7jKQ_m9nmOAnyiWQhzH-6g41xIi3fwt5
|
|
|
72
72
|
tree_sitter_analyzer/queries/javascript.py,sha256=TSe6uSHhBuQU0r2B8YBqpEYkU4q9CYRuTUqRK0WfM5o,4183
|
|
73
73
|
tree_sitter_analyzer/queries/python.py,sha256=V5MsKmI9A_FqAT2PKkrSL_Xp9bGKBUSpyVPoBmLxxWg,8018
|
|
74
74
|
tree_sitter_analyzer/queries/typescript.py,sha256=T8a9PwqqGkwLr8clVsAfu0IUIrLKH8u4sBqlU1Cz-FE,7138
|
|
75
|
-
tree_sitter_analyzer-0.1.
|
|
76
|
-
tree_sitter_analyzer-0.1.
|
|
77
|
-
tree_sitter_analyzer-0.1.
|
|
78
|
-
tree_sitter_analyzer-0.1.
|
|
75
|
+
tree_sitter_analyzer-0.1.1.dist-info/METADATA,sha256=1Isr-NuXUcAmSICuHE8f8MJIhZgIY6olfl19D9kBXTc,20459
|
|
76
|
+
tree_sitter_analyzer-0.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
77
|
+
tree_sitter_analyzer-0.1.1.dist-info/entry_points.txt,sha256=-XEh1racqnCT30mhKWMv5-bgX0iqd_J6b08lZS9J4eg,336
|
|
78
|
+
tree_sitter_analyzer-0.1.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
[console_scripts]
|
|
2
|
+
code-analyzer = tree_sitter_analyzer.cli_main:main
|
|
3
|
+
java-analyzer = tree_sitter_analyzer.cli_main:main
|
|
4
|
+
tree-sitter-analyzer = tree_sitter_analyzer.cli_main:main
|
|
5
|
+
|
|
6
|
+
[tree_sitter_analyzer.plugins]
|
|
7
|
+
java = tree_sitter_analyzer.languages.java_plugin:JavaPlugin
|
|
8
|
+
python = tree_sitter_analyzer.plugins.python_plugin:PythonPlugin
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
[console_scripts]
|
|
2
|
-
code-analyzer = tree_sitter_analyzer.interfaces.cli:main
|
|
3
|
-
java-analyzer = tree_sitter_analyzer.interfaces.cli:main
|
|
4
|
-
tree-sitter-analyzer = tree_sitter_analyzer.interfaces.cli:main
|
|
5
|
-
|
|
6
|
-
[tree_sitter_analyzer.plugins]
|
|
7
|
-
java = tree_sitter_analyzer.languages.java_plugin:JavaPlugin
|
|
8
|
-
python = tree_sitter_analyzer.plugins.python_plugin:PythonPlugin
|
|
File without changes
|