webscout 7.8__py3-none-any.whl → 8.0__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 webscout might be problematic. Click here for more details.

Files changed (66) hide show
  1. webscout/Bard.py +5 -25
  2. webscout/DWEBS.py +476 -476
  3. webscout/Extra/GitToolkit/__init__.py +10 -0
  4. webscout/Extra/GitToolkit/gitapi/__init__.py +12 -0
  5. webscout/Extra/GitToolkit/gitapi/repository.py +195 -0
  6. webscout/Extra/GitToolkit/gitapi/user.py +96 -0
  7. webscout/Extra/GitToolkit/gitapi/utils.py +62 -0
  8. webscout/Extra/YTToolkit/ytapi/video.py +232 -103
  9. webscout/Extra/__init__.py +2 -0
  10. webscout/Extra/autocoder/__init__.py +1 -1
  11. webscout/Extra/autocoder/{rawdog.py → autocoder.py} +849 -849
  12. webscout/Extra/tempmail/__init__.py +26 -0
  13. webscout/Extra/tempmail/async_utils.py +141 -0
  14. webscout/Extra/tempmail/base.py +156 -0
  15. webscout/Extra/tempmail/cli.py +187 -0
  16. webscout/Extra/tempmail/mail_tm.py +361 -0
  17. webscout/Extra/tempmail/temp_mail_io.py +292 -0
  18. webscout/Provider/AISEARCH/__init__.py +5 -1
  19. webscout/Provider/AISEARCH/hika_search.py +194 -0
  20. webscout/Provider/AISEARCH/monica_search.py +246 -0
  21. webscout/Provider/AISEARCH/scira_search.py +320 -0
  22. webscout/Provider/AISEARCH/webpilotai_search.py +281 -0
  23. webscout/Provider/AllenAI.py +255 -122
  24. webscout/Provider/DeepSeek.py +1 -2
  25. webscout/Provider/Deepinfra.py +296 -286
  26. webscout/Provider/ElectronHub.py +709 -716
  27. webscout/Provider/ExaAI.py +261 -0
  28. webscout/Provider/ExaChat.py +28 -6
  29. webscout/Provider/Gemini.py +167 -165
  30. webscout/Provider/GithubChat.py +2 -1
  31. webscout/Provider/Groq.py +38 -24
  32. webscout/Provider/LambdaChat.py +2 -1
  33. webscout/Provider/Netwrck.py +3 -2
  34. webscout/Provider/OpenGPT.py +199 -0
  35. webscout/Provider/PI.py +39 -24
  36. webscout/Provider/TextPollinationsAI.py +232 -230
  37. webscout/Provider/Youchat.py +326 -296
  38. webscout/Provider/__init__.py +10 -4
  39. webscout/Provider/ai4chat.py +58 -56
  40. webscout/Provider/akashgpt.py +34 -22
  41. webscout/Provider/copilot.py +427 -427
  42. webscout/Provider/freeaichat.py +9 -2
  43. webscout/Provider/labyrinth.py +121 -20
  44. webscout/Provider/llmchatco.py +306 -0
  45. webscout/Provider/scira_chat.py +271 -0
  46. webscout/Provider/typefully.py +280 -0
  47. webscout/Provider/uncovr.py +312 -299
  48. webscout/Provider/yep.py +64 -12
  49. webscout/__init__.py +38 -36
  50. webscout/cli.py +293 -293
  51. webscout/conversation.py +350 -17
  52. webscout/litprinter/__init__.py +59 -667
  53. webscout/optimizers.py +419 -419
  54. webscout/update_checker.py +14 -12
  55. webscout/version.py +1 -1
  56. webscout/webscout_search.py +1346 -1282
  57. webscout/webscout_search_async.py +877 -813
  58. {webscout-7.8.dist-info → webscout-8.0.dist-info}/METADATA +44 -39
  59. {webscout-7.8.dist-info → webscout-8.0.dist-info}/RECORD +63 -46
  60. webscout/Provider/DARKAI.py +0 -225
  61. webscout/Provider/EDITEE.py +0 -192
  62. webscout/litprinter/colors.py +0 -54
  63. {webscout-7.8.dist-info → webscout-8.0.dist-info}/LICENSE.md +0 -0
  64. {webscout-7.8.dist-info → webscout-8.0.dist-info}/WHEEL +0 -0
  65. {webscout-7.8.dist-info → webscout-8.0.dist-info}/entry_points.txt +0 -0
  66. {webscout-7.8.dist-info → webscout-8.0.dist-info}/top_level.txt +0 -0
