sqlshell 0.1.6__py3-none-any.whl → 0.1.9__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 sqlshell might be problematic. Click here for more details.

sqlshell/query_tab.py ADDED
@@ -0,0 +1,172 @@
1
+ from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
2
+ QPushButton, QFrame, QHeaderView, QTableWidget, QSplitter, QApplication)
3
+ from PyQt6.QtCore import Qt
4
+ from PyQt6.QtGui import QIcon
5
+
6
+ from sqlshell.editor import SQLEditor
7
+ from sqlshell.syntax_highlighter import SQLSyntaxHighlighter
8
+ from sqlshell.ui import FilterHeader
9
+
10
+ class QueryTab(QWidget):
11
+ def __init__(self, parent, results_title="RESULTS"):
12
+ super().__init__()
13
+ self.parent = parent
14
+ self.current_df = None
15
+ self.filter_widgets = []
16
+ self.results_title_text = results_title
17
+ self.init_ui()
18
+
19
+ def init_ui(self):
20
+ """Initialize the tab's UI components"""
21
+ # Set main layout
22
+ main_layout = QVBoxLayout(self)
23
+ main_layout.setContentsMargins(0, 0, 0, 0)
24
+ main_layout.setSpacing(0)
25
+
26
+ # Create splitter for query and results
27
+ self.splitter = QSplitter(Qt.Orientation.Vertical)
28
+ self.splitter.setHandleWidth(8)
29
+ self.splitter.setChildrenCollapsible(False)
30
+
31
+ # Top part - Query section
32
+ query_widget = QFrame()
33
+ query_widget.setObjectName("content_panel")
34
+ query_layout = QVBoxLayout(query_widget)
35
+ query_layout.setContentsMargins(16, 16, 16, 16)
36
+ query_layout.setSpacing(12)
37
+
38
+ # Query input
39
+ self.query_edit = SQLEditor()
40
+ # Apply syntax highlighting to the query editor
41
+ self.sql_highlighter = SQLSyntaxHighlighter(self.query_edit.document())
42
+
43
+ # Ensure a default completer is available
44
+ if not self.query_edit.completer:
45
+ from PyQt6.QtCore import QStringListModel
46
+ from PyQt6.QtWidgets import QCompleter
47
+
48
+ # Create a basic completer with SQL keywords if one doesn't exist
49
+ if hasattr(self.query_edit, 'all_sql_keywords'):
50
+ model = QStringListModel(self.query_edit.all_sql_keywords)
51
+ completer = QCompleter()
52
+ completer.setModel(model)
53
+ self.query_edit.set_completer(completer)
54
+
55
+ query_layout.addWidget(self.query_edit)
56
+
57
+ # Button row
58
+ button_layout = QHBoxLayout()
59
+ button_layout.setSpacing(8)
60
+
61
+ self.execute_btn = QPushButton('Execute Query')
62
+ self.execute_btn.setObjectName("primary_button")
63
+ self.execute_btn.setIcon(QIcon.fromTheme("media-playback-start"))
64
+ self.execute_btn.clicked.connect(self.execute_query)
65
+
66
+ self.clear_btn = QPushButton('Clear')
67
+ self.clear_btn.clicked.connect(self.clear_query)
68
+
69
+ button_layout.addWidget(self.execute_btn)
70
+ button_layout.addWidget(self.clear_btn)
71
+ button_layout.addStretch()
72
+
73
+ self.export_excel_btn = QPushButton('Export to Excel')
74
+ self.export_excel_btn.setIcon(QIcon.fromTheme("x-office-spreadsheet"))
75
+ self.export_excel_btn.clicked.connect(self.export_to_excel)
76
+
77
+ self.export_parquet_btn = QPushButton('Export to Parquet')
78
+ self.export_parquet_btn.setIcon(QIcon.fromTheme("application-octet-stream"))
79
+ self.export_parquet_btn.clicked.connect(self.export_to_parquet)
80
+
81
+ button_layout.addWidget(self.export_excel_btn)
82
+ button_layout.addWidget(self.export_parquet_btn)
83
+
84
+ query_layout.addLayout(button_layout)
85
+
86
+ # Bottom part - Results section
87
+ results_widget = QWidget()
88
+ results_layout = QVBoxLayout(results_widget)
89
+ results_layout.setContentsMargins(16, 16, 16, 16)
90
+ results_layout.setSpacing(12)
91
+
92
+ # Results header with row count
93
+ header_layout = QHBoxLayout()
94
+ self.results_title = QLabel(self.results_title_text)
95
+ self.results_title.setObjectName("header_label")
96
+ header_layout.addWidget(self.results_title)
97
+
98
+ header_layout.addStretch()
99
+
100
+ self.row_count_label = QLabel("")
101
+ self.row_count_label.setStyleSheet("color: #7F8C8D; font-style: italic;")
102
+ header_layout.addWidget(self.row_count_label)
103
+
104
+ results_layout.addLayout(header_layout)
105
+
106
+ # Results table with customized header
107
+ self.results_table = QTableWidget()
108
+ self.results_table.setAlternatingRowColors(True)
109
+
110
+ # Use custom FilterHeader for filtering
111
+ header = FilterHeader(self.results_table)
112
+ header.set_main_window(self.parent) # Set reference to main window
113
+ self.results_table.setHorizontalHeader(header)
114
+
115
+ # Set table properties for better performance with large datasets
116
+ self.results_table.setShowGrid(True)
117
+ self.results_table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers)
118
+ self.results_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Interactive)
119
+ self.results_table.horizontalHeader().setStretchLastSection(True)
120
+ self.results_table.verticalHeader().setVisible(True)
121
+
122
+ results_layout.addWidget(self.results_table)
123
+
124
+ # Add widgets to splitter
125
+ self.splitter.addWidget(query_widget)
126
+ self.splitter.addWidget(results_widget)
127
+
128
+ # Set initial sizes - default 40% query, 60% results
129
+ # This will be better for most uses of the app
130
+ screen = QApplication.primaryScreen()
131
+ if screen:
132
+ # Get available screen height
133
+ available_height = screen.availableGeometry().height()
134
+ # Calculate reasonable query pane size (25-35% depending on screen size)
135
+ if available_height >= 1080: # Large screens
136
+ query_height = int(available_height * 0.3) # 30% for query area
137
+ self.splitter.setSizes([query_height, available_height - query_height])
138
+ else: # Smaller screens
139
+ self.splitter.setSizes([300, 500]) # Default values for smaller screens
140
+ else:
141
+ # Fallback to fixed values if screen detection fails
142
+ self.splitter.setSizes([300, 500])
143
+
144
+ main_layout.addWidget(self.splitter)
145
+
146
+ def get_query_text(self):
147
+ """Get the current query text"""
148
+ return self.query_edit.toPlainText()
149
+
150
+ def set_query_text(self, text):
151
+ """Set the query text"""
152
+ self.query_edit.setPlainText(text)
153
+
154
+ def execute_query(self):
155
+ """Execute the current query"""
156
+ if hasattr(self.parent, 'execute_query'):
157
+ self.parent.execute_query()
158
+
159
+ def clear_query(self):
160
+ """Clear the query editor"""
161
+ if hasattr(self.parent, 'clear_query'):
162
+ self.parent.clear_query()
163
+
164
+ def export_to_excel(self):
165
+ """Export results to Excel"""
166
+ if hasattr(self.parent, 'export_to_excel'):
167
+ self.parent.export_to_excel()
168
+
169
+ def export_to_parquet(self):
170
+ """Export results to Parquet"""
171
+ if hasattr(self.parent, 'export_to_parquet'):
172
+ self.parent.export_to_parquet()
@@ -0,0 +1 @@
1
+ # SQLShell resources package initialization
@@ -0,0 +1,131 @@
1
+ import os
2
+ import sys
3
+ from PIL import Image, ImageDraw, ImageFont
4
+
5
+ def create_sql_icon(output_path, size=256):
6
+ """Create a professional SQL icon with improved readability"""
7
+ # Create a new image with a transparent background
8
+ img = Image.new('RGBA', (size, size), (0, 0, 0, 0))
9
+ draw = ImageDraw.Draw(img)
10
+
11
+ # Define colors
12
+ primary_color = (44, 62, 80, 255) # Dark blue-gray
13
+ secondary_color = (52, 152, 219, 255) # Bright blue
14
+ text_color = (236, 240, 241, 255) # Light gray for better readability
15
+ accent_color = (26, 188, 156, 255) # Teal
16
+
17
+ # Draw a rounded rectangle background
18
+ radius = size // 8
19
+ rect = [(size//12, size//12), (size - size//12, size - size//12)]
20
+ draw.rounded_rectangle(rect, radius, fill=primary_color)
21
+
22
+ # Try to load fonts in order of preference
23
+ font_size = size // 4 # Slightly smaller for better readability
24
+ font = None
25
+
26
+ # Common fonts list to try
27
+ font_options = [
28
+ "Arial Bold", "Arial", "Helvetica Bold", "Helvetica",
29
+ "DejaVuSans-Bold.ttf", "DejaVuSans.ttf",
30
+ "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
31
+ "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
32
+ ]
33
+
34
+ for font_name in font_options:
35
+ try:
36
+ font = ImageFont.truetype(font_name, font_size)
37
+ break
38
+ except IOError:
39
+ continue
40
+
41
+ if font is None:
42
+ font = ImageFont.load_default()
43
+ font_size = size // 5 # Adjust size for default font
44
+
45
+ # Draw "SQL" text with improved visibility
46
+ text = "SQL"
47
+
48
+ # Handle different PIL versions for text size calculation
49
+ if hasattr(draw, 'textsize'):
50
+ text_width, text_height = draw.textsize(text, font=font)
51
+ elif hasattr(font, 'getsize'):
52
+ text_width, text_height = font.getsize(text)
53
+ else:
54
+ # Fallback for newer PIL versions
55
+ try:
56
+ text_width, text_height = font.getbbox(text)[2:]
57
+ except:
58
+ text_width, text_height = font_size * 3, font_size
59
+
60
+ # Position text slightly higher
61
+ position = ((size - text_width) // 2, (size - text_height) // 2 - size//12)
62
+
63
+ # Draw text with subtle shadow for better readability
64
+ shadow_offset = max(1, size // 64)
65
+ draw.text((position[0] + shadow_offset, position[1] + shadow_offset),
66
+ text, fill=(0, 0, 0, 100), font=font)
67
+ draw.text(position, text, fill=text_color, font=font)
68
+
69
+ # Draw a small database icon
70
+ db_size = size // 3
71
+ db_x = size // 2 - db_size // 2
72
+ db_y = size // 2 + text_height // 2 + db_size // 4
73
+
74
+ # Draw database cylinder with improved shape
75
+ # Top ellipse
76
+ draw.ellipse([(db_x, db_y - db_size//4), (db_x + db_size, db_y)],
77
+ fill=secondary_color)
78
+ # Bottom ellipse
79
+ draw.ellipse([(db_x, db_y + db_size//2), (db_x + db_size, db_y + db_size//1.5)],
80
+ fill=secondary_color)
81
+ # Rectangle body
82
+ draw.rectangle([(db_x, db_y), (db_x + db_size, db_y + db_size//2)],
83
+ fill=secondary_color)
84
+
85
+ # Add subtle details to database
86
+ highlight_color = (72, 172, 240, 150) # Lighter blue for highlight
87
+ # Database line details
88
+ line_y1 = db_y + db_size//6
89
+ line_y2 = db_y + db_size//3
90
+ draw.line([(db_x + db_size//6, line_y1), (db_x + db_size - db_size//6, line_y1)],
91
+ fill=highlight_color, width=max(1, size//128))
92
+ draw.line([(db_x + db_size//6, line_y2), (db_x + db_size - db_size//6, line_y2)],
93
+ fill=highlight_color, width=max(1, size//128))
94
+
95
+ # Save the image with compression
96
+ img.save(output_path, optimize=True)
97
+ print(f"Professional SQL icon created at {output_path}")
98
+ return img
99
+
100
+ def create_logo(size=512):
101
+ """Create a properly sized logo for different uses"""
102
+ output_dir = os.path.dirname(os.path.abspath(__file__))
103
+ project_dir = os.path.abspath(os.path.join(output_dir, '..', '..'))
104
+
105
+ # Create different sizes
106
+ sizes = {
107
+ 'icon': 128, # For app icon
108
+ 'logo_small': 256, # For UI elements
109
+ 'logo_medium': 512, # For documentation
110
+ 'logo_large': 1024 # For high-res displays
111
+ }
112
+
113
+ for name, icon_size in sizes.items():
114
+ output_path = os.path.join(output_dir, f"{name}.png")
115
+ create_sql_icon(output_path, icon_size)
116
+
117
+ # Create the main logo file at the root directory
118
+ main_logo_path = os.path.join(project_dir, "sqlshell_logo.png")
119
+ logo = create_sql_icon(main_logo_path, size)
120
+ print(f"Main logo created at {main_logo_path}")
121
+
122
+ if __name__ == "__main__":
123
+ # Default size is 512 if no argument provided
124
+ size = 512
125
+ if len(sys.argv) > 1:
126
+ try:
127
+ size = int(sys.argv[1])
128
+ except ValueError:
129
+ print(f"Invalid size argument: {sys.argv[1]}. Using default size {size}.")
130
+
131
+ create_logo(size)
@@ -0,0 +1,96 @@
1
+ from PIL import Image, ImageDraw, ImageFont
2
+ import os
3
+ import math
4
+
5
+ def create_frame(size, progress, text=None):
6
+ # Create a new image with a dark background
7
+ img = Image.new('RGBA', size, (44, 62, 80, 255)) # Dark blue-gray background
8
+ draw = ImageDraw.Draw(img)
9
+
10
+ # Calculate dimensions
11
+ width, height = size
12
+ center_x = width // 2
13
+ center_y = height // 2
14
+
15
+ # Create a more visible circular pattern
16
+ radius = 80 # Larger radius
17
+ num_dots = 12
18
+ dot_size = 6 # Larger dots
19
+ trail_length = 8 # Longer trail
20
+
21
+ # Add a subtle gradient background
22
+ for y in range(height):
23
+ # Create a vertical gradient
24
+ gradient_factor = y / height
25
+ r = int(44 + (52 - 44) * gradient_factor)
26
+ g = int(62 + (152 - 62) * gradient_factor)
27
+ b = int(80 + (219 - 80) * gradient_factor)
28
+ draw.line([(0, y), (width, y)], fill=(r, g, b, 255))
29
+
30
+ # Draw a pulsing circle
31
+ pulse_size = 40 + 15 * math.sin(progress * 2 * math.pi)
32
+ draw.ellipse(
33
+ (center_x - pulse_size, center_y - pulse_size,
34
+ center_x + pulse_size, center_y + pulse_size),
35
+ outline=(52, 152, 219, 100),
36
+ width=2
37
+ )
38
+
39
+ # Draw orbiting dots with trails
40
+ for i in range(num_dots):
41
+ # Calculate dot position
42
+ angle = (progress * 360 - i * (360 / num_dots)) % 360
43
+ x = center_x + radius * math.cos(math.radians(angle))
44
+ y = center_y + radius * math.sin(math.radians(angle))
45
+
46
+ # Calculate dot opacity based on position in trail
47
+ opacity = int(255 * (1 - (i / trail_length))) if i < trail_length else 0
48
+
49
+ if opacity > 0:
50
+ # Draw dot with gradient effect
51
+ for size_mult in [1.0, 0.8, 0.6]:
52
+ current_size = int(dot_size * size_mult)
53
+ current_opacity = int(opacity * size_mult)
54
+
55
+ # Use more vibrant color for dots
56
+ draw.ellipse(
57
+ (x - current_size, y - current_size,
58
+ x + current_size, y + current_size),
59
+ fill=(41, 128, 185, current_opacity) # Brighter blue with fading opacity
60
+ )
61
+
62
+ # Add a subtle glow effect in the center
63
+ glow_radius = 60 + 10 * math.sin(progress * 4 * math.pi)
64
+ for r in range(int(glow_radius), 0, -5):
65
+ opacity = int(100 * (r / glow_radius))
66
+ draw.ellipse(
67
+ (center_x - r, center_y - r, center_x + r, center_y + r),
68
+ fill=(52, 152, 219, opacity // 8) # Very transparent blue
69
+ )
70
+
71
+ return img
72
+
73
+ def create_splash_gif():
74
+ size = (400, 300)
75
+ frames = []
76
+
77
+ # Create 30 frames for smooth animation (reduced from 60 for smaller file size)
78
+ for i in range(30):
79
+ progress = i / 30
80
+ frame = create_frame(size, progress)
81
+ frames.append(frame)
82
+
83
+ # Save the animated GIF
84
+ output_path = os.path.join(os.path.dirname(__file__), "splash_screen.gif")
85
+ frames[0].save(
86
+ output_path,
87
+ save_all=True,
88
+ append_images=frames[1:],
89
+ duration=66, # 66ms per frame = ~15fps (reduced from 20fps for smaller file size)
90
+ loop=0,
91
+ optimize=True # Enable optimization
92
+ )
93
+ print(f"Created splash screen GIF at: {output_path}")
94
+
95
+ if __name__ == "__main__":
96
+ create_splash_gif()
Binary file
Binary file
Binary file
Binary file
Binary file
sqlshell/setup.py CHANGED
@@ -21,7 +21,7 @@ setup(
21
21
  },
22
22
  author="SQLShell Team",
23
23
  description="A powerful SQL shell with GUI interface for data analysis",
24
- long_description=open('README.md').read(),
24
+ long_description=open('README.md', encoding='utf-8').read(),
25
25
  long_description_content_type="text/markdown",
26
26
  keywords="sql, data analysis, gui, duckdb",
27
27
  url="https://github.com/yourusername/sqlshell",