Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lint tools to the project #1

Merged
merged 1 commit into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[flake8]
max-line-length = 120
exclude = .git,
__pycache__,
docs/source/conf.py,
old,build,
dist,
venv,
.venv,
.tox,
.eggs,
*.egg,
*.egg-info,
*.egg-info/*
__init__.py
ignore = E203, E266, W503
max-complexity = 18
select = B,C,E,F,W,T4,B9
50 changes: 49 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,54 @@ env:
PLATFORMS: linux/amd64,linux/arm64

jobs:
lint:
runs-on: ubuntu-22.04
steps:
- name: "Checkout backend(REST)"
uses: actions/checkout@v4
with:
path: backend
fetch-depth: 0
fetch-tags: 1

- name: "lint"
run: |
cd backend

echo "Fix mess with tags in actions/checkout..."
git fetch -f && git fetch -f --tags

sudo apt-get install -y make
pip3 install -r requirements.txt
pip3 install -r requirements-dev.txt

#Run linter
make lint

format:
runs-on: ubuntu-22.04
steps:
- name: "Checkout backend(REST)"
uses: actions/checkout@v4
with:
path: backend
fetch-depth: 0
fetch-tags: 1

- name: "format"
run: |
cd backend

echo "Fix mess with tags in actions/checkout..."
git fetch -f && git fetch -f --tags

sudo apt-get install -y make
pip3 install -r requirements.txt
pip3 install -r requirements-dev.txt

#Run formatter
AUTOPEP8_EXIT_CODE=--exit-code make format-code
msune marked this conversation as resolved.
Show resolved Hide resolved

unit-test:
runs-on: ubuntu-22.04
steps:
Expand All @@ -37,7 +85,7 @@ jobs:

docker_build_and_publish:
runs-on: ubuntu-22.04
needs: [unit-test]
needs: [unit-test, format, lint]
steps:
- name: "Checkout backend(REST)"
uses: actions/checkout@v4
Expand Down
4 changes: 4 additions & 0 deletions .mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[mypy]
check_untyped_defs = True
disallow_untyped_calls = True
ignore_missing_imports = True
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
AUTOPEP8_OPTS ?= --in-place --recursive --aggressive
AUTOPEP8_EXIT_CODE ?=

all: start

start: _build _run
Expand All @@ -10,3 +13,8 @@ stop:
@docker kill rest_backend || true
@docker rm rest_backend || true
reload: stop start
format-code:
autopep8 $(AUTOPEP8_OPTS) $(AUTOPEP8_EXIT_CODE) ./
lint:
flake8 ./
mypy ./
3 changes: 3 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mypy
flake8
autopep8
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ psycopg2==2.9.9
jinja2==3.1.3
pyyaml==6.0.1
pytest
types-requests
26 changes: 13 additions & 13 deletions src/constants.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#DB
# DB

##Driver
DRIVER="sqlite"
# Driver
DRIVER = "sqlite"

##SQLite
SQLITE_FILE="./data/backend.db"
# SQLite
SQLITE_FILE = "./data/backend.db"

##Postgres
POSTGRES_HOST="127.0.0.1"
POSTGRES_PORT=5432
POSTGRES_DB="stack"
POSTGRES_USERNAME="postgres"
POSTGRES_PASSWORD="test"
# Postgres
POSTGRES_HOST = "127.0.0.1"
POSTGRES_PORT = 5432
POSTGRES_DB = "stack"
POSTGRES_USERNAME = "postgres"
POSTGRES_PASSWORD = "test"

#API
URL_PATH="/rest"
# API
URL_PATH = "/rest"
32 changes: 23 additions & 9 deletions src/data/database.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
from typing import Any, Generator
from sqlmodel import SQLModel, create_engine, Session
from sqlalchemy_utils import database_exists, create_database
from constants import *
import constants

def createTables(db_engine):

def create_tables(db_engine) -> None:
from models.turnilo_dashboard import TurniloDashboard
SQLModel.metadata.create_all(db_engine)
SQLModel.metadata.create_all(db_engine, tables=[TurniloDashboard.__table__])


if DRIVER == "sqlite":
engine = create_engine("sqlite:///"+SQLITE_FILE, connect_args={"check_same_thread": False})
if constants.DRIVER == "sqlite":
engine = create_engine("sqlite:///" + constants.SQLITE_FILE, connect_args={"check_same_thread": False})
else:
engine = create_engine("postgresql://"+POSTGRES_USERNAME+":"+POSTGRES_PASSWORD+"@"+POSTGRES_HOST+":"+str(POSTGRES_PORT)+"/"+POSTGRES_DB)
engine = create_engine(
"postgresql://"
+ constants.POSTGRES_USERNAME
+ ":"
+ constants.POSTGRES_PASSWORD
+ "@"
+ constants.POSTGRES_HOST
+ ":"
+ str(constants.POSTGRES_PORT)
+ "/"
+ constants.POSTGRES_DB)

if not database_exists(engine.url):
print("Creating DB...")
create_database(engine.url)
createTables(engine)
create_database(engine.url) # type: ignore
create_tables(engine)


def get_session():
def get_session() -> Generator[Session, Any, None]:
db_session = Session(engine)
try:
yield db_session
Expand Down
5 changes: 3 additions & 2 deletions src/models/turnilo_dashboard.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from typing import Optional
from sqlmodel import Field, Session, SQLModel, UniqueConstraint
from sqlmodel import Field, SQLModel, UniqueConstraint


class TurniloDashboard(SQLModel, table=True):
__tablename__ = "turniloDashboards"
__tablename__ = "turniloDashboards" # type: ignore
__table_args__ = (UniqueConstraint('dataCube', 'shortName', name='_dataCube_shortName'),)

id: Optional[int] = Field(default=None, primary_key=True, index=True)
Expand Down
51 changes: 29 additions & 22 deletions src/routes/routes.py
Original file line number Diff line number Diff line change
@@ -1,70 +1,77 @@
from fastapi import APIRouter, Depends, HTTPException, status, Path
from fastapi import APIRouter, Depends, HTTPException
from typing import List
from sqlalchemy.orm import Session
from models.turnilo_dashboard import TurniloDashboard
from services.turnilo_dashboards import *
from services import turnilo_dashboards as td

from constants import *
import constants
import data.database as db

api_router = APIRouter()

### Dashboards ###

#GET
# GET


@api_router.get(
URL_PATH+"/turnilo/dashboards/",
constants.URL_PATH + "/turnilo/dashboards/",
response_model=List[TurniloDashboard],
summary="Gets all Turnilo dashboards"
)
def turnilo_get_dashboards(db_session: Session = Depends(db.get_session)):
return dashboards_get_all(db_session)
return td.dashboards_get_all(db_session)


@api_router.get(
URL_PATH+"/turnilo/dashboards/{id}",
constants.URL_PATH + "/turnilo/dashboards/{id}",
response_model=TurniloDashboard,
summary="Get a Turnilo dashboard by id (integer)"
)
def turnilo_get_dashboard_id(id:str, db_session: Session = Depends(db.get_session)):
def turnilo_get_dashboard_id(id: str, db_session: Session = Depends(db.get_session)):
try:
int_id = int(id)
except:
except BaseException:
raise HTTPException(status_code=400, detail="Id is not an integer")
return dashboards_get_id(db_session, int_id)
return td.dashboards_get_id(db_session, int_id)

# POST


#POST
@api_router.post(
URL_PATH+"/turnilo/dashboards/",
constants.URL_PATH + "/turnilo/dashboards/",
response_model=TurniloDashboard,
summary="Create a Turnilo dashboard. A unique id will be assigned."
)
def turnilo_create_dashboard(dashboard: TurniloDashboard, db_session: Session = Depends(db.get_session)):
return dashboards_create(db_session, dashboard)
return td.dashboards_create(db_session, dashboard)


#PUT
# PUT
@api_router.put(
URL_PATH+"/turnilo/dashboards/{id}",
constants.URL_PATH + "/turnilo/dashboards/{id}",
response_model=TurniloDashboard,
summary="Update/replace a Turnilo dashboard. The dashboard (id) must exist"
)
def turnilo_update_dashboard(id:str, dashboard: TurniloDashboard, db_session: Session = Depends(db.get_session)):
def turnilo_update_dashboard(id: str, dashboard: TurniloDashboard, db_session: Session = Depends(db.get_session)):
try:
int_id = int(id)
dashboard.id = int_id
except:
except BaseException:
raise HTTPException(status_code=400, detail="Id is not an integer")
return dashboards_update(db_session, dashboard)
return td.dashboards_update(db_session, dashboard)

# DELETE


#DELETE
@api_router.delete(
URL_PATH+"/turnilo/dashboards/{id}",
constants.URL_PATH + "/turnilo/dashboards/{id}",
response_model=TurniloDashboard,
summary="Delete a Turnilo dashboard"
)
def turnilo_delete_dashboard(id: str, db_session: Session = Depends(db.get_session)):
try:
int_id = int(id)
except:
except BaseException:
raise HTTPException(status_code=400, detail="Id is not an integer")
return dashboards_delete(db_session, id)
return td.dashboards_delete(db_session, int_id)
44 changes: 28 additions & 16 deletions src/services/turnilo_dashboards.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
from sqlmodel import Session
from typing import List
from sqlalchemy.orm import Session
from sqlalchemy import exc
from models.turnilo_dashboard import TurniloDashboard
from fastapi import HTTPException

#Turnilo Dashboards
def dashboards_get_all(session: Session):
# Turnilo Dashboards


def dashboards_get_all(session: Session) -> List[TurniloDashboard]:
return session.query(TurniloDashboard).all()
def _dashboards_return_single_obj(results):
if results == None or len(results) == 0:


def _dashboards_return_single_obj(results: List[TurniloDashboard]):
if results is None or len(results) == 0:
raise HTTPException(status_code=404, detail="Item not found")
elif len(results) > 1:
raise HTTPException(status_code=500, detail="Corrupted state. Get query returned > 1 result")
return results[0]
def dashboards_get_id(session: Session, _id: int):
results = session.query(TurniloDashboard).filter(TurniloDashboard.id == _id).all()


def dashboards_get_id(session: Session, _id: int) -> TurniloDashboard:
results: List[TurniloDashboard] = session.query(TurniloDashboard).filter_by(id=_id).all()
return _dashboards_return_single_obj(results)
def dashboards_create(session: Session, dashboard: TurniloDashboard):


def dashboards_create(session: Session, dashboard: TurniloDashboard) -> TurniloDashboard:
if dashboard.id:
raise HTTPException(status_code=400, detail="'id' must NOT be set")
if not dashboard.shortName or dashboard.shortName == "":
Expand All @@ -26,34 +35,37 @@ def dashboards_create(session: Session, dashboard: TurniloDashboard):
except exc.IntegrityError as e:
print(str(e))
raise HTTPException(status_code=400, detail="Integrity error: duplicated datacube+shortName")
print("Created dashboard: "+str(dashboard.id))
print("Created dashboard: " + str(dashboard.id))
print(dashboard)
return dashboard
def dashboards_update(session: Session, dashboard: TurniloDashboard):


def dashboards_update(session: Session, dashboard: TurniloDashboard) -> TurniloDashboard:
if not dashboard.id:
raise HTTPException(status_code=400, detail="'id' MUST be set")
if not dashboard.shortName or dashboard.shortName == "":
raise HTTPException(status_code=400, detail="shortName not present or empty")

#First check if it exists
# First check if it exists
dashboards_get_id(session, dashboard.id)
try:
session.merge(dashboard)
session.commit()
except exc.IntegrityError as e:
print(str(e))
raise HTTPException(status_code=400, detail="Integrity error: duplicated datacube+shortName")
print("Updated dashboard:"+str(dashboard.id))
print("Updated dashboard:" + str(dashboard.id))
print(dashboard)
return dashboard

def dashboards_delete(session: Session, _id: int):
dashboard=None

def dashboards_delete(session: Session, _id: int) -> TurniloDashboard:
dashboard = None
try:
dashboard = session.query(TurniloDashboard).filter_by(id=_id).one()
except:
except BaseException:
pass
if dashboard == None:
if dashboard is None:
raise HTTPException(status_code=404, detail="Item not found")
session.delete(dashboard)
session.commit()
Expand Down
Loading
Loading