Skip to content

Commit

Permalink
style: Switches to ruff for linting (#115)
Browse files Browse the repository at this point in the history
* style: Switches to ruff

* style: Fixes ruff

* style: Fixes mypy

* style: Fixes bandit

* ci: Fixes style job

* style: Fixes mypy

* ci: Fixing mypy job

* style: Fixes mypy
  • Loading branch information
frgfm authored Oct 30, 2023
1 parent a988f02 commit b550875
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 134 deletions.
5 changes: 0 additions & 5 deletions .flake8

This file was deleted.

76 changes: 28 additions & 48 deletions .github/workflows/style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,24 @@ on:
branches: main

jobs:
flake8:
ruff:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
python: [3.8]
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
architecture: x64
- name: Run flake8
run: |
pip install flake8
flake8 --version
flake8 ./
isort:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
python: [3.8]
python: [3.9]
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
architecture: x64
- name: Run isort
- name: Run ruff
run: |
pip install isort
isort --version
isort app/
if [ -n "$(git status --porcelain --untracked-files=no)" ]; then exit 1; else echo "All clear"; fi
pip install ruff==0.1.2
ruff --version
ruff check --diff .
mypy:
runs-on: ${{ matrix.os }}
Expand All @@ -61,7 +41,7 @@ jobs:
architecture: x64
- uses: abatilo/actions-poetry@v2
with:
poetry-version: "1.3.0"
poetry-version: "1.6.1"
- name: Resolve dependencies
run: poetry export -f requirements.txt --without-hashes --output requirements.txt
- name: Cache python modules
Expand All @@ -73,7 +53,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt --upgrade
pip install "mypy==1.2.0"
pip install mypy==1.6.1 pandas-stubs types-requests
- name: Run mypy
run: |
mypy --version
Expand All @@ -84,7 +64,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
python: [3.8]
python: [3.9]
steps:
- uses: actions/checkout@v2
- name: Set up Python
Expand All @@ -94,25 +74,25 @@ jobs:
architecture: x64
- name: Run black
run: |
pip install "black==22.3.0"
pip install "black==23.3.0"
black --version
black --check --diff .
#bandit:
# runs-on: ${{ matrix.os }}
# strategy:
# matrix:
# os: [ubuntu-latest]
# python: [3.8]
# steps:
# - uses: actions/checkout@v2
# - name: Set up Python
# uses: actions/setup-python@v4
# with:
# python-version: ${{ matrix.python }}
# architecture: x64
# - name: Run bandit
# run: |
# pip install bandit[toml]
# bandit --version
# bandit -r . -c pyproject.toml
bandit:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
python: [3.9]
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
architecture: x64
- name: Run bandit
run: |
pip install bandit[toml]
bandit --version
bandit -r . -c pyproject.toml
19 changes: 10 additions & 9 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
default_language_version:
python: python3.9
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v4.4.0
hooks:
- id: check-yaml
- id: check-toml
Expand All @@ -16,14 +18,13 @@ repos:
- id: debug-statements
language_version: python3
- repo: https://github.com/psf/black
rev: 22.3.0
rev: 23.3.0
hooks:
- id: black
- repo: https://github.com/pycqa/isort
rev: 5.10.1
language_version: python3.9
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: 'v0.0.290'
hooks:
- id: isort
- repo: https://github.com/PyCQA/autoflake
rev: v1.7.7
hooks:
- id: autoflake
- id: ruff
args:
- --fix
9 changes: 3 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
# this target runs checks on all files
quality:
isort . -c
flake8
ruff check .
mypy
black --check .
# bandit -r . -c pyproject.toml
autoflake -r .
bandit -r . -c pyproject.toml

# this target runs checks on all files and potentially modifies some of them
style:
isort .
black .
autoflake --in-place -r .
ruff --fix .

# Build the docker
build:
Expand Down
1 change: 0 additions & 1 deletion app/components/navbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ def Navbar(dropdown=False):
The returned 'navbar' object is an instantiation of the class dbc.Navbar.
"""

# Dropdown menu
if dropdown is True:
dropdown = dbc.DropdownMenu(
Expand Down
20 changes: 7 additions & 13 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@
app.config.suppress_callback_exceptions = True
server = app.server # Gunicorn will be looking for the server attribute of this module

response_devices = requests.get(f"{cfg.API_URL}/devices/", headers=api_client.headers, verify=False)
response_devices = requests.get(f"{cfg.API_URL}/devices/", headers=api_client.headers, verify=False, timeout=5)
# Check token expiration
if response_devices.status_code == 401:
api_client.refresh_token(cfg.API_LOGIN, cfg.API_PWD)
response_devices = requests.get(f"{cfg.API_URL}/devices/", headers=api_client.headers, verify=False)
response_devices = requests.get(f"{cfg.API_URL}/devices/", headers=api_client.headers, verify=False, timeout=5)

# Site devices
response = api_client.get_sites()
Expand Down Expand Up @@ -244,7 +244,6 @@ def update_live_alerts_data(
client so as to identify live alerts, load the associated data and trigger their display on the platform. This doc-
string should be completed but more details can be found in the comments below.
"""

if user_headers is None:
raise PreventUpdate
user_token = user_headers["Authorization"].split(" ")[1]
Expand All @@ -259,7 +258,7 @@ def update_live_alerts_data(
raise PreventUpdate

get_alerts = call_api(api_client.get_alerts_for_event, user_credentials)
_ = live_events["id"].apply(lambda x: pd.DataFrame(get_alerts(x)))
_ = live_events["id"].apply(lambda x: pd.DataFrame(get_alerts(x))) # type: ignore[arg-type, return-value]
live_alerts = pd.concat(_.values).groupby(["device_id", "event_id"]).head(15).reset_index(drop=True)

# Is there any live alert to display?
Expand Down Expand Up @@ -555,7 +554,7 @@ def manage_login_modal(n_clicks, username, password, login_storage, current_cent
form_feedback.append(html.P("Vous êtes connecté, bienvenue sur la plateforme Pyronear !"))

# Based on the user's credentials, we request the set of relevant devices
response_devices = requests.get(f"{cfg.API_URL}/devices/", headers=client.headers)
response_devices = requests.get(f"{cfg.API_URL}/devices/", headers=client.headers, timeout=5)

# We also update the site_devices dictionary, restricting it to the user's scope
response_sites = client.get_sites().json()
Expand Down Expand Up @@ -683,7 +682,6 @@ def click_new_alerts_button(n_clicks, map_style_button_label):
- If we are viewing the "risks" map, a PreventUpdate is raised and clicks on the banner will have no effect.
"""

# Deducing the style of the map in place from the map style button label
if "risques" in map_style_button_label.lower():
map_style = "alerts"
Expand Down Expand Up @@ -766,7 +764,6 @@ def change_map_zoom_and_center(login_zoom_and_center, alert_zoom_and_center, log
login_zoom_and_center and alert_zoom_and_center placeholders. The latter correspond to the recentering of the map
that takes place respectively after the user logs in and when the user clicks on one of the alert selection buttons.
"""

ctx = dash.callback_context

# If none of the input has triggered the callback, we raise a PreventUpdate
Expand Down Expand Up @@ -1035,7 +1032,6 @@ def select_alert_frame_to_display(slider_value, urls):
callback is triggered by a change in value of the slider and return the URL address of the frame to be displayed.
Like there is one alert modal per event, there is one alert slider per event, which allows to use MATCH here.
"""

if slider_value is None:
raise PreventUpdate

Expand Down Expand Up @@ -1152,7 +1148,6 @@ def change_map_style_main(map_style_button_input, alert_button_input, map_style_
- the right map object;
- the slider object if relevant.
"""

# Deducing from the map style button label, the argument that we should pass to the choose_map_style function
if current_map_style == "alerts":
arg = 1
Expand Down Expand Up @@ -1219,7 +1214,6 @@ def update_live_alerts_components(live_alerts, map_style_button_label, images_ur
To build these elements, it relies on the build_alerts_elements imported from alerts.
"""

# Deducing the style of the map in place from the map style button label
if "risques" in map_style_button_label.lower():
map_style = "alerts"
Expand Down Expand Up @@ -1320,11 +1314,11 @@ def update_alert_frame_due_to_new_event(images_to_display, last_event_id):
if "frame_URLs" in images_to_display.keys() and images_to_display["frame_URLs"] == "no_images":
raise PreventUpdate

elif list(images_to_display.keys())[0] == last_event_id:
return list(images_to_display.values())[0][-1], dash.no_update
elif next(iter(images_to_display.keys())) == last_event_id:
return next(iter(images_to_display.values()))[-1], dash.no_update

else:
return list(images_to_display.values())[0][-1], list(images_to_display.keys())[0]
return next(iter(images_to_display.values()))[-1], next(iter(images_to_display.keys()))


# @app.callback(
Expand Down
7 changes: 1 addition & 6 deletions app/pages/homepage.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ def choose_map_style(n_clicks):
- the chosen map object;
- and the slider object (simply a void string if the alerts view was chosen).
"""

# Because we start with the alerts map, if the number of clicks is even, this means that
# we are still using the "Alerts and Infrastructure" map and we may want to switch to the "Risk Scores" one
if n_clicks % 2 == 0:
Expand Down Expand Up @@ -98,7 +97,6 @@ def build_historic_fires_radio_button():
It instantiates and returns the appropriate radio button (inside a html.Center wrapping).
"""

historic_fires_radio_button = dcc.RadioItems(
options=[
{"label": "Oui", "value": 1},
Expand Down Expand Up @@ -209,8 +207,7 @@ def display_alerts_frames(n_clicks=None, img_url=None):
children=[frame_title, alert_frame, separator, alert_metadata_title, alert_metadata]
)
return html.Div(alert_frame_metadata)"""

return html.Div(alert_frame_metadata)"""
# If no button click is triggering the display of the alert frame and metadata, function returns a void string
return ""

Expand All @@ -230,7 +227,6 @@ def build_login_modal():
dal object which prevent the user from closing the modal respectively by clicking next to it and by pressing the
Escape key.
"""

return dbc.Modal(
[
dbc.ModalBody(
Expand Down Expand Up @@ -296,7 +292,6 @@ def Homepage():
It builds upon methods defined above or in alerts.py or navbar.py files to instantiate the various components.
"""

# Body container
body = dbc.Container(
[
Expand Down
17 changes: 7 additions & 10 deletions app/pages/risks.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@
# NB: for now, scores are acquired from a static json file on GitHub; the API call is still to be implemented.

# We read the GeoJSON file from the Pyro-Risk release (URL in config.py) and store it in the departments variable
departments = requests.get(cfg.GEOJSON_FILE).json()
departments = requests.get(cfg.GEOJSON_FILE, timeout=10).json()

# We fetch the department risk score json and store it in the risk_json variable
# When everything is validated, we'll request the data directly from the API
risk_json = requests.get(cfg.PYRORISK_FALLBACK).json()
risk_json = requests.get(cfg.PYRORISK_FALLBACK, timeout=10).json()

# We add to each department in the geojson a new property called "score" that corresponds to the risk level
for department in departments["features"]:
Expand Down Expand Up @@ -69,7 +69,6 @@ def build_risks_geojson_and_colorbar(opacity_level=0.75):
- a dl.GeoJSON object that allows to displays the departments' boundaries and respective risk score categories;
- a colorbar object that distinguishes, as shades of yellow and red, 8 categories of risk score from 0 to 1.
"""

# First step is to prepare the choropleth map by building the color scale corresponding to score risks
# To define 8 risk levels between 0 and 1, we need to choose 9 floats that will serve as borders
classes = [idx / 8 for idx in range(9)]
Expand All @@ -86,16 +85,16 @@ def build_risks_geojson_and_colorbar(opacity_level=0.75):

# We define the style of department delimitations on the map
# (opacity and color of borders, opacity of color backgrounds...)
scale_style = dict(weight=2, opacity=0.9, color="white", dashArray="3", fillOpacity=opacity_level)
scale_style = {"weight": 2, "opacity": 0.9, "color": "white", "dashArray": "3", "fillOpacity": opacity_level}

# We finally instantiate the dl.GeoJSON object that will be attributed to the "Niveaux de Risque" map
geojson = dl.GeoJSON(
data=departments,
id="geojson_risks",
zoomToBoundsOnClick=True,
hoverStyle=dict(weight=3, color="#666", dashArray=""),
hideout=dict(colorscale=colorscale, classes=classes, style=scale_style, color_prop="score"),
options=dict(style=dlx.choropleth.style),
hoverStyle={"weight": 3, "color": "#666", "dashArray": ""},
hideout={"colorscale": colorscale, "classes": classes, "style": scale_style, "color_prop": "score"},
options={"style": dlx.choropleth.style},
)

return geojson, colorbar
Expand All @@ -107,7 +106,6 @@ def build_opacity_slider():
that allows the user to choose the most appropriate color opacity level when displaying
the risk score associated with the various departments.
"""

slider_title = dcc.Markdown("Choisissez le niveau d'opacité des aplats de couleurs :")

slider = dcc.Slider(
Expand All @@ -119,7 +117,7 @@ def build_opacity_slider():
value=0.75,
)

slider_div = html.Div(style=dict(width=330), children=[slider_title, slider])
slider_div = html.Div(style={"width": 330}, children=[slider_title, slider])

return html.Center(slider_div)

Expand All @@ -134,7 +132,6 @@ def build_risks_map():
This function mobilises functions defined hereabove or in the utils module to
instantiate and return a dl.Map object, corresponding to the "Risk Score" view.
"""

geojson, colorbar = build_risks_geojson_and_colorbar()

map_object = dl.Map(
Expand Down
Loading

0 comments on commit b550875

Please sign in to comment.