DEV Community

Armaan Khan
Armaan Khan

Posted on

new

Understood! My apologies for the previous format. You want surgical, line-by-line instructions. I will provide precise "replace this line" or "add this after/before this line" instructions.


Actionable, Line-by-Line Changes for finops_framework


1. Changes in finops_framework/api.py

File Path: your_project/finops_framework/api.py

Change 1: Update typing imports.

  • Find this line (or similar):

    from typing import List, Dict, Any
    
  • Replace with:

    from typing import List, Dict, Any, Optional # Added Optional
    

Change 2: Modify display_charts_section method signature.

  • Find this line (it's the start of the method definition):

    def display_charts_section(self,
                               section_title: str,
                               chart_configs: List[Dict[str, Any]],
                               sql_queries: Dict[str, str],
                               current_start_date: date,
                               current_end_date: date):
    
  • Replace the entire above block with:

    def display_charts_section(self,
                               section_title: str,
                               chart_configs: List[Dict[str, Any]],
                               sql_queries: Dict[str, str],
                               current_start_date: date,
                               current_end_date: date,
                               extra_query_params: Optional[Dict[str, Any]] = None): # Added this line
    

Change 3: Update parameter passing within display_charts_section.

  • Find this line (it will be inside the for chart_config in chart_configs: loop):

            data = self._data_fetcher.execute_query(query_string)
    
  • Insert the following 3 lines immediately before the line you just found:

            if extra_query_params:
                params.update(extra_query_params)
    
  • Then, modify the line you found (the data = ... line) to:

            data = self._data_fetcher.execute_query(query_string, params) # Modified to pass params
    

2. Changes in finops_framework/core/data_fetcher.py

File Path: your_project/finops_framework/core/data_fetcher.py

Change 1: Update typing and datetime imports.

  • Find this line (or similar):

    from typing import Dict, Any
    
  • Replace with:

    from typing import Dict, Any, Tuple # Added Tuple
    
  • Find this line (or similar, if it exists):

    # (no specific datetime import, or just 'from datetime import date')
    
  • Ensure this line is present (add if not):

    from datetime import date, timedelta # Ensure timedelta is imported
    

Change 2: Modify execute_query method signature and logic.

  • Find this line (it's the start of the method definition):

    def execute_query(self, query_string: str) -> pd.DataFrame:
    
  • Replace the entire above block with:

    def execute_query(self, query_string: str, params: Dict[str, Any] = None) -> pd.DataFrame: # Modified signature
    
  • Find these lines within the execute_query method (they represent the original query execution):

            # For simplicity, directly execute. In a real app, you might parameterize.
            try:
                result = self._session.sql(query_string).collect()
                return pd.DataFrame(result)
            except Exception as e:
                raise DataFetchError(f"Snowflake query failed: {e}")
    
  • Replace the entire above block with:

        if params is None: # Added these two lines
            params = {}    #
        try: # Existing try block
            # Use self._session.sql().collect() for parameterized queries
            # Snowpark handles parameters securely with named binds
            result_df = self._session.sql(query_string).collect(_bind_parameters=params) # Modified this line
            return pd.DataFrame(result_df)
        except Exception as e: # Existing exception handling
            raise DataFetchError(f"Snowflake query failed: {e}")
    

Change 3: Add calculate_prev_period_dates method.

  • Find the very end of the DataFetcher class (after execute_query).
  • Add this entire method block at the end of the DataFetcher class:

    def calculate_prev_period_dates(self, start_date: date, end_date: date) -> Tuple[date, date]:
        """
        Calculates the start and end dates for the previous period of the same duration.
        """
        duration = end_date - start_date
        prev_end_date = start_date - timedelta(days=1)
        prev_start_date = prev_end_date - duration
        return prev_start_date, prev_end_date
    

3. Changes in finops_framework/ui/visual_renderers.py

File Path: your_project/finops_framework/ui/visual_renderers.py

Change 1: Enhance _render_altair_chart for theme colors (Optional but recommended for consistency).

  • Find this line (inside _render_altair_chart):

            st.altair_chart(chart_builder(data, height), use_container_width=True)
    
  • Replace the entire above line with:

            # Apply theme colors
            chart_obj = chart_builder(data, height) # Modified to create chart_obj
            chart_colors = st.session_state.get("app_theme", {}).get("chart_colors", [])
            if chart_colors:
                chart_obj = chart_obj.encode(
                    color=alt.Color(
                        alt.Color.field('color_col_placeholder', type="nominal"), # Placeholder for actual color column
                        scale=alt.Scale(range=chart_colors)
                    )
                ).resolve_scale(color='independent') # Allow color scale to be independent
    
            st.altair_chart(chart_obj, use_container_width=True) # Uses chart_obj
    

Change 2: Modify render_line_chart for color_col.

  • Find this line (it's the start of the render_line_chart method definition):

    def render_line_chart(self, data: pd.DataFrame, config: Dict[str, Any]):
    
  • Insert the following 3 lines immediately after the line you just found:

        color_encoding = None
        if "color_col" in config and config["color_col"] in data.columns:
            color_encoding = alt.Color(config["color_col"], title=config["color_col"])
    
  • Find this line (inside the encode section):

                tooltip=[config["x_col"], config["y_col"]]
    
  • Replace that line with:

                color=color_encoding, # Added this line
                tooltip=[config["x_col"], config["y_col"]] + ([config["color_col"]] if color_encoding else []) # Modified tooltip
    

Change 3: Modify render_bar_chart for color_col and sort.

  • Find this line (it's the start of the render_bar_chart method definition):

    def render_bar_chart(self, data: pd.DataFrame, config: Dict[str, Any]):
    
  • Insert the following 3 lines immediately after the line you just found:

        color_encoding = None
        if "color_col" in config and config["color_col"] in data.columns:
            color_encoding = alt.Color(config["color_col"], title=config["color_col"])
    
  • Find this line (inside the encode section, defining the x-axis):

                x=alt.X(config["x_col"], title=config.get("x_axis_title", config["x_col"])),
    
  • Replace that line with:

                x=alt.X( # Modified x-axis encoding
                    config["x_col"],
                    title=config.get("x_axis_title", config["x_col"]),
                    sort="-y" if config.get("sort_desc") else None # Added sort option
                ),
    
  • Find this line (inside the encode section):

                tooltip=[config["x_col"], config["y_col"]]
    
  • Replace that line with:

                color=color_encoding, # Added this line
                tooltip=[config["x_col"], config["y_col"]] + ([config["color_col"]] if color_encoding else []) # Modified tooltip
    

Change 4: Modify render_area_chart for color_col.

  • Find this line (it's the start of the render_area_chart method definition):

    def render_area_chart(self, data: pd.DataFrame, config: Dict[str, Any]):
    
  • Insert the following 3 lines immediately after the line you just found:

        color_encoding = None
        if "color_col" in config and config["color_col"] in data.columns:
            color_encoding = alt.Color(config["color_col"], title=config["color_col"])
    
  • Find this line (inside the encode section):

                tooltip=[config["x_col"], config["y_col"]]
    
  • Replace that line with:

                color=color_encoding, # Added this line
                tooltip=[config["x_col"], config["y_col"]] + ([config["color_col"]] if color_encoding else []) # Modified tooltip
    

These precise instructions should allow you to update your framework files with the necessary enhancements. Once these changes are applied, app.py and user30.py should run as intended!

Top comments (0)