diff --git a/.github/workflows/python-black.yml b/.github/workflows/python-quality.yml similarity index 67% rename from .github/workflows/python-black.yml rename to .github/workflows/python-quality.yml index 43d02bf..e1bbbba 100644 --- a/.github/workflows/python-black.yml +++ b/.github/workflows/python-quality.yml @@ -1,4 +1,4 @@ -name: Python Black Formatting Check +name: Python Code Quality Check on: pull_request: @@ -15,10 +15,13 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: '3.8' # Specify the Python version + python-version: '3.8' - name: Install Black - run: pip install black + run: pip install black flake8 - name: Check Python code formatting with Black run: black --check backend/ + + - name: Check Python code style with Flake8 + run: flake8 backend/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ea37579..3d8c455 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,12 @@ repos: - repo: https://github.com/psf/black - rev: 23.11.0 # Use a specific version or 'stable' for the latest stable release + rev: 23.11.0 hooks: - id: black language_version: python3 # Ensure black uses the correct version of Python files: ^backend/ # Run black only on files in the backend/ directory +- repo: https://github.com/PyCQA/flake8 + rev: 6.1.0 + hooks: + - id: flake8 + files: ^backend/ # Run flake8 only on files in the backend/ directory diff --git a/backend/databases/data_profile_manager.py b/backend/databases/data_profile_manager.py index 31cf1aa..9f3a84d 100644 --- a/backend/databases/data_profile_manager.py +++ b/backend/databases/data_profile_manager.py @@ -1,4 +1,3 @@ -from sqlalchemy.orm import Session from models.data_profile import DataProfile diff --git a/backend/envs/dev/utils.py b/backend/envs/dev/utils.py index 5d9791c..3cba575 100644 --- a/backend/envs/dev/utils.py +++ b/backend/envs/dev/utils.py @@ -1,6 +1,3 @@ -from sqlalchemy import MetaData, Table -from sqlalchemy.schema import CreateTable - from databases.database_manager import DatabaseManager from databases.sql_executor import SQLExecutor from databases.table_manager import TableManager @@ -36,7 +33,7 @@ def seed_db(): # Create sample table if it doesn't exist table_manager = TableManager() if "sample_sales" not in existing_tables: - df = pd.read_csv(f"envs/dev/sample_data/sample_sales_data.csv") + df = pd.read_csv("envs/dev/sample_data/sample_sales_data.csv") df.columns = map(str.lower, df.columns) table_manager.create_table_from_df(df, "sample_sales") @@ -47,38 +44,41 @@ def seed_db(): table_name="sample_sales", create_query=""" CREATE TABLE sample_sales ( - ordernumber BIGINT, - quantityordered BIGINT, - priceeach DOUBLE PRECISION, - orderlinenumber BIGINT, - sales DOUBLE PRECISION, - orderdate TEXT, - status TEXT, - qtr_id BIGINT, - month_id BIGINT, - year_id BIGINT, - productline TEXT, - msrp BIGINT, - productcode TEXT, - customername TEXT, - phone TEXT, - addressline1 TEXT, - addressline2 TEXT, - city TEXT, - state TEXT, - postalcode TEXT, - country TEXT, - territory TEXT, - contactlastname TEXT, - contactfirstname TEXT, + ordernumber BIGINT, + quantityordered BIGINT, + priceeach DOUBLE PRECISION, + orderlinenumber BIGINT, + sales DOUBLE PRECISION, + orderdate TEXT, + status TEXT, + qtr_id BIGINT, + month_id BIGINT, + year_id BIGINT, + productline TEXT, + msrp BIGINT, + productcode TEXT, + customername TEXT, + phone TEXT, + addressline1 TEXT, + addressline2 TEXT, + city TEXT, + state TEXT, + postalcode TEXT, + country TEXT, + territory TEXT, + contactlastname TEXT, + contactfirstname TEXT, dealsize TEXT) """, description=""" - The sample_sales table is designed for storing detailed sales transaction records. - It includes fields for order details (order number, quantity ordered, price per item, line number, total sales), date and status of the order, and temporal identifiers (quarter, month, and year). - Product information is detailed through product line, manufacturer's suggested retail price (MSRP), and product code. - Customer information is comprehensive, encompassing name, contact details, and address (with provisions for a second address line), along with geographical data like city, state, postal code, country, and sales territory. - Additional fields for contact person's name and the size of the deal are also included. - This table is suitable for categorizing detailed sales transactions and can support queries for sales analytics, customer segmentation, geographical sales trends, and time-based sales performance. + The sample_sales table is designed for storing detailed sales transaction records. + It includes fields for order details (order number, quantity ordered, price per item, line number, total sales), date and status of the order, and temporal identifiers + (quarter, month, and year). + Product information is detailed through product line, manufacturer's suggested retail price (MSRP), and product code. + Customer information is comprehensive, encompassing name, contact details, and address (with provisions for a second address line), + along with geographical data like city, state, postal code, country, and sales territory. + Additional fields for contact person's name and the size of the deal are also included. + This table is suitable for categorizing detailed sales transactions and can support queries for sales analytics, customer segmentation, geographical sales trends, + and time-based sales performance. """, ) diff --git a/backend/llms/base.py b/backend/llms/base.py index 204e705..1f48297 100644 --- a/backend/llms/base.py +++ b/backend/llms/base.py @@ -21,9 +21,6 @@ def generate_table_desc( ) -> str: raise NotImplementedError - def generate_text(self, input_text): - raise NotImplementedError - def fetch_table_name_from_sample( self, sample_content: str, extra_desc: str, table_metadata: str ): diff --git a/backend/models/data_profile.py b/backend/models/data_profile.py index 947b4b4..b8b8530 100644 --- a/backend/models/data_profile.py +++ b/backend/models/data_profile.py @@ -1,5 +1,4 @@ -from sqlalchemy import Boolean, Column, DateTime, Integer, String, ForeignKey -from sqlalchemy.sql import func +from sqlalchemy import Column, Integer, String, ForeignKey from pydantic import BaseModel from .base import Base diff --git a/backend/routes/auth_routes.py b/backend/routes/auth_routes.py index c78d2cf..821ccd8 100644 --- a/backend/routes/auth_routes.py +++ b/backend/routes/auth_routes.py @@ -135,7 +135,8 @@ async def register(response: Response, user: UserCreate): """ Register a new user and set a JWT token in a cookie upon successful registration. - This endpoint registers a new user with the provided details. It checks for the uniqueness of the username and email. If the registration is successful, it creates a JWT token, sets it in a secure, HttpOnly cookie in the response, and returns a success message. + This endpoint registers a new user with the provided details. It checks for the uniqueness of the username and email. If the registration is successful, it creates a JWT token, + sets it in a secure, HttpOnly cookie in the response, and returns a success message. Args: user (UserCreate): Pydantic model containing the user's registration details, such as username, email, and password. @@ -165,7 +166,7 @@ async def register(response: Response, user: UserCreate): # Generate access token access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) - access_token = create_access_token( + access_token = create_token( data={"sub": user.username}, expires_delta=access_token_expires ) diff --git a/backend/routes/table_routes.py b/backend/routes/table_routes.py index 317a1c7..922758f 100644 --- a/backend/routes/table_routes.py +++ b/backend/routes/table_routes.py @@ -1,6 +1,5 @@ from fastapi import APIRouter, Depends from security import get_current_user -from typing import Annotated from databases.database_manager import DatabaseManager from databases.sql_executor import SQLExecutor diff --git a/backend/routes/user_routes.py b/backend/routes/user_routes.py index 62c8286..cd9da2e 100644 --- a/backend/routes/user_routes.py +++ b/backend/routes/user_routes.py @@ -1,6 +1,5 @@ from fastapi import APIRouter, Depends, HTTPException -from security import get_current_admin_user, get_current_user, oauth2_scheme -from typing import Annotated +from security import get_current_admin_user, get_current_user from models.user import User, UserOut, UserRole, UserUpdate from databases.database_manager import DatabaseManager diff --git a/backend/security.py b/backend/security.py index 48b3261..0f6de36 100644 --- a/backend/security.py +++ b/backend/security.py @@ -3,7 +3,6 @@ from fastapi.security import OAuth2PasswordBearer from jose import jwt, JWTError from passlib.context import CryptContext -from typing import Annotated from databases.database_manager import DatabaseManager from databases.user_manager import UserManager diff --git a/backend/utils/nivo_assistant.py b/backend/utils/nivo_assistant.py index 94641c1..5ebeece 100644 --- a/backend/utils/nivo_assistant.py +++ b/backend/utils/nivo_assistant.py @@ -98,7 +98,8 @@ def get_bar_params(self): "string | (value: number) => string | number optional", "Optional formatter for values.", "The formatted value can then be used for labels & tooltips.", - "Under the hood, nivo uses d3-format, please have a look at it for available formats, you can also pass a function which will receive the raw value and should return the formatted one.", + "Under the hood, nivo uses d3-format, please have a look at it for available formats, you can also pass a function which will receive the raw value and should return the \ + formatted one.", ], "padding": [ "number optional default:0.1", @@ -159,14 +160,17 @@ def get_bar_params(self): "Defines the order of layers.", "support svg canvas", "Defines the order of layers, available layers are: grid, axes, bars, markers, legends, annotations. The markers layer is not available in the canvas flavor.", - "You can also use this to insert extra layers to the chart, this extra layer must be a function which will receive the chart computed data and must return a valid SVG element.", + "You can also use this to insert extra layers to the chart, this extra layer must be a function which will receive the chart computed data and must return a valid SVG \ + element.", ], "enableLabel": ["boolean optional default:true", "Enable/disable labels."], "label": [ "string | Function optional default:'formattedValue'", "Define how bar labels are computed.", "By default it will use the bar's value. It accepts a string which will be used to access a specific bar data property, such as 'value' or 'id'.", - "You can also use a funtion if you want to add more logic, this function will receive the current bar's data and must return the computed label which, depending on the context, should return a string or an svg element (Bar) or a string (BarCanvas). For example let's say you want to use a label with both the id and the value, you can achieve this with: label={d => `${d.id}: ${d.value}`}", + "You can also use a funtion if you want to add more logic, this function will receive the current bar's data and must return the computed label which, depending on the \ + context, should return a string or an svg element (Bar) or a string (BarCanvas). For example let's say you want to use a label with both the id and the value, you can \ + achieve this with: label={d => `${d.id}: ${d.value}`}", ], "labelSkipWidth": [ "number optional default:0", @@ -200,7 +204,8 @@ def get_bar_params(self): "Function optional", "Tooltip custom component", "support svg canvas", - "A function allowing complete tooltip customisation, it must return a valid HTML element and will receive the following data: {bar: {id: string | number,value: number,formattedValue: string,index: number,indexValue: string | number,// datum associated to the current index (raw data)data: object},color: string,label: string}", + "A function allowing complete tooltip customisation, it must return a valid HTML element and will receive the following data: {bar: {id: string | number,value: number,\ + formattedValue: string,index: number,indexValue: string | number,// datum associated to the current index (raw data)data: object},color: string,label: string}", ], "legends": ["object[] optional", "Optional chart's legends."], }