1
1
import argparse
2
+ import sys
2
3
import time
4
+ import traceback
5
+ from importlib import metadata
3
6
from pathlib import Path
4
7
from typing import NoReturn
5
8
12
15
from .validation import find_dependency_files , validate_dependency_files , validate_output_directory
13
16
14
17
18
+ def get_version () -> str :
19
+ """Get the current version of the package."""
20
+ try :
21
+ return metadata .version ("mvn-tree-visualizer" )
22
+ except metadata .PackageNotFoundError :
23
+ return "unknown"
24
+
25
+
15
26
def generate_diagram (
16
27
directory : str ,
17
28
output_file : str ,
@@ -20,6 +31,7 @@ def generate_diagram(
20
31
output_format : str ,
21
32
show_versions : bool ,
22
33
theme : str = "minimal" ,
34
+ quiet : bool = False ,
23
35
) -> None :
24
36
"""Generate the dependency diagram with comprehensive error handling."""
25
37
timestamp = time .strftime ("%H:%M:%S" )
@@ -31,7 +43,7 @@ def generate_diagram(
31
43
32
44
# Show what files we found
33
45
dependency_files = find_dependency_files (directory , filename )
34
- if len (dependency_files ) > 1 :
46
+ if len (dependency_files ) > 1 and not quiet :
35
47
print (f"[{ timestamp } ] Found { len (dependency_files )} dependency files" )
36
48
37
49
# Setup paths
@@ -103,31 +115,42 @@ def generate_diagram(
103
115
except Exception as e :
104
116
raise OutputGenerationError (f"Error generating { output_format .upper ()} output: { e } " )
105
117
106
- print (f"[{ timestamp } ] ✅ Diagram generated and saved to { output_file } " )
118
+ if not quiet :
119
+ print (f"[{ timestamp } ] SUCCESS: Diagram generated and saved to { output_file } " )
107
120
108
121
except MvnTreeVisualizerError as e :
109
122
# Our custom errors already have helpful messages
110
- print (f"[{ timestamp } ] ❌ Error: { e } " )
123
+ print (f"[{ timestamp } ] ERROR: { e } " , file = sys .stderr )
124
+ raise # Re-raise the exception for the caller to handle
111
125
except KeyboardInterrupt :
112
- print (f"\n [{ timestamp } ] ⏹️ Operation cancelled by user" )
126
+ print (f"\n [{ timestamp } ] Operation cancelled by user" , file = sys .stderr )
127
+ raise # Re-raise for the caller to handle
113
128
except Exception as e :
114
129
# Unexpected errors
115
- print (f"[{ timestamp } ] ❌ Unexpected error: { e } " )
116
- print ("This is an internal error. Please report this issue with the following details:" )
117
- print (f" - Directory: { directory } " )
118
- print (f" - Filename: { filename } " )
119
- print (f" - Output: { output_file } " )
120
- print (f" - Format: { output_format } " )
121
- import traceback
130
+ print (f"[{ timestamp } ] UNEXPECTED ERROR: { e } " , file = sys .stderr )
131
+ print ("This is an internal error. Please report this issue with the following details:" , file = sys .stderr )
132
+ print (f" - Directory: { directory } " , file = sys .stderr )
133
+ print (f" - Filename: { filename } " , file = sys .stderr )
134
+ print (f" - Output: { output_file } " , file = sys .stderr )
135
+ print (f" - Format: { output_format } " , file = sys .stderr )
122
136
123
137
traceback .print_exc ()
138
+ raise # Re-raise for the caller to handle
124
139
125
140
126
141
def cli () -> NoReturn :
127
142
parser = argparse .ArgumentParser (
128
143
prog = "mvn-tree-visualizer" ,
129
144
description = "Generate a dependency diagram from a file." ,
130
145
)
146
+
147
+ parser .add_argument (
148
+ "-v" ,
149
+ "--version" ,
150
+ action = "version" ,
151
+ version = f"mvn-tree-visualizer { get_version ()} " ,
152
+ )
153
+
131
154
parser .add_argument (
132
155
"directory" ,
133
156
type = str ,
@@ -186,6 +209,13 @@ def cli() -> NoReturn:
186
209
help = "Theme for the diagram visualization. Default is 'minimal'." ,
187
210
)
188
211
212
+ parser .add_argument (
213
+ "-q" ,
214
+ "--quiet" ,
215
+ action = "store_true" ,
216
+ help = "Suppress all console output except errors. Perfect for CI/CD pipelines and scripted usage." ,
217
+ )
218
+
189
219
args = parser .parse_args ()
190
220
directory : str = args .directory
191
221
output_file : str = args .output
@@ -195,28 +225,46 @@ def cli() -> NoReturn:
195
225
show_versions : bool = args .show_versions
196
226
watch_mode : bool = args .watch
197
227
theme : str = args .theme
228
+ quiet : bool = args .quiet
198
229
199
230
# Generate initial diagram
200
- print ("Generating initial diagram..." )
201
- generate_diagram (directory , output_file , filename , keep_tree , output_format , show_versions , theme )
231
+ if not quiet :
232
+ timestamp = time .strftime ("%Y-%m-%d %H:%M:%S" )
233
+ print (f"[{ timestamp } ] Generating initial diagram..." )
234
+
235
+ try :
236
+ generate_diagram (directory , output_file , filename , keep_tree , output_format , show_versions , theme , quiet )
237
+ except MvnTreeVisualizerError :
238
+ sys .exit (1 )
239
+ except KeyboardInterrupt :
240
+ sys .exit (130 ) # Standard exit code for SIGINT
241
+ except Exception :
242
+ sys .exit (1 )
202
243
203
244
if not watch_mode :
204
- print ("You can open it in your browser to view the dependency tree." )
205
- print ("Thank you for using mvn-tree-visualizer!" )
245
+ if not quiet :
246
+ print ("You can open it in your browser to view the dependency tree." )
247
+ print ("Thank you for using mvn-tree-visualizer!" )
206
248
return
207
249
208
250
# Watch mode
209
251
def regenerate_callback ():
210
252
"""Callback function for file watcher."""
211
- generate_diagram (directory , output_file , filename , keep_tree , output_format , show_versions , theme )
253
+ try :
254
+ generate_diagram (directory , output_file , filename , keep_tree , output_format , show_versions , theme , quiet )
255
+ except Exception :
256
+ # In watch mode, we don't want to exit on errors, just log them
257
+ print ("Error during diagram regeneration:" , file = sys .stderr )
258
+ traceback .print_exc ()
212
259
213
260
watcher = FileWatcher (directory , filename , regenerate_callback )
214
261
watcher .start ()
215
262
216
263
try :
217
264
watcher .wait ()
218
265
finally :
219
- print ("Thank you for using mvn-tree-visualizer!" )
266
+ if not quiet :
267
+ print ("Thank you for using mvn-tree-visualizer!" )
220
268
221
269
222
270
if __name__ == "__main__" :
0 commit comments