@@ -1,667 +1,59 @@
1
- import sys
2
- import os
3
- import json
4
- import time
5
- import threading
6
- import re
7
- from typing import Any, Optional, TextIO, Union, Sequence, Dict, List
8
- import textwrap
9
- import shutil
10
- from .colors import Colors
11
- import ctypes
12
-
13
- # Checking Pygments availability
14
- try:
15
- from pygments import highlight
16
- from pygments.lexers import get_lexer_by_name
17
- from pygments.formatters import Terminal256Formatter
18
-
19
- PYGMENTS_AVAILABLE = True
20
- except ImportError:
21
- PYGMENTS_AVAILABLE = False
22
-
23
- # Enabling UTF-8 output on Windows
24
- if sys.platform == 'win32':
25
- import ctypes
26
-
27
- kernel32 = ctypes.windll.kernel32
28
- kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
29
-
30
- # Checking and overriding sys.stdout
31
- try:
32
- if sys.stdout is not None:
33
- sys.stdout.reconfigure(encoding='utf-8')
34
- else:
35
- print("sys.stdout is not available.")
36
- except AttributeError:
37
- print("Failed to redefine sys.stdout.")
38
-
39
- # Enabling ANSI escape sequences for Windows
40
- if os.name == 'nt':
41
- kernel32 = ctypes.windll.kernel32
42
- kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
43
-
44
- # Removed the duplicated Colors class to import from colors.py
45
-
46
- class SyntaxTheme:
47
- """Syntax highlighting theme."""
48
- KEYWORD = Colors.MAGENTA + Colors.BOLD
49
- STRING = Colors.GREEN
50
- NUMBER = Colors.CYAN
51
- COMMENT = Colors.BRIGHT_BLACK + Colors.ITALIC
52
- FUNCTION = Colors.BRIGHT_BLUE
53
- CLASS = Colors.BRIGHT_YELLOW + Colors.BOLD
54
- OPERATOR = Colors.WHITE
55
- BRACKET = Colors.WHITE
56
- VARIABLE = Colors.BRIGHT_WHITE
57
-
58
- class MarkdownTheme:
59
- """Theme for markdown elements."""
60
- H1 = Colors.BOLD + Colors.BLUE
61
- H2 = Colors.BOLD + Colors.CYAN
62
- H3 = Colors.BOLD + Colors.GREEN
63
- BOLD = Colors.BOLD
64
- ITALIC = Colors.ITALIC
65
- CODE = Colors.YELLOW
66
- LINK = Colors.BLUE + Colors.UNDERLINE
67
- LIST_BULLET = Colors.CYAN + "•" + Colors.RESET
68
- QUOTE = Colors.GRAY
69
- STRIKE = Colors.STRIKE
70
- TABLE = Colors.GREEN
71
- TASK = Colors.YELLOW
72
- DETAILS = Colors.MAGENTA
73
-
74
- class ThemeStyles:
75
- SUCCESS = f"{Colors.GREEN}{Colors.BOLD}"
76
- ERROR = f"{Colors.RED}{Colors.BOLD}"
77
- WARNING = f"{Colors.YELLOW}{Colors.BOLD}"
78
- INFO = f"{Colors.BLUE}{Colors.BOLD}"
79
- DEBUG = f"{Colors.MAGENTA}"
80
- CODE = f"{Colors.CYAN}"
81
-
82
- class HoverInfo:
83
- """Hover information for different elements."""
84
- BANNER = "A fancy banner to make your output pop!"
85
- SUCCESS = "Something went right! "
86
- ERROR = "Oops! Something went wrong "
87
- WARNING = "Heads up! Something needs attention "
88
- INFO = "Just some helpful info "
89
- TABLE = "Data organized in rows and columns "
90
- TREE = "Hierarchical data visualization "
91
- JSON = "Pretty-printed JSON data "
92
- CODE = "Syntax-highlighted code block "
93
-
94
- class ProgressBar:
95
- def __init__(self, total: int, width: int = 40, prefix: str = '', suffix: str = ''):
96
- self.total = total
97
- self.width = width
98
- self.prefix = prefix
99
- self.suffix = suffix
100
- self.current = 0
101
-
102
- def update(self, current: int):
103
- self.current = current
104
- filled = int(self.width * current / self.total)
105
- bar = f"{Colors.GREEN}{'█' * filled}{Colors.RESET}{'░' * (self.width - filled)}"
106
- percent = f"{Colors.CYAN}{int(100 * current / self.total)}%{Colors.RESET}"
107
- print(f'\r{self.prefix} |{bar}| {percent} {self.suffix}', end='', flush=True)
108
- if current >= self.total:
109
- print()
110
-
111
- class Spinner:
112
- def __init__(self, message: str = ''):
113
- self.message = message
114
- self.frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
115
- self.running = False
116
- self.thread = None
117
-
118
- def spin(self):
119
- while self.running:
120
- for frame in self.frames:
121
- if not self.running:
122
- break
123
- print(f'\r{Colors.CYAN}{frame}{Colors.RESET} {self.message}', end='', flush=True)
124
- time.sleep(0.1)
125
-
126
- def __enter__(self):
127
- self.start()
128
- return self
129
-
130
- def __exit__(self, exc_type, exc_val, exc_tb):
131
- self.stop()
132
-
133
- def start(self):
134
- self.running = True
135
- self.thread = threading.Thread(target=self.spin)
136
- self.thread.start()
137
-
138
- def stop(self):
139
- self.running = False
140
- if self.thread:
141
- self.thread.join()
142
- print('\r' + ' ' * (len(self.message) + 2), end='', flush=True)
143
- print('\r', end='')
144
-
145
- class LitPrinter:
146
- def __init__(self,
147
- file: TextIO = sys.stdout,
148
- theme: Optional[dict] = None,
149
- indent_size: int = 4,
150
- buffer_size: int = 1024,
151
- syntax_theme: Optional[Dict[str, str]] = None,
152
- markdown_theme: Optional[Dict[str, str]] = None):
153
- self.file = file
154
- self.indent_size = indent_size
155
- self.buffer_size = buffer_size
156
- self._terminal_width = shutil.get_terminal_size().columns
157
- self._last_line = ""
158
- self._spinner_active = False
159
- self._progress_active = False
160
-
161
- # Default theme
162
- self.theme = theme or {
163
- "str": Colors.WHITE,
164
- "int": Colors.CYAN,
165
- "float": Colors.CYAN,
166
- "bool": Colors.YELLOW,
167
- "list": Colors.MAGENTA,
168
- "dict": Colors.BLUE,
169
- "none": Colors.RED,
170
- "timestamp": Colors.GREEN,
171
- "key": Colors.YELLOW,
172
- "bracket": Colors.BLUE,
173
- "comma": Colors.WHITE,
174
- "colon": Colors.WHITE,
175
- "url": f"{Colors.BLUE}{Colors.UNDERLINE}",
176
- "number": Colors.CYAN,
177
- "special": Colors.MAGENTA + Colors.BOLD,
178
- "error": Colors.RED + Colors.BOLD,
179
- "warning": Colors.YELLOW + Colors.BOLD,
180
- "success": Colors.GREEN + Colors.BOLD,
181
- "info": Colors.BLUE + Colors.BOLD,
182
- }
183
-
184
- self.syntax_theme = syntax_theme or vars(SyntaxTheme)
185
- self.markdown_theme = markdown_theme or vars(MarkdownTheme)
186
-
187
- def _get_terminal_width(self) -> int:
188
- """Get the terminal width or default to 80."""
189
- try:
190
- width = shutil.get_terminal_size().columns
191
- return width if width > 0 else 80
192
- except:
193
- return 80
194
-
195
- def _format_dict(self, d: dict, indent_level: int = 0) -> str:
196
- """Format dictionary with proper indentation and colors."""
197
- if not d:
198
- return f"{self.theme['bracket']}{{}}{Colors.RESET}"
199
-
200
- indent = " " * (self.indent_size * indent_level)
201
- next_indent = " " * (self.indent_size * (indent_level + 1))
202
-
203
- lines = [f"{self.theme['bracket']}{{{Colors.RESET}"]
204
-
205
- for i, (key, value) in enumerate(d.items()):
206
- # Format key with quotes if it's a string
207
- if isinstance(key, str):
208
- formatted_key = f"{self.theme['key']}'{key}'{Colors.RESET}"
209
- else:
210
- formatted_key = f"{self.theme['key']}{key}{Colors.RESET}"
211
-
212
- # Format value based on type
213
- if isinstance(value, dict):
214
- formatted_value = self._format_dict(value, indent_level + 1)
215
- elif isinstance(value, str):
216
- # Special handling for URLs
217
- if any(url_prefix in value.lower() for url_prefix in ['http://', 'https://', 'www.']):
218
- formatted_value = f"{self.theme['url']}{value}{Colors.RESET}"
219
- else:
220
- # Word wrap long strings
221
- if len(value) > 80:
222
- wrapped = textwrap.fill(value, width=80, subsequent_indent=next_indent + " ")
223
- formatted_value = f"{self.theme['str']}'{wrapped}'{Colors.RESET}"
224
- else:
225
- formatted_value = f"{self.theme['str']}'{value}'{Colors.RESET}"
226
- elif isinstance(value, (int, float)):
227
- formatted_value = f"{self.theme['number']}{value}{Colors.RESET}"
228
- elif isinstance(value, bool):
229
- formatted_value = f"{self.theme['bool']}{value}{Colors.RESET}"
230
- elif value is None:
231
- formatted_value = f"{self.theme['none']}None{Colors.RESET}"
232
- else:
233
- formatted_value = self._format_value(value)
234
-
235
- # Add comma if not last item
236
- comma = f"{self.theme['comma']},{Colors.RESET}" if i < len(d) - 1 else ""
237
-
238
- lines.append(f"{next_indent}{formatted_key}{self.theme['colon']}: {Colors.RESET}{formatted_value}{comma}")
239
-
240
- lines.append(f"{indent}{self.theme['bracket']}}}{Colors.RESET}")
241
- return '\n'.join(lines)
242
-
243
- def _format_sequence(self, seq: Sequence, indent_level: int = 0) -> str:
244
- """Format sequences (lists, tuples, sets) with proper indentation."""
245
- if not seq:
246
- return f"{self.theme['bracket']}[]{Colors.RESET}"
247
-
248
- indent = " " * (self.indent_size * indent_level)
249
- next_indent = " " * (self.indent_size * (indent_level + 1))
250
-
251
- lines = [f"{self.theme['bracket']}[{Colors.RESET}"]
252
-
253
- for i, item in enumerate(seq):
254
- formatted_item = self._format_value(item, indent_level + 1)
255
- comma = f"{self.theme['comma']},{Colors.RESET}" if i < len(seq) - 1 else ""
256
- lines.append(f"{next_indent}{formatted_item}{comma}")
257
-
258
- lines.append(f"{indent}{self.theme['bracket']}]{Colors.RESET}")
259
- return '\n'.join(lines)
260
-
261
- def _format_value(self, value: Any, indent_level: int = 0) -> str:
262
- """Enhanced format for any value with proper indentation and styling."""
263
- if value is None:
264
- return f"{self.theme['none']}None{Colors.RESET}"
265
-
266
- if isinstance(value, dict):
267
- return self._format_dict(value, indent_level)
268
-
269
- if isinstance(value, (list, tuple, set)):
270
- return self._format_sequence(value, indent_level)
271
-
272
- if isinstance(value, str):
273
- return str(value)
274
-
275
- if isinstance(value, bool):
276
- return f"{self.theme['bool']}{str(value)}{Colors.RESET}"
277
-
278
- if isinstance(value, (int, float)):
279
- return f"{self.theme['number']}{str(value)}{Colors.RESET}"
280
-
281
- if hasattr(value, '__dict__'):
282
- return self._format_dict(value.__dict__, indent_level)
283
-
284
- return str(value)
285
-
286
- def _highlight_code(self, code: str, language: str = "python") -> str:
287
- """Print code with that extra drip """
288
- if PYGMENTS_AVAILABLE:
289
- try:
290
- lexer = get_lexer_by_name(language)
291
- formatter = Terminal256Formatter(style='monokai')
292
- return highlight(code, lexer, formatter)
293
- except:
294
- pass
295
-
296
- if language != 'python':
297
- return code
298
-
299
- lines = []
300
- for line in code.split('\n'):
301
- if '#' in line:
302
- code_part, comment_part = line.split('#', 1)
303
- line = code_part + f"{self.syntax_theme['COMMENT']}#{comment_part}{Colors.RESET}"
304
-
305
- line = re.sub(r'(".*?"|\'.*?\')',
306
- f"{self.syntax_theme['STRING']}\\1{Colors.RESET}", line)
307
-
308
- line = re.sub(r'\b(\d+)\b',
309
- f"{self.syntax_theme['NUMBER']}\\1{Colors.RESET}", line)
310
-
311
- keywords = ['def', 'class', 'if', 'else', 'elif', 'for', 'while', 'try',
312
- 'except', 'finally', 'with', 'as', 'import', 'from', 'return']
313
-
314
- for keyword in keywords:
315
- line = re.sub(f'\\b{keyword}\\b',
316
- f"{self.syntax_theme['KEYWORD']}{keyword}{Colors.RESET}", line)
317
-
318
- lines.append(line)
319
-
320
- return '\n'.join(lines)
321
-
322
- def _format_markdown_stream(self, text: str) -> str:
323
- """Enhanced markdown formatting for streaming mode."""
324
- # Headers with emoji flair
325
- text = re.sub(r'^# (.+)$', f"{self.markdown_theme['H1']}🔥 \\1{Colors.RESET}", text, flags=re.M)
326
- text = re.sub(r'^## (.+)$', f"{self.markdown_theme['H2']}✨ \\1{Colors.RESET}", text, flags=re.M)
327
- text = re.sub(r'^### (.+)$', f"{self.markdown_theme['H3']}💫 \\1{Colors.RESET}", text, flags=re.M)
328
-
329
- # Bold, italic, and combined with multiple styles
330
- text = re.sub(r'\*\*\*(.+?)\*\*\*', f"{Colors.BOLD}{Colors.ITALIC}\\1{Colors.RESET}", text)
331
- text = re.sub(r'\*\*(.+?)\*\*', f"{Colors.BOLD}\\1{Colors.RESET}", text)
332
- text = re.sub(r'\*(.+?)\*', f"{Colors.ITALIC}\\1{Colors.RESET}", text)
333
- text = re.sub(r'__(.+?)__', f"{Colors.BOLD}\\1{Colors.RESET}", text)
334
- text = re.sub(r'_(.+?)_', f"{Colors.ITALIC}\\1{Colors.RESET}", text)
335
-
336
- # Code blocks and inline code
337
- text = re.sub(r'```(\w+)?\n(.*?)\n```', lambda m: self._highlight_code(m.group(2), m.group(1) or 'text'), text, flags=re.S)
338
- text = re.sub(r'`(.+?)`', f"{Colors.CYAN}\\1{Colors.RESET}", text)
339
-
340
- # Lists with proper indentation and bullets
341
- lines = text.split('\n')
342
- formatted_lines = []
343
- for i, line in enumerate(lines):
344
- # Match different bullet point styles
345
- bullet_match = re.match(r'^(\s*)([-•*]|\d+\.) (.+)$', line)
346
- if bullet_match:
347
- indent, bullet, content = bullet_match.groups()
348
- indent_level = len(indent) // 2
349
-
350
- # Choose bullet style based on nesting level
351
- if indent_level == 0:
352
- bullet_style = "•"
353
- elif indent_level == 1:
354
- bullet_style = "◦"
355
- else:
356
- bullet_style = "▪"
357
-
358
- # Format the line with proper indentation and bullet
359
- formatted_line = f"{' ' * (indent_level * 2)}{Colors.CYAN}{bullet_style}{Colors.RESET} {content}"
360
- formatted_lines.append(formatted_line)
361
- else:
362
- formatted_lines.append(line)
363
- text = '\n'.join(formatted_lines)
364
-
365
- # Links with underline
366
- text = re.sub(r'\[(.+?)\]\((.+?)\)', f"{Colors.BLUE}{Colors.UNDERLINE}\\1{Colors.RESET}", text)
367
-
368
- # Blockquotes with style
369
- text = re.sub(r'^> (.+)$', f"{self.markdown_theme['QUOTE']}│ \\1{Colors.RESET}", text, flags=re.M)
370
-
371
- # Strikethrough
372
- text = re.sub(r'~~(.+?)~~', f"{Colors.STRIKE}\\1{Colors.RESET}", text)
373
-
374
- # Task lists with fancy checkboxes
375
- text = re.sub(r'- \[ \] (.+)$', f"{self.markdown_theme['TASK']}☐ \\1{Colors.RESET}", text, flags=re.M)
376
- text = re.sub(r'- \[x\] (.+)$', f"{self.markdown_theme['TASK']}☑ \\1{Colors.RESET}", text, flags=re.M)
377
-
378
- # Tables with borders
379
- table_pattern = r'\|(.+?)\|[\r\n]+\|[-:| ]+\|[\r\n]+((?:\|.+?\|[\r\n]+)+)'
380
- text = re.sub(table_pattern, self._format_table_markdown, text, flags=re.M)
381
-
382
- return text
383
-
384
- def _format_table_markdown(self, match) -> str:
385
- """Format markdown tables with style."""
386
- header = [cell.strip() for cell in match.group(1).split('|') if cell.strip()]
387
- rows = []
388
- for row in match.group(2).strip().split('\n'):
389
- cells = [cell.strip() for cell in row.split('|')[1:-1]]
390
- if cells:
391
- rows.append(cells)
392
-
393
- # Get column widths
394
- widths = [max(len(str(row[i])) for row in [header] + rows) for i in range(len(header))]
395
-
396
- # Build table
397
- result = []
398
- # Header
399
- result.append('┌' + '┬'.join('─' * (w + 2) for w in widths) + '┐')
400
- result.append('│ ' + ' │ '.join(f"{h:<{w}}" for h, w in zip(header, widths)) + ' │')
401
- result.append('├' + '┼'.join('─' * (w + 2) for w in widths) + '┤')
402
- # Rows
403
- for row in rows:
404
- result.append('│ ' + ' │ '.join(f"{str(c):<{w}}" for c, w in zip(row, widths)) + ' │')
405
- result.append('└' + '┴'.join('─' * (w + 2) for w in widths) + '┘')
406
-
407
- return '\n'.join(result)
408
-
409
- def print(self, *args,
410
- # Builtin print compatibility
411
- sep: str = " ",
412
- end: str = "\n",
413
- file: Optional[TextIO] = None,
414
- flush: bool = True,
415
-
416
- # Styling options
417
- style: Optional[str] = None,
418
- color: Optional[str] = None,
419
- bg_color: Optional[str] = None,
420
- bold: bool = False,
421
- italic: bool = False,
422
- underline: bool = False,
423
- blink: bool = False,
424
- strike: bool = False,
425
- dim: bool = False,
426
- reverse: bool = False,
427
-
428
- # Layout options
429
- markdown: Optional[bool] = None,
430
- highlight: bool = False,
431
- center: bool = False,
432
- indent: int = 0,
433
- prefix: Optional[str] = None,
434
- suffix: Optional[str] = None,
435
- width: Optional[int] = None,
436
- padding: int = 0,
437
- margin: int = 0,
438
- align: str = "left",
439
-
440
- # Border options
441
- border: bool = False,
442
- border_style: Optional[str] = None,
443
- border_char: str = "─",
444
- border_color: Optional[str] = None,
445
- rounded_corners: bool = False,
446
- double_border: bool = False,
447
-
448
- # Animation options
449
- animate: bool = False,
450
- animation_speed: float = 0.05,
451
- animation_type: str = "typing",
452
-
453
- # Special features
454
- as_table: bool = False,
455
- as_tree: bool = False,
456
- as_json: bool = False,
457
- as_code: bool = False,
458
- language: str = "python",
459
-
460
- # Advanced features
461
- raw: bool = False) -> None:
462
- """
463
- Enhanced print with all builtin features plus rich formatting.
464
-
465
- Supports all builtin print parameters plus rich formatting features.
466
- Automatically detects and formats markdown content unless explicitly disabled.
467
- """
468
- # Handle raw output mode
469
- if raw:
470
- print(*args, sep=sep, end=end, file=file or self.file, flush=flush)
471
- return
472
-
473
- # Join args with separator
474
- output = sep.join(str(arg) for arg in args)
475
-
476
- # Auto-detect markdown if not explicitly set
477
- if markdown is None:
478
- markdown = any(marker in output for marker in [
479
- '#', '*', '_', '`', '>', '-', '•', '|',
480
- # '✨', '🔥', '💫', '☐', '☑',
481
- 'http://', 'https://',
482
- '```', '~~~',
483
- '<details>', '<summary>',
484
- ])
485
-
486
- # Apply markdown formatting if enabled
487
- if markdown:
488
- output = self._format_markdown_stream(output)
489
-
490
- # Build style string
491
- style_str = style or ""
492
- if color:
493
- style_str += getattr(Colors, color.upper(), "")
494
- if bg_color:
495
- style_str += getattr(Colors, f"BG_{bg_color.upper()}", "")
496
- if bold:
497
- style_str += Colors.BOLD
498
- if italic:
499
- style_str += Colors.ITALIC
500
- if underline:
501
- style_str += Colors.UNDERLINE
502
- if blink:
503
- style_str += Colors.BLINK
504
- if strike:
505
- style_str += Colors.STRIKE
506
- if dim:
507
- style_str += Colors.DIM
508
- if reverse:
509
- style_str += Colors.REVERSE
510
-
511
- # Apply style if any
512
- if style_str:
513
- output = f"{style_str}{output}{Colors.RESET}"
514
-
515
- # Handle special formatting
516
- if as_json:
517
- output = self._format_json(output)
518
- elif as_code:
519
- output = self._highlight_code(output, language)
520
- elif as_table:
521
- if isinstance(output, (list, tuple)):
522
- self.table(*output)
523
- return
524
- elif as_tree:
525
- if isinstance(output, (dict, list)):
526
- self.tree(output)
527
- return
528
-
529
- # Apply layout options
530
- if center:
531
- term_width = self._get_terminal_width()
532
- output = output.center(term_width)
533
- if indent > 0:
534
- output = " " * (indent * 4) + output
535
- if prefix:
536
- output = prefix + output
537
- if suffix:
538
- output = output + suffix
539
- if width:
540
- output = textwrap.fill(output, width=width)
541
-
542
- # Add borders
543
- if border:
544
- width = max(len(line) for line in output.split('\n'))
545
- border_top = '┌' + border_char * width + '┐'
546
- border_bottom = '└' + border_char * width + '┘'
547
- output = f"{border_top}\n{output}\n{border_bottom}"
548
-
549
- # Handle animation
550
- if animate:
551
- for char in output:
552
- print(char, end="", flush=True)
553
- time.sleep(animation_speed)
554
- print(end=end, flush=flush)
555
- return
556
-
557
- # Final output
558
- print(output, end=end, file=file or self.file, flush=flush)
559
-
560
- def status(self, text: str, style: Optional[str] = None):
561
- """Print a status message that can be overwritten."""
562
- style = style or self.theme['info']
563
- self._clear_line()
564
- self._last_line = f"{style}{text}{Colors.RESET}"
565
- print(self._last_line, end='\r', file=self.file, flush=True)
566
-
567
- def banner(self, text: str, style: Optional[str] = None):
568
- """Print a fancy banner with hover info."""
569
- print(f"\033]1337;Custom=id=banner:{HoverInfo.BANNER}\a", end='')
570
- style = style or self.theme['special']
571
- width = self._get_terminal_width() - 4
572
-
573
- lines = textwrap.wrap(text, width=width, break_long_words=False)
574
-
575
- print('╔' + '═' * width + '╗')
576
- for line in lines:
577
- padding = width - len(line)
578
- print('║ ' + line + ' ' * padding + ' ║')
579
- print('╚' + '═' * width + '╝')
580
- print("\033]1337;Custom=id=banner:end\a", end='')
581
-
582
- def success(self, text: str):
583
- """Print a success message with hover info."""
584
- print(f"\033]1337;Custom=id=success:{HoverInfo.SUCCESS}\a", end='')
585
- self.print(f"✓ {text}", style=self.theme['success'])
586
- print("\033]1337;Custom=id=success:end\a", end='')
587
-
588
- def error(self, text: str):
589
- """Print an error message with hover info."""
590
- print(f"\033]1337;Custom=id=error:{HoverInfo.ERROR}\a", end='')
591
- self.print(f"✗ {text}", style=self.theme['error'])
592
- print("\033]1337;Custom=id=error:end\a", end='')
593
-
594
- def warning(self, text: str):
595
- """Print a warning message with hover info."""
596
- print(f"\033]1337;Custom=id=warning:{HoverInfo.WARNING}\a", end='')
597
- self.print(f"⚠ {text}", style=self.theme['warning'])
598
- print("\033]1337;Custom=id=warning:end\a", end='')
599
-
600
- def info(self, text: str):
601
- """Print an info message with hover info."""
602
- print(f"\033]1337;Custom=id=info:{HoverInfo.INFO}\a", end='')
603
- self.print(f"ℹ {text}", style=self.theme['info'])
604
- print("\033]1337;Custom=id=info:end\a", end='')
605
-
606
- def table(self, headers: List[str], rows: List[List[Any]], style: Optional[str] = None):
607
- """Print a formatted table."""
608
- style = style or self.theme['special']
609
-
610
- col_widths = [len(h) for h in headers]
611
- for row in rows:
612
- for i, cell in enumerate(row):
613
- col_widths[i] = max(col_widths[i], len(str(cell)))
614
-
615
- header_line = '| ' + ' | '.join(f"{h:<{w}}" for h, w in zip(headers, col_widths)) + ' |'
616
- print(header_line)
617
-
618
- separator = '+' + '+'.join('-' * (w + 2) for w in col_widths) + '+'
619
- print(separator)
620
-
621
- for row in rows:
622
- row_line = '| ' + ' | '.join(f"{str(cell):<{w}}" for cell, w in zip(row, col_widths)) + ' |'
623
- print(row_line)
624
-
625
- def tree(self, data: Union[Dict, List], indent: int = 0):
626
- """Print a tree structure of nested data."""
627
- if isinstance(data, dict):
628
- for key, value in data.items():
629
- self.print(" " * indent + "├─ " + str(key) + ":", style=self.theme['key'])
630
- if isinstance(value, (dict, list)):
631
- self.tree(value, indent + 1)
632
- else:
633
- self.print(" " * (indent + 1) + "└─ " + str(value))
634
- elif isinstance(data, list):
635
- for item in data:
636
- if isinstance(item, (dict, list)):
637
- self.tree(item, indent + 1)
638
- else:
639
- self.print(" " * indent + "├─ " + str(item))
640
-
641
- def json(self, data: Any, indent: int = 4):
642
- """Print formatted JSON data."""
643
- formatted = json.dumps(data, indent=indent)
644
- self.print(formatted, highlight=True)
645
-
646
- def code_block(self, code: str, language: str = "python"):
647
- """Print code in a fancy box with syntax highlighting."""
648
- highlighted = self._highlight_code(code, language)
649
- lines = highlighted.split('\n')
650
-
651
- width = max(len(line) for line in lines)
652
- width = min(width, self._get_terminal_width() - 4) # Account for borders
653
-
654
- print('┌' + '─' * width + '┐')
655
-
656
- for line in lines:
657
- if len(line) > width:
658
- line = line[:width-3] + '...'
659
- else:
660
- line = line + ' ' * (width - len(line))
661
- print('│ ' + line + ' │')
662
-
663
- print('└' + '─' * width + '┘')
664
-
665
- def _clear_line(self):
666
- """Clear the current line."""
667
- print('\r' + ' ' * self._get_terminal_width(), end='\r', file=self.file, flush=True)
1
+ """
2
+ >>> from litprinter import litprint
3
+ >>> from litprinter import lit
4
+ >>> from litprinter import install, uninstall
5
+ >>>
6
+ >>> litprint("Hello, world!")
7
+ LIT -> [__main__.py:1] in () >>> Hello, world!
8
+ >>>
9
+ >>> def my_function():
10
+ ... lit(1, 2, 3)
11
+ >>> my_function()
12
+ LIT -> [__main__.py:4] in my_function() >>> 1, 2, 3
13
+ >>> install()
14
+ >>> ic("This is now the builtins.ic()")
15
+ LIT -> [__main__.py:7] in () >>> This is now the builtins.ic()
16
+ >>> uninstall()
17
+
18
+ This module provides enhanced print and logging functionalities for Python,
19
+ allowing developers to debug their code with style and precision. It
20
+ includes the litprint and lit functions for debugging, log for logging, and
21
+ install/uninstall functions for integration into the builtins module.
22
+ It also handles colorizing output and provides different styles and customizable
23
+ options.
24
+
25
+ LITPRINTER is inspired by the icecream package and provides similar functionality
26
+ with additional features:
27
+ - Variable inspection with expression display
28
+ - Return value handling for inline usage
29
+ - Support for custom formatters for specific data types
30
+ - Execution context tracking
31
+ - Rich-like colorized output with multiple themes (JARVIS, RICH, MODERN, NEON, CYBERPUNK)
32
+ - Better JSON formatting with indent=2 by default
33
+ - Advanced pretty printing for complex data structures with smart truncation
34
+ - Clickable file paths in supported terminals and editors (VSCode compatible)
35
+ - Enhanced visual formatting with better spacing and separators
36
+ - Special formatters for common types (Exception, bytes, set, frozenset, etc.)
37
+ - Smart object introspection for custom classes
38
+ - Logging capabilities with timestamp and log levels
39
+ """
40
+
41
+ # Try to import from the standalone litprinter package first
42
+ # If it's not installed
43
+ try:
44
+ import litprinter
45
+ # If standalone package is found, re-export all its components
46
+ from litprinter import litprint, lit, log, ic, install, uninstall
47
+ from litprinter import LITPrintDebugger, argumentToString
48
+ from litprinter import JARVIS, RICH, MODERN, NEON, CYBERPUNK, create_custom_style
49
+ from litprinter import traceback
50
+ # For compatibility with icecream
51
+ enable = litprinter.enable
52
+ disable = litprinter.disable
53
+
54
+ except ImportError:
55
+ # Raise a more informative error when litprinter is not installed
56
+ raise ImportError(
57
+ "The 'litprinter' package is required but not installed. "
58
+ "Please install it using: pip install litprinter"
59
+ ) from None