Skip to content

Lint code with ruff #99

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
29 changes: 29 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Lint

on:
push:
branches:
- main
pull_request: ~

jobs:
lint:
name: Lint
runs-on: ubuntu-latest

steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v4

- name: Install Ruff
run: |
python -m pip install --upgrade pip
pip install ruff

- name: Check Code with Ruff
run: |
ruff check --statistics
ruff format --check
9 changes: 6 additions & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@

project = 'MAL Toolbox'
copyright = '2024, Andrei Buhaiu, Giuseppe Nebbione, Nikolaos Kakouros, Jakob Nyberg, Joakim Loxdal'
author = 'Andrei Buhaiu, Giuseppe Nebbione, Nikolaos Kakouros, Jakob Nyberg, Joakim Loxdal'
author = (
'Andrei Buhaiu, Giuseppe Nebbione, Nikolaos Kakouros, Jakob Nyberg, Joakim Loxdal'
)


# -- General configuration ---------------------------------------------------

import os
import sys

sys.path.insert(0, os.path.abspath('../')) # Source code dir relative to this file

# Add any Sphinx extension module names here, as strings. They can be
Expand Down Expand Up @@ -53,9 +56,9 @@
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme' # pip install sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme' # pip install sphinx_rtd_theme

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
# html_static_path = ['_static']
# html_static_path = ['_static']
31 changes: 15 additions & 16 deletions maltoolbox/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- encoding: utf-8 -*-
# MAL Toolbox v0.2.0
# Copyright 2024, Andrei Buhaiu.
#
Expand All @@ -16,41 +15,40 @@
#


"""
MAL-Toolbox Framework
"""
"""MAL-Toolbox Framework."""

__title__ = 'maltoolbox'
__version__ = '0.2.0'
__authors__ = ['Andrei Buhaiu',
__authors__ = [
'Andrei Buhaiu',
'Giuseppe Nebbione',
'Nikolaos Kakouros',
'Jakob Nyberg',
'Joakim Loxdal']
'Joakim Loxdal',
]
__license__ = 'Apache 2.0'
__docformat__ = 'restructuredtext en'

__all__ = ()

import os
import configparser
import logging
import os

ERROR_INCORRECT_CONFIG = 1

CONFIGFILE = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"default.conf"
)
CONFIGFILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'default.conf')

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line length seems too long - I think me and Andrei have line length set to 79 or 80

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can configure it. 88 is the common setting and the default in ruff. If you look at pyproject.toml there is a rationale behind it.

About 88 being the default, Black, which is what ruff follows, says:

Line length

You probably noticed the peculiar default line length. Black defaults to 88 characters per line, which happens to be 10% over 80. This number was found to produce significantly shorter files than sticking with 80 (the most popular), or even 79 (used by the standard library). In general, 90-ish seems like the wise choice.

If you’re paid by the lines of code you write, you can pass --line-length with a lower number. Black will try to respect that. However, sometimes it won’t be able to without breaking other rules. In those rare cases, auto-formatted code will exceed your allotted limit.

It is also the case that if you have a hard limit of 80, then you may have one or two characters that go over it. It is a good practice, and there are plugins that allow for a 10% more line length than the configured one so that you don't have to sacrifice readability to satisfy a linter or a hard rule. 10% of 80 is 88. This may be a coincidence, but I doubt it.

In general, my approach to these things has been to go with what the defaults are, and by defaults, I mean also the tools of the trade such as ruff and black. This is similar to how I don't override application defaults anymore; use and learn what is there instead of learning your own things. This keeps peace of mind and reduces the maintenance burden.

But if you need this changed, it can be changed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally think 88 is too long. Looking at that line it is too long (more breath with shorter lines).

config = configparser.ConfigParser()
config.read(CONFIGFILE)

if 'logging' not in config:
raise ValueError('Config file is missing essential information, cannot proceed.')
msg = 'Config file is missing essential information, cannot proceed.'
raise ValueError(msg)

