Skip to content

Commit e479cfe

Browse files
authored
Merge pull request #53 from stackql/feature/refactor
dry
2 parents 4ddb831 + 731ace4 commit e479cfe

File tree

5 files changed

+220
-93
lines changed

5 files changed

+220
-93
lines changed

.devcontainer/devcontainer.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"image": "mcr.microsoft.com/devcontainers/universal:2",
3+
"containerEnv": {
4+
},
5+
"hostRequirements": {
6+
"cpus": 2
7+
},
8+
"waitFor": "onCreateCommand",
9+
"updateContentCommand": "pip install -e ",
10+
"postCreateCommand": "",
11+
"postStartCommand": "git reset --hard && git clean -fd",
12+
"customizations": {
13+
"codespaces": {
14+
"openFiles": [
15+
"notebooks/demo.ipynb"
16+
]
17+
},
18+
"vscode": {
19+
"extensions": [
20+
"ms-toolsai.jupyter",
21+
"ms-python.python"
22+
]
23+
}
24+
}
25+
}

notebooks/demo.ipynb

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# PyStackQL Development Demo\n",
8+
"\n",
9+
"This notebook demonstrates how to use the development version of PyStackQL directly from the source code. Any changes you make to the PyStackQL code will be immediately reflected here."
10+
]
11+
},
12+
{
13+
"cell_type": "code",
14+
"execution_count": null,
15+
"metadata": {},
16+
"outputs": [],
17+
"source": [
18+
"# First, let's check what version of PyStackQL we're using\n",
19+
"import pystackql\n",
20+
"print(f\"PyStackQL Version: {pystackql.__version__}\")\n",
21+
"\n",
22+
"# Check the location of the package to confirm we're using the development version\n",
23+
"print(f\"Package Location: {pystackql.__file__}\")"
24+
]
25+
},
26+
{
27+
"cell_type": "code",
28+
"execution_count": null,
29+
"metadata": {},
30+
"outputs": [],
31+
"source": [
32+
"# Load the magic extension\n",
33+
"%load_ext pystackql.magic"
34+
]
35+
},
36+
{
37+
"cell_type": "markdown",
38+
"metadata": {},
39+
"source": [
40+
"## Basic Query Test\n",
41+
"\n",
42+
"Let's run a simple query to test that everything is working:"
43+
]
44+
},
45+
{
46+
"cell_type": "code",
47+
"execution_count": null,
48+
"metadata": {},
49+
"outputs": [],
50+
"source": [
51+
"%stackql SELECT 42 as answer"
52+
]
53+
},
54+
{
55+
"cell_type": "markdown",
56+
"metadata": {},
57+
"source": [
58+
"## CSV Download Test\n",
59+
"\n",
60+
"Let's test the CSV download functionality:"
61+
]
62+
},
63+
{
64+
"cell_type": "code",
65+
"execution_count": null,
66+
"metadata": {},
67+
"outputs": [],
68+
"source": [
69+
"%%stackql --csv-download\n",
70+
"SELECT \n",
71+
" 'Python' as language,\n",
72+
" 'Development' as mode,\n",
73+
" 'PyStackQL' as package"
74+
]
75+
},
76+
{
77+
"cell_type": "markdown",
78+
"metadata": {},
79+
"source": [
80+
"## Test Cloud Provider Functionality\n",
81+
"\n",
82+
"If you have credentials configured, you can test actual cloud provider queries:"
83+
]
84+
},
85+
{
86+
"cell_type": "code",
87+
"execution_count": null,
88+
"metadata": {},
89+
"outputs": [],
90+
"source": [
91+
"# Uncomment and run the appropriate provider query based on your available credentials\n",
92+
"\n",
93+
"# AWS Example\n",
94+
"# %stackql DESCRIBE aws.ec2.instances\n",
95+
"\n",
96+
"# GitHub Example\n",
97+
"# %stackql registry pull github\n",
98+
"# %stackql SELECT login FROM github.users.followers WHERE username = 'stackql'"
99+
]
100+
},
101+
{
102+
"cell_type": "markdown",
103+
"metadata": {},
104+
"source": [
105+
"## Development Tips\n",
106+
"\n",
107+
"1. After modifying PyStackQL code, you don't need to reinstall the package - changes are reflected immediately\n",
108+
"2. You can run tests from the terminal with `pytest tests/`\n",
109+
"3. If you modify deep core functionality, you may need to restart the kernel\n",
110+
"4. To debug issues, you can use Python's built-in debugging tools:"
111+
]
112+
},
113+
{
114+
"cell_type": "code",
115+
"execution_count": null,
116+
"metadata": {},
117+
"outputs": [],
118+
"source": [
119+
"# Example debugging a PyStackQL function\n",
120+
"from pystackql.core import StackQL\n",
121+
"\n",
122+
"# Get instance properties\n",
123+
"stackql = StackQL()\n",
124+
"props = stackql.properties()\n",
125+
"print(props)"
126+
]
127+
}
128+
],
129+
"metadata": {
130+
"kernelspec": {
131+
"display_name": "Python (PyStackQL Dev)",
132+
"language": "python",
133+
"name": "pystackql-dev"
134+
},
135+
"language_info": {
136+
"codemirror_mode": {
137+
"name": "ipython",
138+
"version": 3
139+
},
140+
"file_extension": ".py",
141+
"mimetype": "text/x-python",
142+
"name": "python",
143+
"nbconvert_exporter": "python",
144+
"pygments_lexer": "ipython3",
145+
"version": "3.10.4"
146+
}
147+
},
148+
"nbformat": 4,
149+
"nbformat_minor": 4
150+
}

