Project Guidelines¶
This document describes general guidelines for the Safe-DS Stub Generator.
Docstrings¶
The docstrings should use the numpydoc format. The descriptions should not start with "this" and should use imperative mood. Docstrings should not contain type hints, since they are already specified in the code. Refer to the subsections below for more details on how to document specific API elements.
Modules¶
All modules should have
- A one-line description (short summary).
- A longer description if needed (extended summary).
Example:
Classes¶
All classes should have
- A one-line description (short summary).
- A longer description if needed (extended summary).
- A description of the parameters of their
__init__
method (Parameters
section). Specify a name and a description, with a colon to separate them. Omit types and default values. - Examples that show how to use them correctly (
Examples
section).
Example:
"""
A row is a collection of named values.
Parameters
----------
data:
The data. If None, an empty row is created.
Examples
--------
>>> from safeds.data.tabular.containers import Row
>>> row = Row({"a": 1, "b": 2})
"""
Functions¶
All functions should have
- A one-line description (short summary).
- A longer description if needed (extended summary).
- A description of their parameters (
Parameters
section). Specify a name and a description, with a colon to separate them. Omit types and default values. - A description of their results (
Returns
section). Specify a name and a description, with a colon to separate them. Omit types. - A description of any exceptions that may be raised and under which conditions that may
happen (
Raises
section). - A description of any warnings that may be issued and under which conditions that may
happen (
Warns
section). - Examples that show how to use them correctly (
Examples
section).
Example:
"""
Return the value of a specified column.
Parameters
----------
column_name:
The column name.
Returns
-------
value:
The column value.
Raises
------
UnknownColumnNameError
If the row does not contain the specified column.
Examples
--------
>>> from safeds.data.tabular.containers import Row
>>> row = Row({"a": 1, "b": 2})
>>> row.get_value("a")
1
"""
Tests¶
We aim for 100% line coverage, so automated tests should be added for any new function.
File structure¶
Tests belong in the tests
folder. The file structure in the tests folder should mirror the file
structure of the src
folder.
Naming¶
Names of test functions shall start with test_should_
followed by a description of the expected behaviour,
e.g. test_should_add_column
.
DO:
DON'T:
Parametrization¶
Tests should be parametrized using @pytest.mark.parametrize
, even if there is only a single test case. This makes it
easier to add new test cases in the future. Test cases should be given descriptive IDs.
DO:
@pytest.mark.parametrize("number_of_trees", [0, -1], ids=["zero", "negative"])
def test_should_raise_if_less_than_or_equal_to_0(self, number_of_trees) -> None:
with pytest.raises(ValueError, match="The parameter 'number_of_trees' has to be greater than 0."):
RandomForest(number_of_trees=number_of_trees)
DON'T:
def test_should_raise_if_less_than_0(self, number_of_trees) -> None:
with pytest.raises(ValueError, match="The parameter 'number_of_trees' has to be greater than 0."):
RandomForest(number_of_trees=-1)
def test_should_raise_if_equal_to_0(self, number_of_trees) -> None:
with pytest.raises(ValueError, match="The parameter 'number_of_trees' has to be greater than 0."):
RandomForest(number_of_trees=0)
Code style¶
Consistency¶
If there is more than one way to solve a particular task, check how it has been solved at other places in the codebase and stick to that solution.
Sort exported classes in __init__.py
¶
Classes defined in a module that other classes shall be able to import must be defined in a list named __all__
in the
module's __init__.py
file. This list should be sorted alphabetically, to reduce the likelihood of merge conflicts when
adding new classes to it.