Contribution¶
Code Style¶
Naming conversions¶
Still not written in stone but the snake_case
seems to dominate the code base.
If you are new to the project, take up that one.
Most importantly, use descriptive names and stick to one style and use it consequently.
Regarding functions, variables, class etc. we follow the good advice of PEP8.
Note
Functions: Please use an underscore like _spam_and_helps()
for functions which should not be used outside of the sub-package (package).
Start function names without an underscore if they are meant to be used outside of the package/sub-package. E. g. flying_circus()
.
For the rest, it is still to be defined. But we basically follow PEP8, but do not forget how PEP8 itself starts:
“A Foolish Consistency is the Hobgoblin of Little Minds”
So use it when it makes sense, and do not where it does not. We would even suggest looking for an auto-pep8 plug-in for your favourite IDE or text editor. Or go bare bones and get something like flake8 to check your code. If it is too annoying, you can always add some guidelines to be ignored. But at the and of the day, it will help you and us to read the code.
Todo
Look into rivus.main.rivus
and reformat code where it makes sense.
(Mathematical notation vs. descriptiveness)
Unittests¶
Note
Unit tests are criteria for pull-request acceptance.
As several bugs could have been avoided with unit tests, we want to embrace testing in the development workflow.
You can find and extend the tests in rivus-repo/rivus/tests/test_*.py
Just add your own test_subpackage.py and start with the following skeleton:
import unittest
# import what you want to test with an absolute path.
# If I want to test line_length from main.rivus:
from rivus.main.rivus import line_length
# give a nice class name.
class RivusMainTest(unittest.TestCase):
def test_line_length(self):
# here comes the test logic
# self.assertTrue(4/2 == 4//2, msg='What? Is not that always true???')
pass
To run all tests:
>>> cd /to/rivus/repo/
>>> python -m unittest
----------------------------------------------------------------------
Ran 10 tests in 4.572s
OK
To run specific test(s):
>>> cd /to/rivus/repo/
>>> python -m unittest rivus.tests.test_db
----------------------------------------------------------------------
Ran 1 test in 1.213s
OK
Profiling¶
Although the whole project is not yet in a performance oriented phase, it can be very helpful in the long run if more and more profiling is involved within the contributions.
For decision between short expression: use timeit.timeit()
.
E.g. is .at[]
or .loc[]
indexer slower from a DataFrame?
>>> import timeit.timeit as tit
>>> dfout = m.r_out.to_frame() # m is a rivus problem instance
>>> tit("m.r_out.loc['Gas power plant', 'CO2']", number=1000, globals=dict(m=m))
>>> tit("dfout.at[('Gas power plant', 'CO2'), 'ratio']", number=1000, globals=dict(dfout=dfout))
To detect overall (function-level) hotspots (where the most time is spent) you can use cProfile with pstats. See blog post
python -m cProfile -o runme.profile runme.py # Execute with profiler
python -m pstats runme.profile # Interactive analyser
% sort cumulative
% stats 10
To go deeper, you can use the jupyter magic, %lprun (line_profiler). See end of tutorial and other
%load_ext line_profiler
%lprun -f slow_functions.main slow_functions.main()
Note
Profiling is encouraged before pull-request.
Documentation¶
Nobody can explain better what your code does than you. The doc-strings are essential, and I would not suppose anybody would submit code without it ;)
Please take the time and jump into the conventions of RtD the following short description should be enough to get you started and ensure the success of your contribution.
Note
We use nepoleon (autodoc) extensions to parse the doc-strings. You can decide whether you choose NumPy or Google style.
Google it, there is a good chance that there is already a plug-in for your favourite IDE or text editor. (Yes, there is even one for vim…)
The whole RtD (Sphinx) workflow builds on rST. So format your Examples, Notes, References in the doc-strings also with rST syntax.
Doc-string template:
"""Summary line.
Extended description of function.
Parameters
----------
arg1 : int
Description of arg1
arg2 : str
Description of arg2
Returns
-------
bool
Description of return value
Example
--------
::
this_will = 'be formatted as nice code!'
Note
----
+ This is a bullet list
+ E.g. for limitations...
.. note::
This will draw attention to the content.
.. warning::
This is for deprecate warnings and such.
"""
Note
For autodoc/napoleon to work, readthedocs must be able to build the whole
project. It will create a new environment and install the packages from
environment.yml. This is told to readthedocs through the readthedocs.yaml
config file.
See project structure
The whole process of the documentation is depicted in the following figure.
How to write (and build) documentation locally:
-
pip install sphinx sphinx-autodoc
-
pip install sphinx_rtd_theme
Build the docs manually into doc/_build/html/
cd /rivus/repo/doc make html
Or start autobuild, which will detect changes and autobuild the new html.
cd /rivus/repo sphinx-autobuild doc/ doc/_build/html
Tips:
- online table editor
- online pandoc converter It is an anything to anything converter. Here: (HTML, Markdown, …) -> rST
- online rST/Sphinx editor
- You can also try Atom and its rST packages.
Note
Documentation is a criteria for pull-request acceptance.
Doc TODOs¶
Summary of the ToDos from the whole documentation.
Todo
Look into rivus.main.rivus
and reformat code where it makes sense.
(Mathematical notation vs. descriptiveness)
(The original entry is located in /home/docs/checkouts/readthedocs.org/user_builds/rivus/checkouts/latest/doc/contribution.rst, line 33.)
Todo
Set version number to 0.2 after accepting the PRs
(The original entry is located in /home/docs/checkouts/readthedocs.org/user_builds/rivus/checkouts/latest/doc/index.rst, line 81.)
Todo
Extract description from ojdo’s thesis
(The original entry is located in /home/docs/checkouts/readthedocs.org/user_builds/rivus/checkouts/latest/doc/reference_math.rst, line 5.)