pystackql/magic_ext/base.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,46 @@ def run_query(self, query):
5050
if query.strip().lower().startswith("registry pull"):
5151
return self.stackql_instance.executeStmt(query)
5252

53-
return self.stackql_instance.execute(query)
53+
return self.stackql_instance.execute(query)
54+
55+
def _display_with_csv_download(self, df):
56+
"""Display DataFrame with CSV download link.
57+
58+
:param df: The DataFrame to display and make downloadable.
59+
"""
60+
import IPython.display
61+
62+
try:
63+
# Generate CSV data
64+
import io
65+
import base64
66+
csv_buffer = io.StringIO()
67+
df.to_csv(csv_buffer, index=False)
68+
csv_data = csv_buffer.getvalue()
69+
70+
# Encode to base64 for data URI
71+
csv_base64 = base64.b64encode(csv_data.encode()).decode()
72+
73+
# Create download link
74+
download_link = f'data:text/csv;base64,{csv_base64}'
75+
76+
# Display the DataFrame first
77+
IPython.display.display(df)
78+
79+
# Create and display the download button
80+
download_html = f'''
81+
<div style="margin-top: 10px;">
82+
<a href="{download_link}" download="stackql_results.csv"
83+
style="display: inline-block; padding: 8px 16px; background-color: #007cba;
84+
color: white; text-decoration: none; border-radius: 4px;
85+
font-family: Arial, sans-serif; font-size: 14px; border: none; cursor: pointer;">
86+
📥 Download CSV
87+
</a>
88+
</div>
89+
'''
90+
IPython.display.display(IPython.display.HTML(download_html))
91+
92+
except Exception as e:
93+
# If CSV generation fails, just display the DataFrame normally
94+
IPython.display.display(df)
95+
print(f"Error generating CSV download: {e}")