if 'log_file' not in config['logging']:
raise ValueError('Config file is missing a log_file location, cannot proceed.')
msg = 'Config file is missing a log_file location, cannot proceed.'
raise ValueError(msg)

log_configs = {
'log_file': config['logging']['log_file'],
Expand All @@ -60,9 +58,11 @@
'langspec_file': config['logging']['langspec_file'],
}

os.makedirs(os.path.dirname(log_configs['log_file']), exist_ok = True)
os.makedirs(os.path.dirname(log_configs['log_file']), exist_ok=True)

formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M')
formatter = logging.Formatter(
'%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M'
)
file_handler = logging.FileHandler(log_configs['log_file'], mode='w')
file_handler.setFormatter(formatter)

Expand All @@ -78,7 +78,6 @@
if 'neo4j' in config:
for term in ['uri', 'username', 'password', 'dbname']:
if term not in config['neo4j']:

msg = (
'Config file is missing essential Neo4J '
f'information: {term}, cannot proceed.'
Expand Down
42 changes: 22 additions & 20 deletions maltoolbox/__main__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""
Command-line interface for MAL toolbox operations
"""Command-line interface for MAL toolbox operations.

Usage:
maltoolbox attack-graph generate [options] <model> <lang_file>
Expand All @@ -20,58 +19,61 @@
- If --neo4j is used, the Neo4j instance should be running. The connection
parameters required for this app to reach the Neo4j instance should be
defined in the default.conf file.

"""

import logging
import json
import logging

import docopt

from maltoolbox.wrappers import create_attack_graph

from . import log_configs, neo4j_configs
from .language.compiler import MalCompiler
from .ingestors import neo4j
from .language.compiler import MalCompiler

logger = logging.getLogger(__name__)

def generate_attack_graph(
model_file: str,
lang_file: str,
send_to_neo4j: bool
) -> None:
"""Create an attack graph and optionally send to neo4j


def generate_attack_graph(model_file: str, lang_file: str, send_to_neo4j: bool) -> None:
"""Create an attack graph and optionally send to neo4j.

Args:
model_file - path to the model file
lang_file - path to the language file
send_to_neo4j - whether to ingest into neo4j or not

"""
attack_graph = create_attack_graph(lang_file, model_file)
if log_configs['attackgraph_file']:
attack_graph.save_to_file(
log_configs['attackgraph_file']
)
attack_graph.save_to_file(log_configs['attackgraph_file'])

if send_to_neo4j:
logger.debug('Ingest model graph into Neo4J database.')
neo4j.ingest_model(attack_graph.model,
neo4j.ingest_model(
attack_graph.model,
neo4j_configs['uri'],
neo4j_configs['username'],
neo4j_configs['password'],
neo4j_configs['dbname'],
delete=True)
delete=True,
)
logger.debug('Ingest attack graph into Neo4J database.')
neo4j.ingest_attack_graph(attack_graph,
neo4j.ingest_attack_graph(
attack_graph,
neo4j_configs['uri'],
neo4j_configs['username'],
neo4j_configs['password'],
neo4j_configs['dbname'],
delete=False)
delete=False,
)


def compile(lang_file: str, output_file: str) -> None:
"""Compile language and dump into output file"""
"""Compile language and dump into output file."""
compiler = MalCompiler()
with open(output_file, "w") as f:
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(compiler.compile(lang_file), f, indent=2)


Expand Down
9 changes: 4 additions & 5 deletions maltoolbox/attackgraph/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
"""
Contains tools used to generate attack graphs from MAL instance
"""Contains tools used to generate attack graphs from MAL instance
models and analyze attack graphs.
"""

from .attacker import Attacker
from .attackgraph import AttackGraph
from .node import AttackGraphNode
from .attacker import Attacker as Attacker
from .attackgraph import AttackGraph as AttackGraph
from .node import AttackGraphNode as AttackGraphNode
Loading
Loading