Skip to content

Commit

Permalink
Adding the usual Linters (#8)
Browse files Browse the repository at this point in the history
Signed-off-by: Christian Henkel <[email protected]>
Co-authored-by: Marco Lampacrescia <[email protected]>
  • Loading branch information
ct2034 and MarcoLm993 authored Aug 7, 2024
1 parent 8c6666a commit 8e1829f
Show file tree
Hide file tree
Showing 50 changed files with 566 additions and 381 deletions.
77 changes: 77 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Lint
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
build:
name: ${{ matrix.package }} ⏩ ${{ matrix.linter }}
strategy:
fail-fast: false
matrix:
linter: [
# "pylint",
# "pycodestyle",
# "flake8",
"mypy",
"isort"
]
package: [ "jani_generator", "as2fm_common", "scxml_converter" ]
include:
# (for humble):
- python-version: "3.10"
# os: "ubuntu-latest"
runs-on: ubuntu-latest

steps:
- uses: szenius/[email protected]
with:
timezoneLinux: "Europe/Berlin"
- uses: actions/checkout@v3
# Get bt_tools TODO: remove after the release of bt_tools
- name: Checkout bt_tools
uses: actions/checkout@v2
with:
repository: boschresearch/bt_tools
ref: main
path: bt_tools
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Update pip
run: |
pip install --upgrade pip
pip install setuptools_rust
# Install btlib TODO: remove after the release of bt_tools
- name: Install btlib
run: |
cd bt_tools
pip install -e btlib/.
- name: Install packages
run: |
pip install jani_generator/.[dev]
pip install as2fm_common/.[dev]
pip install scxml_converter/.[dev]
- uses: marian-code/python-lint-annotate@v4
with:
python-root-list: ${{ matrix.package }}/src/${{ matrix.package }}
python-version: ${{ matrix.python-version }}
use-pylint: ${{ matrix.linter == 'pylint' }}
use-pycodestyle: ${{ matrix.linter == 'pycodestyle' }}
use-flake8: ${{ matrix.linter == 'flake8' }}
use-black: false
use-mypy: ${{ matrix.linter == 'mypy' }}
use-isort: ${{ matrix.linter == 'isort' }}
use-vulture: false
use-pydocstyle: false
extra-pylint-options: ""
extra-pycodestyle-options: ""
extra-flake8-options: ""
extra-black-options: ""
extra-mypy-options: "--ignore-missing-imports"
extra-isort-options: ""
8 changes: 6 additions & 2 deletions as2fm_common/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ keywords = []
dependencies = [

]
requires-python = ">=3.7"
requires-python = ">=3.10"

[project.optional-dependencies]
dev = ["pytest", "pytest-cov", "pycodestyle", "flake8", "mypy", "isort", "bumpver"]

[isort]
profile = "google"
profile = "google"
line_length = 100

[flake8]
max_line_length = 100
8 changes: 6 additions & 2 deletions jani_generator/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependencies = [
"js2py",
"esprima"
]
requires-python = ">=3.7"
requires-python = ">=3.10"

[project.optional-dependencies]
dev = ["pytest", "pytest-cov", "pycodestyle", "flake8", "mypy", "isort", "bumpver"]
Expand All @@ -31,4 +31,8 @@ convince_to_plain_jani = "jani_generator.main:main_convince_to_plain_jani"
scxml_to_jani = "jani_generator.main:main_scxml_to_jani"

[isort]
profile = "google"
profile = "google"
line_length = 100

[flake8]
max_line_length = 100
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
Module to convert convince-flavored robotic, specific jani into plain jani.
"""

from typing import List

from os import path
import json
from jani_generator.jani_entries import JaniModel, JaniAutomaton, JaniComposition, JaniProperty
from math import degrees
from os import path
from typing import List

from jani_generator.jani_entries import (JaniAutomaton, JaniComposition,
JaniModel, JaniProperty)


def to_cm(value: float) -> int:
Expand Down
2 changes: 2 additions & 0 deletions jani_generator/src/jani_generator/jani_entries/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# isort: skip_file
# Skipping file to avoid circular import problem
from .jani_value import JaniValue # noqa: F401
from .jani_expression import JaniExpression # noqa: F401
from .jani_constant import JaniConstant # noqa: F401
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
"""

from typing import Dict
from jani_generator.jani_entries import JaniExpression, JaniConstant
from jani_generator.jani_entries.jani_convince_expression_expansion import expand_expression

from jani_generator.jani_entries import JaniConstant, JaniExpression
from jani_generator.jani_entries.jani_convince_expression_expansion import \
expand_expression


class JaniAssignment:
Expand Down
16 changes: 10 additions & 6 deletions jani_generator/src/jani_generator/jani_entries/jani_automaton.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@

"""An automaton for jani."""

from typing import List, Dict, Set, Optional
from jani_generator.jani_entries import JaniEdge, JaniConstant, JaniVariable, JaniExpression
from typing import Any, Dict, List, Optional, Set

from jani_generator.jani_entries import (JaniConstant, JaniEdge,
JaniExpression, JaniVariable)


class JaniAutomaton:
def __init__(self, *, automaton_dict: Optional[dict] = None):
def __init__(self, *, automaton_dict: Optional[Dict[str, Any]] = None):
self._locations: Set[str] = set()
self._initial_locations: Set[str] = set()
self._local_variables: Dict[str, JaniVariable] = {}
Expand Down Expand Up @@ -84,7 +86,7 @@ def remove_empty_self_loop_edges(self):
"""Remove all self-loop edges from the automaton."""
self._edges = [edge for edge in self._edges if not edge.is_empty_self_loop()]

def _generate_locations(self, location_list: List[str], initial_locations: List[str]):
def _generate_locations(self, location_list: List[Dict[str, Any]], initial_locations: List[str]):
for location in location_list:
self._locations.add(location["name"])
for init_location in initial_locations:
Expand All @@ -107,10 +109,12 @@ def _generate_edges(self, edge_list: List[dict]):
jani_edge = JaniEdge(edge)
self.add_edge(jani_edge)

def get_actions(self) -> Set[JaniEdge]:
def get_actions(self) -> Set[str]:
actions = set()
for edge in self._edges:
actions.add(edge.get_action())
action = edge.get_action()
if action is not None:
actions.add(action)
return actions

def merge(self, other: 'JaniAutomaton'):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

"""This allows the composition of multiple automata in jani."""

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


class JaniComposition:
Expand Down Expand Up @@ -52,16 +52,16 @@ def add_sync(self, sync_name: str, syncs: Dict[str, str]):
:param sync_name: The name of the synchronization action
:param syncs: A dictionary relating each automaton to the action to be executed in the sync
"""
new_sync = {
"result": sync_name,
"synchronise": [None] * len(self._elements)
}
# Generate the synchronize list
sync_list: List[Optional[str]] = [None] * len(self._elements)
for automata, action in syncs.items():
assert automata in self._element_to_id, \
f"Automaton {automata} does not exist in the composition"
new_sync["synchronise"][self._element_to_id[automata]] = action
self._syncs.append(new_sync)
sync_list[self._element_to_id[automata]] = action
self._syncs.append({
"result": sync_name,
"synchronise": sync_list
})

def get_syncs_for_element(self, element: str) -> List[str]:
"""Get the existing syncs for a specific element (=automaton)."""
Expand Down
10 changes: 6 additions & 4 deletions jani_generator/src/jani_generator/jani_entries/jani_constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
"""A constant value expression."""

from typing import Type, Union, get_args
from jani_generator.jani_entries import JaniExpression, JaniValue

from jani_generator.jani_entries import JaniExpression, JaniValue

ValidTypes = Union[bool, int, float]

Expand All @@ -33,13 +33,14 @@ def __init__(self, c_name: str, c_type: Type, c_value: JaniExpression):
def name(self) -> str:
return self._name

def value(self) -> JaniValue:
def value(self) -> ValidTypes:
assert self._value is not None, "Value not set"
jani_value = self._value.value
assert jani_value is not None and jani_value.is_valid(), "The expression can't be evaluated to a constant value"
return jani_value.value()

def jani_type_from_string(str_type: str) -> ValidTypes:
@staticmethod
def jani_type_from_string(str_type: str) -> Type[ValidTypes]:
"""
Translate a (Jani) type string to a Python type.
"""
Expand All @@ -53,7 +54,8 @@ def jani_type_from_string(str_type: str) -> ValidTypes:
raise ValueError(f"Type {str_type} not supported by Jani")

# TODO: Move this to a util function file
def jani_type_to_string(c_type: ValidTypes) -> str:
@staticmethod
def jani_type_to_string(c_type: Type[ValidTypes]) -> str:
"""
Translate a Python type to the name of the type in Jani.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@

"""Expand expressions into jani."""

from typing import Dict
from jani_generator.jani_entries.jani_expression_generator import minus_operator, plus_operator, \
equal_operator, max_operator, min_operator, greater_equal_operator, lower_operator, \
and_operator, or_operator, if_operator, multiply_operator, divide_operator, pow_operator, \
abs_operator, floor_operator, modulo_operator
from jani_generator.jani_entries import JaniExpression, JaniConstant
from math import pi
from typing import Dict, Union

from jani_generator.jani_entries import JaniConstant, JaniExpression, JaniValue
from jani_generator.jani_entries.jani_expression_generator import (
abs_operator, and_operator, divide_operator, equal_operator,
floor_operator, greater_equal_operator, if_operator, lower_operator,
max_operator, min_operator, minus_operator, modulo_operator,
multiply_operator, or_operator, plus_operator, pow_operator)

BASIC_EXPRESSIONS_MAPPING = {
"-": "-",
Expand Down Expand Up @@ -277,8 +278,12 @@ def __expression_interpolation(
jani_expression: JaniExpression, jani_constants: Dict[str, JaniConstant]) -> JaniExpression:
assert isinstance(jani_expression, JaniExpression), "The input must be a JaniExpression"
assert jani_expression.op == "intersect"
robot_name = jani_expression.operands["robot"].identifier
barrier_name = jani_expression.operands["barrier"].identifier
robot_op = jani_expression.operands["robot"]
assert isinstance(robot_op, JaniExpression), "The robot operand must be a JaniExpression"
barrier_op = jani_expression.operands["barrier"]
assert isinstance(barrier_op, JaniExpression), "The barrier operand must be a JaniExpression"
robot_name = robot_op.identifier
barrier_name = barrier_op.identifier
if barrier_name == "all":
return max_operator(
__expression_interpolation_next_boundaries(jani_constants, robot_name, 0),
Expand Down Expand Up @@ -345,8 +350,12 @@ def __expression_distance(
jani_expression: JaniExpression, jani_constants: Dict[str, JaniConstant]) -> JaniExpression:
assert isinstance(jani_expression, JaniExpression), "The input must be a JaniExpression"
assert jani_expression.op == "distance"
robot_name = jani_expression.operands["robot"].identifier
barrier_name = jani_expression.operands["barrier"].identifier
robot_op = jani_expression.operands["robot"]
assert isinstance(robot_op, JaniExpression), "The robot operand must be a JaniExpression"
barrier_op = jani_expression.operands["barrier"]
assert isinstance(barrier_op, JaniExpression), "The barrier operand must be a JaniExpression"
robot_name = robot_op.identifier
barrier_name = barrier_op.identifier
if barrier_name == "all":
return min_operator(
__expression_distance_next_boundaries(jani_constants, robot_name, 0),
Expand All @@ -362,7 +371,9 @@ def __expression_distance_to_point(
jani_expression: JaniExpression, jani_constants: Dict[str, JaniConstant]) -> JaniExpression:
assert isinstance(jani_expression, JaniExpression), "The input must be a JaniExpression"
assert jani_expression.op == "distance_to_point"
robot_name = jani_expression.operands["robot"].identifier
robot_op = jani_expression.operands["robot"]
assert isinstance(robot_op, JaniExpression), "The robot operand must be a JaniExpression"
robot_name = robot_op.identifier
target_x_cm = to_cm_operator(expand_expression(jani_expression.operands["x"], jani_constants))
target_y_cm = to_cm_operator(expand_expression(jani_expression.operands["y"], jani_constants))
robot_x_cm = f"robots.{robot_name}.pose.x_cm"
Expand All @@ -380,7 +391,7 @@ def __substitute_expression_op(expression: JaniExpression) -> JaniExpression:


def expand_expression(
expression: JaniExpression, jani_constants: Dict[str, JaniConstant]) -> JaniExpression:
expression: Union[JaniExpression, JaniValue], jani_constants: Dict[str, JaniConstant]) -> JaniExpression:
# Given a CONVINCE JaniExpression, expand it to a plain JaniExpression
assert isinstance(expression, JaniExpression), \
f"The expression should be a JaniExpression instance, found {type(expression)} instead."
Expand Down
9 changes: 6 additions & 3 deletions jani_generator/src/jani_generator/jani_entries/jani_edge.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@
"""And edge defining the possible transition from one state to another in jani."""

from typing import Dict, Optional
from jani_generator.jani_entries import JaniGuard, JaniAssignment, JaniExpression, JaniConstant
from jani_generator.jani_entries.jani_convince_expression_expansion import expand_expression

from jani_generator.jani_entries import (JaniAssignment, JaniConstant,
JaniExpression, JaniGuard)
from jani_generator.jani_entries.jani_convince_expression_expansion import \
expand_expression


class JaniEdge:
def __init__(self, edge_dict: dict):
self.location = edge_dict["location"]
self.action: str = None
self.action: Optional[str] = None
if "action" in edge_dict:
self.action = edge_dict["action"]
self.guard = None
Expand Down
Loading

0 comments on commit 8e1829f

Please sign in to comment.