sqlsaber 0.4.0__py3-none-any.whl → 0.5.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 sqlsaber might be problematic. Click here for more details.
- sqlsaber/agents/anthropic.py +50 -1
- sqlsaber/agents/base.py +92 -0
- sqlsaber/cli/commands.py +3 -0
- sqlsaber/cli/display.py +30 -0
- sqlsaber/cli/interactive.py +9 -6
- sqlsaber/cli/streaming.py +5 -0
- sqlsaber/models/events.py +1 -1
- {sqlsaber-0.4.0.dist-info → sqlsaber-0.5.0.dist-info}/METADATA +37 -6
- {sqlsaber-0.4.0.dist-info → sqlsaber-0.5.0.dist-info}/RECORD +12 -12
- {sqlsaber-0.4.0.dist-info → sqlsaber-0.5.0.dist-info}/WHEEL +0 -0
- {sqlsaber-0.4.0.dist-info → sqlsaber-0.5.0.dist-info}/entry_points.txt +0 -0
- {sqlsaber-0.4.0.dist-info → sqlsaber-0.5.0.dist-info}/licenses/LICENSE +0 -0
sqlsaber/agents/anthropic.py
CHANGED
|
@@ -82,6 +82,44 @@ class AnthropicSQLAgent(BaseSQLAgent):
|
|
|
82
82
|
"required": ["query"],
|
|
83
83
|
},
|
|
84
84
|
},
|
|
85
|
+
{
|
|
86
|
+
"name": "plot_data",
|
|
87
|
+
"description": "Create a plot of query results.",
|
|
88
|
+
"input_schema": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"properties": {
|
|
91
|
+
"y_values": {
|
|
92
|
+
"type": "array",
|
|
93
|
+
"items": {"type": ["number", "null"]},
|
|
94
|
+
"description": "Y-axis data points (required)",
|
|
95
|
+
},
|
|
96
|
+
"x_values": {
|
|
97
|
+
"type": "array",
|
|
98
|
+
"items": {"type": ["number", "null"]},
|
|
99
|
+
"description": "X-axis data points (optional, will use indices if not provided)",
|
|
100
|
+
},
|
|
101
|
+
"plot_type": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"enum": ["line", "scatter", "histogram"],
|
|
104
|
+
"description": "Type of plot to create (default: line)",
|
|
105
|
+
"default": "line",
|
|
106
|
+
},
|
|
107
|
+
"title": {
|
|
108
|
+
"type": "string",
|
|
109
|
+
"description": "Title for the plot",
|
|
110
|
+
},
|
|
111
|
+
"x_label": {
|
|
112
|
+
"type": "string",
|
|
113
|
+
"description": "Label for X-axis",
|
|
114
|
+
},
|
|
115
|
+
"y_label": {
|
|
116
|
+
"type": "string",
|
|
117
|
+
"description": "Label for Y-axis",
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
"required": ["y_values"],
|
|
121
|
+
},
|
|
122
|
+
},
|
|
85
123
|
]
|
|
86
124
|
|
|
87
125
|
# Build system prompt with memories if available
|
|
@@ -96,13 +134,15 @@ Your responsibilities:
|
|
|
96
134
|
1. Understand user's natural language requests, think and convert them to SQL
|
|
97
135
|
2. Use the provided tools efficiently to explore database schema
|
|
98
136
|
3. Generate appropriate SQL queries
|
|
99
|
-
4. Execute queries safely
|
|
137
|
+
4. Execute queries safely - queries that modify the database are not allowed
|
|
100
138
|
5. Format and explain results clearly
|
|
139
|
+
6. Create visualizations when requested or when they would be helpful
|
|
101
140
|
|
|
102
141
|
IMPORTANT - Schema Discovery Strategy:
|
|
103
142
|
1. ALWAYS start with 'list_tables' to see available tables and row counts
|
|
104
143
|
2. Based on the user's query, identify which specific tables are relevant
|
|
105
144
|
3. Use 'introspect_schema' with a table_pattern to get details ONLY for relevant tables
|
|
145
|
+
4. Timestamp columns must be converted to text when you write queries
|
|
106
146
|
|
|
107
147
|
Guidelines:
|
|
108
148
|
- Use list_tables first, then introspect_schema for specific tables only
|
|
@@ -249,6 +289,15 @@ Guidelines:
|
|
|
249
289
|
"result": tool_result,
|
|
250
290
|
},
|
|
251
291
|
)
|
|
292
|
+
elif block["name"] == "plot_data":
|
|
293
|
+
yield StreamEvent(
|
|
294
|
+
"plot_result",
|
|
295
|
+
{
|
|
296
|
+
"tool_name": block["name"],
|
|
297
|
+
"input": block["input"],
|
|
298
|
+
"result": tool_result,
|
|
299
|
+
},
|
|
300
|
+
)
|
|
252
301
|
|
|
253
302
|
tool_results.append(build_tool_result_block(block["id"], tool_result))
|
|
254
303
|
|
sqlsaber/agents/base.py
CHANGED
|
@@ -4,6 +4,8 @@ import json
|
|
|
4
4
|
from abc import ABC, abstractmethod
|
|
5
5
|
from typing import Any, AsyncIterator, Dict, List, Optional
|
|
6
6
|
|
|
7
|
+
from uniplot import histogram, plot
|
|
8
|
+
|
|
7
9
|
from sqlsaber.database.connection import (
|
|
8
10
|
BaseDatabaseConnection,
|
|
9
11
|
CSVConnection,
|
|
@@ -146,6 +148,15 @@ class BaseSQLAgent(ABC):
|
|
|
146
148
|
return await self.execute_sql(
|
|
147
149
|
tool_input["query"], tool_input.get("limit", 100)
|
|
148
150
|
)
|
|
151
|
+
elif tool_name == "plot_data":
|
|
152
|
+
return await self.plot_data(
|
|
153
|
+
y_values=tool_input["y_values"],
|
|
154
|
+
x_values=tool_input.get("x_values"),
|
|
155
|
+
plot_type=tool_input.get("plot_type", "line"),
|
|
156
|
+
title=tool_input.get("title"),
|
|
157
|
+
x_label=tool_input.get("x_label"),
|
|
158
|
+
y_label=tool_input.get("y_label"),
|
|
159
|
+
)
|
|
149
160
|
else:
|
|
150
161
|
return json.dumps({"error": f"Unknown tool: {tool_name}"})
|
|
151
162
|
|
|
@@ -182,3 +193,84 @@ class BaseSQLAgent(ABC):
|
|
|
182
193
|
if query_upper.startswith("SELECT") and "LIMIT" not in query_upper:
|
|
183
194
|
return f"{query.rstrip(';')} LIMIT {limit};"
|
|
184
195
|
return query
|
|
196
|
+
|
|
197
|
+
async def plot_data(
|
|
198
|
+
self,
|
|
199
|
+
y_values: List[float],
|
|
200
|
+
x_values: Optional[List[float]] = None,
|
|
201
|
+
plot_type: str = "line",
|
|
202
|
+
title: Optional[str] = None,
|
|
203
|
+
x_label: Optional[str] = None,
|
|
204
|
+
y_label: Optional[str] = None,
|
|
205
|
+
) -> str:
|
|
206
|
+
"""Create a terminal plot using uniplot.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
y_values: Y-axis data points
|
|
210
|
+
x_values: X-axis data points (optional)
|
|
211
|
+
plot_type: Type of plot - "line", "scatter", or "histogram"
|
|
212
|
+
title: Plot title
|
|
213
|
+
x_label: X-axis label
|
|
214
|
+
y_label: Y-axis label
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
JSON string with success status and plot details
|
|
218
|
+
"""
|
|
219
|
+
try:
|
|
220
|
+
# Validate inputs
|
|
221
|
+
if not y_values:
|
|
222
|
+
return json.dumps({"error": "No data provided for plotting"})
|
|
223
|
+
|
|
224
|
+
# Convert to floats if needed
|
|
225
|
+
try:
|
|
226
|
+
y_values = [float(v) if v is not None else None for v in y_values]
|
|
227
|
+
if x_values:
|
|
228
|
+
x_values = [float(v) if v is not None else None for v in x_values]
|
|
229
|
+
except (ValueError, TypeError) as e:
|
|
230
|
+
return json.dumps({"error": f"Invalid data format: {str(e)}"})
|
|
231
|
+
|
|
232
|
+
# Create the plot
|
|
233
|
+
if plot_type == "histogram":
|
|
234
|
+
# For histogram, we only need y_values
|
|
235
|
+
histogram(
|
|
236
|
+
y_values,
|
|
237
|
+
title=title,
|
|
238
|
+
bins=min(20, len(set(y_values))), # Adaptive bin count
|
|
239
|
+
)
|
|
240
|
+
plot_info = {
|
|
241
|
+
"type": "histogram",
|
|
242
|
+
"data_points": len(y_values),
|
|
243
|
+
"title": title or "Histogram",
|
|
244
|
+
}
|
|
245
|
+
elif plot_type in ["line", "scatter"]:
|
|
246
|
+
# For line/scatter plots
|
|
247
|
+
plot_kwargs = {
|
|
248
|
+
"ys": y_values,
|
|
249
|
+
"title": title,
|
|
250
|
+
"lines": plot_type == "line",
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if x_values:
|
|
254
|
+
plot_kwargs["xs"] = x_values
|
|
255
|
+
if x_label:
|
|
256
|
+
plot_kwargs["x_unit"] = x_label
|
|
257
|
+
if y_label:
|
|
258
|
+
plot_kwargs["y_unit"] = y_label
|
|
259
|
+
|
|
260
|
+
plot(**plot_kwargs)
|
|
261
|
+
|
|
262
|
+
plot_info = {
|
|
263
|
+
"type": plot_type,
|
|
264
|
+
"data_points": len(y_values),
|
|
265
|
+
"title": title or f"{plot_type.capitalize()} Plot",
|
|
266
|
+
"has_x_values": x_values is not None,
|
|
267
|
+
}
|
|
268
|
+
else:
|
|
269
|
+
return json.dumps({"error": f"Unsupported plot type: {plot_type}"})
|
|
270
|
+
|
|
271
|
+
return json.dumps(
|
|
272
|
+
{"success": True, "plot_rendered": True, "plot_info": plot_info}
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
except Exception as e:
|
|
276
|
+
return json.dumps({"error": f"Error creating plot: {str(e)}"})
|
sqlsaber/cli/commands.py
CHANGED
|
@@ -117,6 +117,9 @@ def query(
|
|
|
117
117
|
if query_text:
|
|
118
118
|
# Single query mode with streaming
|
|
119
119
|
streaming_handler = StreamingQueryHandler(console)
|
|
120
|
+
console.print(
|
|
121
|
+
f"[bold blue]Connected to:[/bold blue] {db_name} {agent._get_database_type_name()}\n"
|
|
122
|
+
)
|
|
120
123
|
await streaming_handler.execute_streaming_query(query_text, agent)
|
|
121
124
|
else:
|
|
122
125
|
# Interactive mode
|
sqlsaber/cli/display.py
CHANGED
|
@@ -205,3 +205,33 @@ class DisplayManager:
|
|
|
205
205
|
self.show_error("Failed to parse schema data")
|
|
206
206
|
except Exception as e:
|
|
207
207
|
self.show_error(f"Error displaying schema information: {str(e)}")
|
|
208
|
+
|
|
209
|
+
def show_plot(self, plot_data: dict):
|
|
210
|
+
"""Display plot information and status."""
|
|
211
|
+
try:
|
|
212
|
+
# Parse the result if it's a string
|
|
213
|
+
if isinstance(plot_data.get("result"), str):
|
|
214
|
+
result = json.loads(plot_data["result"])
|
|
215
|
+
else:
|
|
216
|
+
result = plot_data.get("result", {})
|
|
217
|
+
|
|
218
|
+
# Check if there was an error
|
|
219
|
+
if "error" in result:
|
|
220
|
+
self.show_error(f"Plot error: {result['error']}")
|
|
221
|
+
return
|
|
222
|
+
|
|
223
|
+
# If plot was successful, show plot info
|
|
224
|
+
if result.get("success") and result.get("plot_rendered"):
|
|
225
|
+
plot_info = result.get("plot_info", {})
|
|
226
|
+
self.console.print(
|
|
227
|
+
f"\n[bold green]✓ Plot rendered:[/bold green] {plot_info.get('title', 'Plot')}"
|
|
228
|
+
)
|
|
229
|
+
self.console.print(
|
|
230
|
+
f"[dim] Type: {plot_info.get('type', 'unknown')}, "
|
|
231
|
+
f"Data points: {plot_info.get('data_points', 0)}[/dim]"
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
except json.JSONDecodeError:
|
|
235
|
+
self.show_error("Failed to parse plot result")
|
|
236
|
+
except Exception as e:
|
|
237
|
+
self.show_error(f"Error displaying plot: {str(e)}")
|
sqlsaber/cli/interactive.py
CHANGED
|
@@ -20,21 +20,24 @@ class InteractiveSession:
|
|
|
20
20
|
|
|
21
21
|
def show_welcome_message(self):
|
|
22
22
|
"""Display welcome message for interactive mode."""
|
|
23
|
+
# Show database information
|
|
24
|
+
db_name = getattr(self.agent, "database_name", None) or "Unknown"
|
|
25
|
+
db_type = self.agent._get_database_type_name()
|
|
26
|
+
|
|
23
27
|
self.console.print(
|
|
24
28
|
Panel.fit(
|
|
25
29
|
"[bold green]SQLSaber - Use the agent Luke![/bold green]\n\n"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
30
|
+
"[bold]Your agentic SQL assistant.[/bold]\n\n\n"
|
|
31
|
+
"[dim]Use 'clear' to reset conversation, 'exit' or 'quit' to leave.[/dim]\n\n"
|
|
32
|
+
"[dim]Start a message with '#' to add something to agent's memory for this database.[/dim]",
|
|
29
33
|
border_style="green",
|
|
30
34
|
)
|
|
31
35
|
)
|
|
32
|
-
|
|
33
36
|
self.console.print(
|
|
34
|
-
"[
|
|
37
|
+
f"[bold blue]Connected to:[/bold blue] {db_name} ({db_type})\n"
|
|
35
38
|
)
|
|
36
39
|
self.console.print(
|
|
37
|
-
"[dim]
|
|
40
|
+
"[dim]Press Esc-Enter or Meta-Enter to submit your query.[/dim]\n"
|
|
38
41
|
)
|
|
39
42
|
|
|
40
43
|
async def run(self):
|
sqlsaber/cli/streaming.py
CHANGED
|
@@ -63,6 +63,11 @@ class StreamingQueryHandler:
|
|
|
63
63
|
self.display.show_schema_info(event.data["result"])
|
|
64
64
|
has_content = True
|
|
65
65
|
|
|
66
|
+
elif event.type == "plot_result":
|
|
67
|
+
# Handle plot results
|
|
68
|
+
self.display.show_plot(event.data)
|
|
69
|
+
has_content = True
|
|
70
|
+
|
|
66
71
|
elif event.type == "processing":
|
|
67
72
|
# Show status when processing tool results
|
|
68
73
|
if explanation_started:
|
sqlsaber/models/events.py
CHANGED
|
@@ -7,7 +7,7 @@ class StreamEvent:
|
|
|
7
7
|
"""Event emitted during streaming processing."""
|
|
8
8
|
|
|
9
9
|
def __init__(self, event_type: str, data: Any = None):
|
|
10
|
-
# 'tool_use', 'text', 'query_result', 'error', 'processing'
|
|
10
|
+
# 'tool_use', 'text', 'query_result', 'plot_result', 'error', 'processing'
|
|
11
11
|
self.type = event_type
|
|
12
12
|
self.data = data
|
|
13
13
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlsaber
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: SQLSaber - Agentic SQL assistant like Claude Code
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.12
|
|
@@ -16,6 +16,7 @@ Requires-Dist: platformdirs>=4.0.0
|
|
|
16
16
|
Requires-Dist: questionary>=2.1.0
|
|
17
17
|
Requires-Dist: rich>=13.7.0
|
|
18
18
|
Requires-Dist: typer>=0.16.0
|
|
19
|
+
Requires-Dist: uniplot>=0.21.2
|
|
19
20
|
Description-Content-Type: text/markdown
|
|
20
21
|
|
|
21
22
|
# SQLSaber
|
|
@@ -24,7 +25,28 @@ Description-Content-Type: text/markdown
|
|
|
24
25
|
|
|
25
26
|
SQLSaber is an agentic SQL assistant. Think Claude Code but for SQL.
|
|
26
27
|
|
|
27
|
-
Ask your questions in natural language and it will gather the right context and answer your query by writing SQL and analyzing the results.
|
|
28
|
+
Ask your questions in natural language and it will gather the right context automatically and answer your query by writing SQL and analyzing the results.
|
|
29
|
+
|
|
30
|
+
## Table of Contents
|
|
31
|
+
|
|
32
|
+
- [Features](#features)
|
|
33
|
+
- [Installation](#installation)
|
|
34
|
+
- [Configuration](#configuration)
|
|
35
|
+
- [Database Connection](#database-connection)
|
|
36
|
+
- [AI Model Configuration](#ai-model-configuration)
|
|
37
|
+
- [Memory Management](#memory-management)
|
|
38
|
+
- [Usage](#usage)
|
|
39
|
+
- [Interactive Mode](#interactive-mode)
|
|
40
|
+
- [Single Query](#single-query)
|
|
41
|
+
- [Database Selection](#database-selection)
|
|
42
|
+
- [Examples](#examples)
|
|
43
|
+
- [MCP Server Integration](#mcp-server-integration)
|
|
44
|
+
- [Starting the MCP Server](#starting-the-mcp-server)
|
|
45
|
+
- [Configuring MCP Clients](#configuring-mcp-clients)
|
|
46
|
+
- [Available MCP Tools](#available-mcp-tools)
|
|
47
|
+
- [How It Works](#how-it-works)
|
|
48
|
+
- [Contributing](#contributing)
|
|
49
|
+
- [License](#license)
|
|
28
50
|
|
|
29
51
|
## Features
|
|
30
52
|
|
|
@@ -39,16 +61,25 @@ Ask your questions in natural language and it will gather the right context and
|
|
|
39
61
|
|
|
40
62
|
## Installation
|
|
41
63
|
|
|
64
|
+
### `uv`
|
|
65
|
+
|
|
42
66
|
```bash
|
|
43
67
|
uv tool install sqlsaber
|
|
44
68
|
```
|
|
45
69
|
|
|
46
|
-
|
|
70
|
+
### `pipx`
|
|
47
71
|
|
|
48
72
|
```bash
|
|
49
73
|
pipx install sqlsaber
|
|
50
74
|
```
|
|
51
75
|
|
|
76
|
+
### `brew`
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
brew install uv
|
|
80
|
+
uv tool install sqlsaber
|
|
81
|
+
```
|
|
82
|
+
|
|
52
83
|
## Configuration
|
|
53
84
|
|
|
54
85
|
### Database Connection
|
|
@@ -151,7 +182,7 @@ SQLSaber includes an MCP (Model Context Protocol) server that allows AI agents l
|
|
|
151
182
|
Run the MCP server using uvx:
|
|
152
183
|
|
|
153
184
|
```bash
|
|
154
|
-
uvx saber-mcp
|
|
185
|
+
uvx --from sqlsaber saber-mcp
|
|
155
186
|
```
|
|
156
187
|
|
|
157
188
|
### Configuring MCP Clients
|
|
@@ -161,12 +192,12 @@ uvx saber-mcp
|
|
|
161
192
|
Add SQLSaber as an MCP server in Claude Code:
|
|
162
193
|
|
|
163
194
|
```bash
|
|
164
|
-
claude mcp add -- uvx saber-mcp
|
|
195
|
+
claude mcp add -- uvx --from sqlsaber saber-mcp
|
|
165
196
|
```
|
|
166
197
|
|
|
167
198
|
#### Other MCP Clients
|
|
168
199
|
|
|
169
|
-
For other MCP clients, configure them to run the command: `uvx saber-mcp`
|
|
200
|
+
For other MCP clients, configure them to run the command: `uvx --from sqlsaber saber-mcp`
|
|
170
201
|
|
|
171
202
|
### Available MCP Tools
|
|
172
203
|
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
sqlsaber/__init__.py,sha256=QCFi8xTVMohelfi7zOV1-6oLCcGoiXoOcKQY-HNBCk8,66
|
|
2
2
|
sqlsaber/__main__.py,sha256=RIHxWeWh2QvLfah-2OkhI5IJxojWfy4fXpMnVEJYvxw,78
|
|
3
3
|
sqlsaber/agents/__init__.py,sha256=LWeSeEUE4BhkyAYFF3TE-fx8TtLud3oyEtyB8ojFJgo,167
|
|
4
|
-
sqlsaber/agents/anthropic.py,sha256=
|
|
5
|
-
sqlsaber/agents/base.py,sha256=
|
|
4
|
+
sqlsaber/agents/anthropic.py,sha256=HxpMV5uiOmxPAUR-ZZw8ncK7lM0aCUvj8mLiyFaUFwE,16268
|
|
5
|
+
sqlsaber/agents/base.py,sha256=IYVYYdQgSOQV6o1_3bzOizRuVMDw_aXfiPdFMNHwpg0,10269
|
|
6
6
|
sqlsaber/agents/mcp.py,sha256=FKtXgDrPZ2-xqUYCw2baI5JzrWekXaC5fjkYW1_Mg50,827
|
|
7
7
|
sqlsaber/agents/streaming.py,sha256=_EO390-FHUrL1fRCNfibtE9QuJz3LGQygbwG3CB2ViY,533
|
|
8
8
|
sqlsaber/cli/__init__.py,sha256=qVSLVJLLJYzoC6aj6y9MFrzZvAwc4_OgxU9DlkQnZ4M,86
|
|
9
|
-
sqlsaber/cli/commands.py,sha256=
|
|
9
|
+
sqlsaber/cli/commands.py,sha256=Dw24W0jij-8t1lpk99C4PBTgzFSag6vU-FZcjAYGG54,5074
|
|
10
10
|
sqlsaber/cli/database.py,sha256=DUfyvNBDp47oFM_VAC_hXHQy_qyE7JbXtowflJpwwH8,12643
|
|
11
|
-
sqlsaber/cli/display.py,sha256=
|
|
12
|
-
sqlsaber/cli/interactive.py,sha256=
|
|
11
|
+
sqlsaber/cli/display.py,sha256=LhsUSAFbiPBQRtW2JFf8PnpDnF2_kYdVTsB9HYgvxT4,8888
|
|
12
|
+
sqlsaber/cli/interactive.py,sha256=Kqe7kN9mhUiY_5z1Ki6apZ9ahs8uzhHp3xMZGiyTXpY,3912
|
|
13
13
|
sqlsaber/cli/memory.py,sha256=LW4ZF2V6Gw6hviUFGZ4ym9ostFCwucgBTIMZ3EANO-I,7671
|
|
14
14
|
sqlsaber/cli/models.py,sha256=3IcXeeU15IQvemSv-V-RQzVytJ3wuQ4YmWk89nTDcSE,7813
|
|
15
|
-
sqlsaber/cli/streaming.py,sha256=
|
|
15
|
+
sqlsaber/cli/streaming.py,sha256=EpltnkdokN42bczULbP9u_t8zduwhGyV-TWm1h8H-jc,3975
|
|
16
16
|
sqlsaber/config/__init__.py,sha256=olwC45k8Nc61yK0WmPUk7XHdbsZH9HuUAbwnmKe3IgA,100
|
|
17
17
|
sqlsaber/config/api_keys.py,sha256=kLdoExF_My9ojmdhO5Ca7-ZeowsO0v1GVa_QT5jjUPo,3658
|
|
18
18
|
sqlsaber/config/database.py,sha256=vKFOxPjVakjQhj1uoLcfzhS9ZFr6Z2F5b4MmYALQZoA,11421
|
|
@@ -26,10 +26,10 @@ sqlsaber/memory/__init__.py,sha256=GiWkU6f6YYVV0EvvXDmFWe_CxarmDCql05t70MkTEWs,6
|
|
|
26
26
|
sqlsaber/memory/manager.py,sha256=ML2NEO5Z4Aw36sEI9eOvWVnjl-qT2VOTojViJAj7Seo,2777
|
|
27
27
|
sqlsaber/memory/storage.py,sha256=DvZBsSPaAfk_DqrNEn86uMD-TQsWUI6rQLfNw6PSCB8,5788
|
|
28
28
|
sqlsaber/models/__init__.py,sha256=RJ7p3WtuSwwpFQ1Iw4_DHV2zzCtHqIzsjJzxv8kUjUE,287
|
|
29
|
-
sqlsaber/models/events.py,sha256=
|
|
29
|
+
sqlsaber/models/events.py,sha256=q2FackB60J9-7vegYIjzElLwKebIh7nxnV5AFoZc67c,752
|
|
30
30
|
sqlsaber/models/types.py,sha256=3U_30n91EB3IglBTHipwiW4MqmmaA2qfshfraMZyPps,896
|
|
31
|
-
sqlsaber-0.
|
|
32
|
-
sqlsaber-0.
|
|
33
|
-
sqlsaber-0.
|
|
34
|
-
sqlsaber-0.
|
|
35
|
-
sqlsaber-0.
|
|
31
|
+
sqlsaber-0.5.0.dist-info/METADATA,sha256=npxser6DO4GaHpYKsdcHvosseRr7RU0pZ0c81h2t2KA,5969
|
|
32
|
+
sqlsaber-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
33
|
+
sqlsaber-0.5.0.dist-info/entry_points.txt,sha256=jmFo96Ylm0zIKXJBwhv_P5wQ7SXP9qdaBcnTp8iCEe8,195
|
|
34
|
+
sqlsaber-0.5.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
35
|
+
sqlsaber-0.5.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|