pystackql/magic_ext/local.py

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@
88
"""
99

1010
from IPython.core.magic import (magics_class, line_cell_magic)
11-
from IPython.display import display, HTML
1211
from .base import BaseStackqlMagic
1312
import argparse
14-
import base64
15-
import io
1613

1714
@magics_class
1815
class StackqlMagic(BaseStackqlMagic):
@@ -62,48 +59,6 @@ def stackql(self, line, cell=None):
6259
elif not is_cell_magic:
6360
return results
6461

65-
def _display_with_csv_download(self, df):
66-
"""Display DataFrame with CSV download link.
67-
68-
:param df: The DataFrame to display and make downloadable.
69-
"""
70-
import IPython.display
71-
72-
try:
73-
# Generate CSV data
74-
import io
75-
import base64
76-
csv_buffer = io.StringIO()
77-
df.to_csv(csv_buffer, index=False)
78-
csv_data = csv_buffer.getvalue()
79-
80-
# Encode to base64 for data URI
81-
csv_base64 = base64.b64encode(csv_data.encode()).decode()
82-
83-
# Create download link
84-
download_link = f'data:text/csv;base64,{csv_base64}'
85-
86-
# Display the DataFrame first
87-
IPython.display.display(df)
88-
89-
# Create and display the download button
90-
download_html = f'''
91-
<div style="margin-top: 10px;">
92-
<a href="{download_link}" download="stackql_results.csv"
93-
style="display: inline-block; padding: 8px 16px; background-color: #007cba;
94-
color: white; text-decoration: none; border-radius: 4px;
95-
font-family: Arial, sans-serif; font-size: 14px; border: none; cursor: pointer;">
96-
📥 Download CSV
97-
</a>
98-
</div>
99-
'''
100-
IPython.display.display(IPython.display.HTML(download_html))
101-
102-
except Exception as e:
103-
# If CSV generation fails, just display the DataFrame normally
104-
IPython.display.display(df)
105-
print(f"Error generating CSV download: {e}")
106-
10762
def load_ipython_extension(ipython):
10863
"""Load the non-server magic in IPython.
10964
@@ -114,4 +69,4 @@ def load_ipython_extension(ipython):
11469
"""
11570
# Create an instance of the magic class and register it
11671
magic_instance = StackqlMagic(ipython)
117-
ipython.register_magics(magic_instance)
72+
ipython.register_magics(magic_instance)

pystackql/magic_ext/server.py

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@
88
"""
99

1010
from IPython.core.magic import (magics_class, line_cell_magic)
11-
from IPython.display import display, HTML
1211
from .base import BaseStackqlMagic
1312
import argparse
14-
import base64
15-
import io
1613

1714
@magics_class
1815
class StackqlServerMagic(BaseStackqlMagic):
@@ -64,50 +61,8 @@ def stackql(self, line, cell=None):
6461
else:
6562
return results
6663

67-
def _display_with_csv_download(self, df):
68-
"""Display DataFrame with CSV download link.
69-
70-
:param df: The DataFrame to display and make downloadable.
71-
"""
72-
import IPython.display
73-
74-
try:
75-
# Generate CSV data
76-
import io
77-
import base64
78-
csv_buffer = io.StringIO()
79-
df.to_csv(csv_buffer, index=False)
80-
csv_data = csv_buffer.getvalue()
81-
82-
# Encode to base64 for data URI
83-
csv_base64 = base64.b64encode(csv_data.encode()).decode()
84-
85-
# Create download link
86-
download_link = f'data:text/csv;base64,{csv_base64}'
87-
88-
# Display the DataFrame first
89-
IPython.display.display(df)
90-
91-
# Create and display the download button
92-
download_html = f'''
93-
<div style="margin-top: 10px;">
94-
<a href="{download_link}" download="stackql_results.csv"
95-
style="display: inline-block; padding: 8px 16px; background-color: #007cba;
96-
color: white; text-decoration: none; border-radius: 4px;
97-
font-family: Arial, sans-serif; font-size: 14px; border: none; cursor: pointer;">
98-
📥 Download CSV
99-
</a>
100-
</div>
101-
'''
102-
IPython.display.display(IPython.display.HTML(download_html))
103-
104-
except Exception as e:
105-
# If CSV generation fails, just display the DataFrame normally
106-
IPython.display.display(df)
107-
print(f"Error generating CSV download: {e}")
108-
10964
def load_ipython_extension(ipython):
11065
"""Load the server magic in IPython."""
11166
# Create an instance of the magic class and register it
11267
magic_instance = StackqlServerMagic(ipython)
113-
ipython.register_magics(magic_instance)
68+
ipython.register_magics(magic_instance)

0 commit comments

Comments
 (0)