|  | 
| 1 |  | -# # pystackql/magic_ext/base.py | 
| 2 |  | - | 
| 3 |  | -# """ | 
| 4 |  | -# Base Jupyter magic extension for PyStackQL. | 
| 5 |  | - | 
| 6 |  | -# This module provides the base class for PyStackQL Jupyter magic extensions. | 
| 7 |  | -# """ | 
| 8 |  | - | 
| 9 |  | -# from __future__ import print_function | 
| 10 |  | -# from IPython.core.magic import Magics | 
| 11 |  | -# from string import Template | 
| 12 |  | - | 
| 13 |  | -# class BaseStackqlMagic(Magics): | 
| 14 |  | -#     """Base Jupyter magic extension enabling running StackQL queries. | 
| 15 |  | - | 
| 16 |  | -#     This extension allows users to conveniently run StackQL queries against cloud  | 
| 17 |  | -#     or SaaS resources directly from Jupyter notebooks, and visualize the results in a tabular  | 
| 18 |  | -#     format using Pandas DataFrames. | 
| 19 |  | -#     """ | 
| 20 |  | -#     def __init__(self, shell, server_mode): | 
| 21 |  | -#         """Initialize the BaseStackqlMagic class. | 
| 22 |  | - | 
| 23 |  | -#         :param shell: The IPython shell instance. | 
| 24 |  | -#         :param server_mode: Whether to use server mode. | 
| 25 |  | -#         """ | 
| 26 |  | -#         from ..core import StackQL | 
| 27 |  | -#         super(BaseStackqlMagic, self).__init__(shell) | 
| 28 |  | -#         self.stackql_instance = StackQL(server_mode=server_mode, output='pandas') | 
| 29 |  | -           | 
| 30 |  | -#     def get_rendered_query(self, data): | 
| 31 |  | -#         """Substitute placeholders in a query template with variables from the current namespace. | 
| 32 |  | -         | 
| 33 |  | -#         :param data: SQL query template containing placeholders. | 
| 34 |  | -#         :type data: str | 
| 35 |  | -#         :return: A SQL query with placeholders substituted. | 
| 36 |  | -#         :rtype: str | 
| 37 |  | -#         """ | 
| 38 |  | -#         t = Template(data) | 
| 39 |  | -#         return t.substitute(self.shell.user_ns) | 
| 40 |  | - | 
| 41 |  | -#     def run_query(self, query): | 
| 42 |  | -#         """Execute a StackQL query | 
| 43 |  | -         | 
| 44 |  | -#         :param query: StackQL query to be executed. | 
| 45 |  | -#         :type query: str | 
| 46 |  | -#         :return: Query results, returned as a Pandas DataFrame. | 
| 47 |  | -#         :rtype: pandas.DataFrame | 
| 48 |  | -#         """ | 
| 49 |  | -#         # Check if the query starts with "registry pull" (case insensitive) | 
| 50 |  | -#         if query.strip().lower().startswith("registry pull"): | 
| 51 |  | -#             return self.stackql_instance.executeStmt(query) | 
| 52 |  | -         | 
| 53 |  | -#         return self.stackql_instance.execute(query) | 
| 54 |  | -     | 
| 55 |  | -#     def _display_with_csv_download(self, df): | 
| 56 |  | -#         """Display a CSV download link for the DataFrame without displaying the DataFrame again. | 
| 57 |  | -         | 
| 58 |  | -#         :param df: The DataFrame to 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 |  | -#             # Only display the download button, not the DataFrame | 
| 77 |  | -#             download_html = f''' | 
| 78 |  | -#             <div style="margin-top: 15px; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', sans-serif;"> | 
| 79 |  | -#                 <a href="{download_link}" download="stackql_results.csv"  | 
| 80 |  | -#                 style="display: inline-flex; align-items: center; gap: 8px; padding: 9px 16px;  | 
| 81 |  | -#                         background-color: #2196F3; color: white; text-decoration: none;  | 
| 82 |  | -#                         border-radius: 4px; font-size: 14px; font-weight: 500;  | 
| 83 |  | -#                         box-shadow: 0 2px 4px rgba(0,0,0,0.08); transition: all 0.2s ease;"> | 
| 84 |  | -#                     <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> | 
| 85 |  | -#                         <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path> | 
| 86 |  | -#                         <polyline points="7 10 12 15 17 10"></polyline> | 
| 87 |  | -#                         <line x1="12" y1="15" x2="12" y2="3"></line> | 
| 88 |  | -#                     </svg> | 
| 89 |  | -#                     Download CSV | 
| 90 |  | -#                 </a> | 
| 91 |  | -#             </div> | 
| 92 |  | -#             ''' | 
| 93 |  | -#             IPython.display.display(IPython.display.HTML(download_html)) | 
| 94 |  | -             | 
| 95 |  | -#         except Exception as e: | 
| 96 |  | -#             # If CSV generation fails, just print an error message without displaying anything | 
| 97 |  | -#             print(f"Error generating CSV download: {e}") | 
| 98 |  | - | 
| 99 | 1 | # pystackql/magic_ext/base.py | 
| 100 | 2 | 
 | 
| 101 | 3 | """ | 
|  | 
0 commit comments