Skip to content

Commit

Permalink
Black for formatting (#54)
Browse files Browse the repository at this point in the history
* black for auto formatting
* isort and black are happy with each other
* formatting by black and isort

---------

Signed-off-by: Christian Henkel <[email protected]>
  • Loading branch information
ct2034 committed Oct 6, 2024
1 parent c67d4be commit 6a75d45
Show file tree
Hide file tree
Showing 68 changed files with 2,915 additions and 2,044 deletions.
6 changes: 6 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ repos:
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
# black for auto-formatting
- repo: https://github.com/psf/black
rev: 24.8.0
hooks:
- id: black
language_version: python3.10
# same as lint.yml
# - repo: https://github.com/pycqa/pylint
# rev: v3.3.1
Expand Down
30 changes: 15 additions & 15 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@

# mypy: ignore-errors

project = 'CONVINCE Model Checking Components'
copyright = '2024'
author = 'CONVINCE Consortium'
project = "CONVINCE Model Checking Components"
copyright = "2024"
author = "CONVINCE Consortium"

release = '0.1'
version = '0.1.0'
release = "0.1"
version = "0.1.0"

# -- General configuration

extensions = [
'sphinx.ext.autosummary',
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
"sphinx.ext.autosummary",
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
# 'myst_parser',
# 'autodoc2',
]
Expand All @@ -26,14 +26,14 @@
# 'sphinx': ('https://www.sphinx-doc.org/en/master/', None),
# 'networkx': ('https://networkx.org/documentation/stable/', None),
# }
intersphinx_disabled_domains = ['std']
intersphinx_disabled_domains = ["std"]

templates_path = ['_templates']
templates_path = ["_templates"]

# -- Options for HTML output

html_theme = 'sphinx_rtd_theme'
html_logo = 'convince_logo_horizontal_200p.png'
html_theme = "sphinx_rtd_theme"
html_logo = "convince_logo_horizontal_200p.png"
html_theme_options = {
# 'analytics_id': 'G-XXXXXXXXXX', # Provided by Google in your dashboard
# 'analytics_anonymize_ip': False,
Expand All @@ -50,11 +50,11 @@
# 'includehidden': True,
# 'titles_only': False
}
html_static_path = ['_static']
html_static_path = ["_static"]
# html_css_files = [
# 'css/custom.css',
# ]
html_style = 'css/custom.css'
html_style = "css/custom.css"

# -- Options for EPUB output
epub_show_urls = 'footnote'
epub_show_urls = "footnote"
11 changes: 7 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,17 @@ dev = [
"bumpver"
]

[isort]
profile = "google"
line_length = 100

[tool.pylint.main]
disable = [
"C0114", # Missing module docstring
"E0401", # Unable to import
"R0401", # Cyclic import
"W0511", # TODO comments (we need them)
]

[tool.black]
line-length = 100

[tool.isort]
profile = "black"
line_length = 100
34 changes: 19 additions & 15 deletions src/as2fm/as2fm_common/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ def remove_namespace(tag: str) -> str:
:param tag: The tag to remove the namespace from.
:return: The tag without the namespace.
"""
if '}' in tag:
tag_wo_ns = tag.split('}')[-1]
if "}" in tag:
tag_wo_ns = tag.split("}")[-1]
else:
tag_wo_ns = tag
return tag_wo_ns
Expand All @@ -61,19 +61,19 @@ def get_default_expression_for_type(field_type: Type[ValidTypes]) -> ValidTypes:
"""Generate a default expression for a field type."""
assert field_type in get_args(ValidTypes), f"Error: Unsupported data type {field_type}."
if field_type is MutableSequence[int]:
return array('i')
return array("i")
elif field_type is MutableSequence[float]:
return array('d')
return array("d")
else:
return field_type()


def value_to_type(value: ValidTypes) -> Type[ValidTypes]:
"""Convert a value to a type."""
if isinstance(value, array):
if value.typecode == 'i':
if value.typecode == "i":
return MutableSequence[int]
elif value.typecode == 'd':
elif value.typecode == "d":
return MutableSequence[float]
else:
raise ValueError(f"Type of array '{value.typecode}' not supported.")
Expand All @@ -99,22 +99,26 @@ def value_to_string(value: ValidTypes) -> str:
def string_to_value(value_str: str, value_type: Type[ValidTypes]) -> ValidTypes:
"""Convert a string to a value of the desired type."""
value_str = value_str.strip()
assert isinstance(value_str, str), \
f"Error: provided value is of type {type(value_str)}, expected a string."
assert isinstance(
value_str, str
), f"Error: provided value is of type {type(value_str)}, expected a string."
assert len(value_str) > 0, "Error: provided value is an empty string, cannot convert."
is_array_value = value_str.startswith('[') and value_str.endswith(']')
is_array_value = value_str.startswith("[") and value_str.endswith("]")
if not is_array_value:
assert value_type in (bool, int, float), \
f"Error: the value {value_str} shall be converted to a base type."
assert value_type in (
bool,
int,
float,
), f"Error: the value {value_str} shall be converted to a base type."
return value_type(value_str)
else:
str_entries = value_str.strip('[]').split(',')
if str_entries == ['']:
str_entries = value_str.strip("[]").split(",")
if str_entries == [""]:
str_entries = []
if value_type is MutableSequence[int]:
return array('i', [int(v) for v in str_entries])
return array("i", [int(v) for v in str_entries])
elif value_type is MutableSequence[float]:
return array('d', [float(v) for v in str_entries])
return array("d", [float(v) for v in str_entries])
else:
raise ValueError(f"Unsupported value type {value_type}.")

Expand Down
17 changes: 11 additions & 6 deletions src/as2fm/as2fm_common/ecmascript_interpretation.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@


def interpret_ecma_script_expr(
expr: str, variables: Optional[Dict[str, ValidTypes]] = None) -> object:
expr: str, variables: Optional[Dict[str, ValidTypes]] = None
) -> object:
"""
Interpret the ECMA script expression.
Expand All @@ -54,12 +55,16 @@ def interpret_ecma_script_expr(
if all(isinstance(x, int) for x in res_as_list):
return array("i", res_as_list)
else:
return array('d', res_as_list)
return array("d", res_as_list)
else:
raise ValueError(f"Expected expr. {expr} to be of type {BasicJsTypes} or "
f"an array, got '{type(expr_result._obj)}'")
raise ValueError(
f"Expected expr. {expr} to be of type {BasicJsTypes} or "
f"an array, got '{type(expr_result._obj)}'"
)
elif isinstance(expr_result, array):
return expr_result
else:
raise ValueError(f"Expected expr. {expr} to be of type {BasicJsTypes} or "
f"JsObjectWrapper, got '{type(expr_result)}'")
raise ValueError(
f"Expected expr. {expr} to be of type {BasicJsTypes} or "
f"JsObjectWrapper, got '{type(expr_result)}'"
)
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@
from os import path
from typing import List

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


def to_cm(value: float) -> int:
Expand Down Expand Up @@ -61,23 +65,28 @@ def __convince_env_model_to_jani(base_model: JaniModel, env_model: dict):
# The robot pose should be stored using integers -> centimeters and degrees
base_model.add_variable(f"robots.{robot_name}.pose.x_cm", int, to_cm(robot_pose["x"]))
base_model.add_variable(f"robots.{robot_name}.pose.y_cm", int, to_cm(robot_pose["y"]))
base_model.add_variable(f"robots.{robot_name}.pose.theta_deg", int,
to_deg(robot_pose["theta"]))
base_model.add_variable(
f"robots.{robot_name}.pose.theta_deg", int, to_deg(robot_pose["theta"])
)
base_model.add_variable(f"robots.{robot_name}.pose.x", float, transient=True)
base_model.add_variable(f"robots.{robot_name}.pose.y", float, transient=True)
base_model.add_variable(f"robots.{robot_name}.pose.theta", float, transient=True)
base_model.add_variable(f"robots.{robot_name}.goal.x", float, transient=True)
base_model.add_variable(f"robots.{robot_name}.goal.y", float, transient=True)
base_model.add_variable(f"robots.{robot_name}.goal.theta", float, transient=True)
robot_shape = robot["shape"]
base_model.add_constant(f"robots.{robot_name}.shape.radius", float,
float(robot_shape["radius"]))
base_model.add_constant(f"robots.{robot_name}.shape.height", float,
float(robot_shape["height"]))
base_model.add_constant(f"robots.{robot_name}.linear_velocity", float,
float(robot["linear_velocity"]))
base_model.add_constant(f"robots.{robot_name}.angular_velocity", float,
float(robot["angular_velocity"]))
base_model.add_constant(
f"robots.{robot_name}.shape.radius", float, float(robot_shape["radius"])
)
base_model.add_constant(
f"robots.{robot_name}.shape.height", float, float(robot_shape["height"])
)
base_model.add_constant(
f"robots.{robot_name}.linear_velocity", float, float(robot["linear_velocity"])
)
base_model.add_constant(
f"robots.{robot_name}.angular_velocity", float, float(robot["angular_velocity"])
)
if "obstacles" in env_model:
# Extract the obstacles from the env_model
# TODO
Expand Down Expand Up @@ -111,8 +120,9 @@ def __convince_properties_to_jani(base_model: JaniModel, properties: List[dict])
assert isinstance(base_model, JaniModel), "The base_model should be a JaniModel instance"
for property_dict in properties:
assert isinstance(property_dict, dict), "The properties list should contain dictionaries"
base_model.add_jani_property(JaniProperty(property_dict["name"],
property_dict["expression"]))
base_model.add_jani_property(
JaniProperty(property_dict["name"], property_dict["expression"])
)


def convince_jani_parser(base_model: JaniModel, convince_jani_path: str):
Expand All @@ -122,14 +132,14 @@ def convince_jani_parser(base_model: JaniModel, convince_jani_path: str):
# Check if the convince_jani_path is a file
assert path.isfile(convince_jani_path), "The convince_jani_path should be a file"
# Read the convince-jani file
with open(convince_jani_path, "r", encoding='utf-8') as file:
with open(convince_jani_path, "r", encoding="utf-8") as file:
convince_jani_json = json.load(file)
# ---- Metadata ----
base_model.set_name(convince_jani_json["name"])
# Make sure we are loading a convince-jani file
assert "features" in convince_jani_json and \
"convince_extensions" in convince_jani_json["features"], \
"The provided file is not a convince-jani file (missing feature entry)"
assert (
"features" in convince_jani_json and "convince_extensions" in convince_jani_json["features"]
), "The provided file is not a convince-jani file (missing feature entry)"
# Extract the environment model from the convince-jani file
# ---- Environment Model ----
__convince_env_model_to_jani(base_model, convince_jani_json["rob_env_model"])
Expand Down
5 changes: 2 additions & 3 deletions src/as2fm/jani_generator/jani_entries/jani_assignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
from typing import Dict

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


class JaniAssignment:
Expand All @@ -43,5 +42,5 @@ def as_dict(self, constants: Dict[str, JaniConstant]):
return {
"ref": self._var_name.as_dict(),
"value": expanded_value.as_dict(),
"index": self._index
"index": self._index,
}
40 changes: 23 additions & 17 deletions src/as2fm/jani_generator/jani_entries/jani_automaton.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@

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

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


class JaniAutomaton:
Expand All @@ -36,8 +35,7 @@ def __init__(self, *, automaton_dict: Optional[Dict[str, Any]] = None):
if automaton_dict is None:
return
self._name = automaton_dict["name"]
self._generate_locations(
automaton_dict["locations"], automaton_dict["initial-locations"])
self._generate_locations(automaton_dict["locations"], automaton_dict["initial-locations"])
self._generate_variables(automaton_dict.get("variables", []))
self._generate_edges(automaton_dict["edges"])

Expand All @@ -56,15 +54,16 @@ def get_initial_locations(self) -> Set[str]:
return self._initial_locations

def make_initial(self, location_name: str):
assert location_name in self._locations, \
f"Location {location_name} must exist in the automaton"
assert (
location_name in self._locations
), f"Location {location_name} must exist in the automaton"
self._initial_locations.add(location_name)

def unset_initial(self, location_name: str):
assert location_name in self._locations, \
f"Location {location_name} must exist in the automaton"
assert location_name in self._initial_locations, \
f"Location {location_name} must be initial"
assert (
location_name in self._locations
), f"Location {location_name} must exist in the automaton"
assert location_name in self._initial_locations, f"Location {location_name} must be initial"
self._initial_locations.remove(location_name)

def add_variable(self, variable: JaniVariable):
Expand All @@ -90,8 +89,9 @@ 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[Dict[str, Any]], 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 @@ -106,8 +106,13 @@ def _generate_variables(self, variable_list: List[dict]):
if "transient" in variable:
is_transient = variable["transient"]
var_type = JaniVariable.python_type_from_json(variable["type"])
self._local_variables.update({variable["name"]: JaniVariable(
variable["name"], var_type, init_expr, is_transient)})
self._local_variables.update(
{
variable["name"]: JaniVariable(
variable["name"], var_type, init_expr, is_transient
)
}
)

def _generate_edges(self, edge_list: List[dict]):
for edge in edge_list:
Expand All @@ -122,7 +127,7 @@ def get_actions(self) -> Set[str]:
actions.add(action)
return actions

def merge(self, other: 'JaniAutomaton'):
def merge(self, other: "JaniAutomaton"):
assert self._name == other.get_name(), "Automaton names must match"
self._locations.update(other._locations)
self._initial_locations.update(other._initial_locations)
Expand All @@ -134,9 +139,10 @@ def as_dict(self, constant: Dict[str, JaniConstant]):
"name": self._name,
"locations": [{"name": location} for location in sorted(self._locations)],
"initial-locations": sorted(list(self._initial_locations)),
"edges": [edge.as_dict(constant) for edge in self._edges]
"edges": [edge.as_dict(constant) for edge in self._edges],
}
if len(self._local_variables) > 0:
automaton_dict.update(
{"variables": [jani_var.as_dict() for jani_var in self._local_variables.values()]})
{"variables": [jani_var.as_dict() for jani_var in self._local_variables.values()]}
)
return automaton_dict
Loading

0 comments on commit 6a75d45

Please sign in to comment.