Skip to content
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

Create markdown docs from docstring in py files #2181

Merged
merged 43 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
73cbafc
adding pydoc-markdown yml
s-martin Dec 17, 2023
17e3cfd
add lazydocs
s-martin Dec 21, 2023
df67711
run lazydocs and pydoc-markdown parallel for testing
s-martin Dec 22, 2023
06e66e0
fix output path
s-martin Dec 22, 2023
8c56cd6
add created docs to source control
s-martin Dec 22, 2023
9b97659
fix the path to source code
s-martin Dec 22, 2023
845fe22
change filter
s-martin Dec 22, 2023
4be921c
revert last commit
s-martin Dec 22, 2023
c094768
use only pydoc-markdown
s-martin Dec 22, 2023
922c187
remove the test files from version control
s-martin Dec 26, 2023
6048444
rename script and add to pre-commit hook
s-martin Dec 26, 2023
3713175
change py file to test pre commit hook
s-martin Dec 26, 2023
70ff089
modify py file again
s-martin Dec 26, 2023
7520514
test markdown formatting
s-martin Dec 26, 2023
bf54480
updated docstring
s-martin Dec 26, 2023
535b0a7
use sphinx renderer
s-martin Dec 26, 2023
34aeebc
update markdown
s-martin Dec 26, 2023
2df3313
convert links and formatting to markdown
s-martin Dec 26, 2023
325c7ce
make link to plugin docs
s-martin Dec 26, 2023
0c4ad4f
fix comment
s-martin Dec 26, 2023
9176013
fix wrong docstring
s-martin Dec 26, 2023
fb74a4e
add more fixes to doc
s-martin Dec 28, 2023
1b6aafc
update docstring-md
s-martin Dec 28, 2023
0de16d3
rename to README.md so github picks it up directly
s-martin Dec 28, 2023
c630ce0
fix formatting
s-martin Dec 28, 2023
8106d06
improve docs
s-martin Dec 28, 2023
7caec0e
improve docs
s-martin Dec 28, 2023
998310d
fix docs
s-martin Dec 28, 2023
486ea8a
Merge remote-tracking branch 'origin/future3/develop' into future3/py…
s-martin Dec 28, 2023
f1bc657
updte docstream md
s-martin Dec 28, 2023
3315e15
fix formatting for md
s-martin Dec 28, 2023
256c4a0
fix formatting to md and check crossref
s-martin Dec 28, 2023
33c8393
fix links
s-martin Dec 28, 2023
3e6bd51
fix formatting for notes
s-martin Dec 28, 2023
a8f1893
fix links
s-martin Dec 28, 2023
365089b
revert wrong fix
s-martin Jan 2, 2024
63ecd19
Merge remote-tracking branch 'remotes/origin/future3/develop' into fu…
s-martin Jan 2, 2024
d46a0e7
fixed indentation
s-martin Jan 3, 2024
f5fc587
add generated docstring
s-martin Jan 3, 2024
bbec5de
Check for docstring in action
s-martin Jan 5, 2024
4908771
Try without request changes
s-martin Jan 5, 2024
efe5097
try request changes
s-martin Jan 13, 2024
a7279a4
remove docstring check from action
s-martin Jan 14, 2024
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
14 changes: 13 additions & 1 deletion .githooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# Checks
# - flake8 on staged python files
# Note: This only checks the modified files
# - docs build of if any python file or any doc file is staged
# - docs build of if any python file is staged
# Note: This builds the entire documentation if a changed file goes into the documentation
#
# If there are problem with this script, commit may still be done with
Expand All @@ -28,6 +28,18 @@ fi

code=$(( flake8_code ))

doc_code=0
if [[ -n $PY_FILES ]]; then
echo -e "\n**************************************************************"
echo -e "Modified Python source files. Generation markdown docs from docstring ... \n"
echo -e "**************************************************************\n"
./run_docgeneration.sh -c
doc_code=$?
echo "pydoc_markdown return code: $doc_code"
fi

code=$(( flake8_code + doc_code ))

if [[ code -gt 0 ]]; then
echo -e "\n**************************************************************"
echo -e "ERROR(s) during pre-commit checks. Aborting commit!"
Expand Down
2 changes: 2 additions & 0 deletions documentation/developers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

* [Jukebox Apps](./coreapps.md)
* [RFID Readers](./rfid)
* [Docstring API Docs (from py files)](./docstring/README.md)
* [Plugin Reference](./docstring/README.md#jukeboxplugs)
* [Feature Status](./status.md)
* [Known Issues](./known-issues.md)

Expand Down
5,914 changes: 5,914 additions & 0 deletions documentation/developers/docstring/README.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions documentation/developers/known-issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ RUN cd ${HOME} && mkdir ${ZMQ_TMP_DIR} && cd ${ZMQ_TMP_DIR}; \
make && make install
```

[libzmq details](./libzmq.md)

## Configuration

In `jukebox.yaml` (and all other config files):
Expand Down
13 changes: 13 additions & 0 deletions pydoc-markdown.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
loaders:
- type: python
search_path: [./src/jukebox]
processors:
- type: filter
# skip_empty_modules: true # Uncommenting this skips also run_jukebox etc.
- type: sphinx
- type: crossref
renderer:
type: markdown
render_toc: true
filename: ./documentation/developers/docstring/README.md
render_page_title: true
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ flake8>=4.0.0
pytest
pytest-cov
mock

# API docs generation
pydoc-markdown
15 changes: 15 additions & 0 deletions run_docgeneration.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash

# Runner script for pydoc-markdown to ensure
# - independent from working directory

# Change working directory to location of script
SOURCE=${BASH_SOURCE[0]}
SCRIPT_DIR="$(dirname "$SOURCE")"
cd "$SCRIPT_DIR" || (echo "Could not change to top-level project directory" && exit 1)

# Run pydoc-markdown
# make sure, directory exists
mkdir -p ./documentation/developers/docstring
# expects pydoc-markdown.yml at working dir
pydoc-markdown
Original file line number Diff line number Diff line change
Expand Up @@ -35,42 +35,39 @@


class battmon_ads1015(BatteryMonitorBase.BattmonBase):
'''Battery Monitor based on a ADS1015
"""Battery Monitor based on a ADS1015

CAUTION - WARNING
========================================================================
Lithium and other batteries are dangerous and must be treated with care.
Rechargeable Lithium Ion batteries are potentially hazardous and can
present a serious FIRE HAZARD if damaged, defective or improperly used.
Do not use this circuit to a lithium ion battery without expertise and
training in handling and use of batteries of this type.
Use appropriate test equipment and safety protocols during development.

There is no warranty, this may not work as expected or at all!
=========================================================================
> [!CAUTION]
> Lithium and other batteries are dangerous and must be treated with care.
> Rechargeable Lithium Ion batteries are potentially hazardous and can
> present a serious **FIRE HAZARD** if damaged, defective or improperly used.
> Do not use this circuit to a lithium ion battery without expertise and
> training in handling and use of batteries of this type.
> Use appropriate test equipment and safety protocols during development.
> There is no warranty, this may not work as expected or at all!

This script is intended to read out the Voltage of a single Cell LiIon Battery using a CY-ADS1015 Board:

3.3V
+
|
.----o----.
___ | | SDA
.--------|___|---o----o---------o AIN0 o------
| 2MΩ | | | | SCL
| .-. | | ADS1015 o------
--- | | --- | |
Battery - 1.5MΩ| | ---100nF '----o----'
2.9V-4.2V| '-' | |
| | | |
=== === === ===
3.3V
+
|
.----o----.
___ | | SDA
.--------|___|---o----o---------o AIN0 o------
| 2MΩ | | | | SCL
| .-. | | ADS1015 o------
--- | | --- | |
Battery - 1.5MΩ| | ---100nF '----o----'
2.9V-4.2V| '-' | |
| | | |
=== === === ===

Attention:
- the circuit is constantly draining the battery! (leak current up to: 2.1µA)
- the time between sample needs to be a minimum 1sec with this high impedance voltage divider
* the circuit is constantly draining the battery! (leak current up to: 2.1µA)
* the time between sample needs to be a minimum 1sec with this high impedance voltage divider
don't use the continuous conversion method!

'''
"""

def __init__(self, cfg):
super().__init__(cfg, logger)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

This effectively does:

* register a callback with components.volume to get notified when a new sound card connects
* if that is a bluetooth device, try opening an input device with similar name using
* button listeners are run each in its own thread
* register a callback with components.volume to get notified when a new sound card connects
* if that is a bluetooth device, try opening an input device with similar name using
* button listeners are run each in its own thread

"""
import logging
Expand Down
6 changes: 2 additions & 4 deletions src/jukebox/components/controls/common/evdev_listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,8 @@ def _filter_by_device_name(all_devices: List[evdev.InputDevice],
def find_device(device_name: str, exact_name: bool = True, mandatory_keys: Optional[Set[int]] = None) -> str:
"""Find an input device with device_name and mandatory keys.

Raises

#. FileNotFoundError, if no device is found.
#. AttributeError, if device does not have the mandatory keys
:raise FileNotFoundError: if no device is found.
:raise AttributeError: if device does not have the mandatory key

If multiple devices match, the first match is returned

Expand Down
2 changes: 0 additions & 2 deletions src/jukebox/components/gpio/gpioz/core/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ class VolumeToRGB:

Map input :data:`0...100` to color range :data:`green...magenta` and get the color for level 50

.. code-block:: python

conv = VolumeToRGB(100, offset=120, section=180)
(r, g, b) = conv(50)

Expand Down
37 changes: 19 additions & 18 deletions src/jukebox/components/gpio/gpioz/core/input_devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
All callback handlers are replaced by GPIOZ callback handlers. These are usually configured
by using the :func:`set_rpc_actions` each input device exhibits.

For examples how to use the devices from the configuration files, see :ref:`userguide/gpioz:Input devices`
For examples how to use the devices from the configuration files, see
[GPIO: Input Devices](../../builders/gpio.md#input-devices).
"""

import functools
Expand Down Expand Up @@ -75,7 +76,7 @@ def set_rpc_actions(self, action_config) -> None:
Set all input device callbacks from :attr:`action_config`

:param action_config: Dictionary with one
:ref:`RPC Command <userguide/rpc_commands:RPC commands>` definition entry for every device callback
[RPC Commands](../../builders/rpc-commands.md) definition entry for every device callback
"""
pass

Expand Down Expand Up @@ -233,11 +234,11 @@ class LongPressButton(NameMixin, ButtonBase):
"""
A Button that runs a single actions only when the button is pressed long enough

:param pull_up: See `Button`_
:param pull_up: See #Button

:param active_state: See `Button`_
:param active_state: See #Button

:param bounce_time: See `Button`_
:param bounce_time: See #Button

:param hold_repeat: If :data:`True` repeat the :attr:`on_press` every :attr:`hold_time` seconds. Else only action
is run only once independent of the length of time the button is pressed for.
Expand Down Expand Up @@ -291,11 +292,11 @@ class ShortLongPressButton(NameMixin, ButtonBase):
event. Furthermore, if there is a long hold, only the long hold action is executed - the short press action is not run
in this case!

:param pull_up: See `Button`_
:param pull_up: See #Button

:param active_state: See `Button`_
:param active_state: See #Button

:param bounce_time: See `Button`_
:param bounce_time: See #Button

:param hold_time: The time in seconds to differentiate if it is a short or long press. If the button is released before
this time, it is a short press. As soon as the button is held for :attr:`hold_time` it is a long press and the
Expand All @@ -304,9 +305,9 @@ class ShortLongPressButton(NameMixin, ButtonBase):
:param hold_repeat: If :data:`True` repeat the long press action every :attr:`hold_time` seconds after first long press
action

:param pin_factory: See `Button`_
:param pin_factory: See #Button

:param name: See `Button`_
:param name: See #Button
"""
def __init__(
self, pin=None, *, pull_up=True, active_state=None, bounce_time=None,
Expand Down Expand Up @@ -370,11 +371,11 @@ class RotaryEncoder(NameMixin):
"""
A rotary encoder to run one of two actions depending on the rotation direction.

:param bounce_time: See `Button`_
:param bounce_time: See #Button

:param pin_factory: See `Button`_
:param pin_factory: See #Button

:param name: See `Button`_
:param name: See #Button
"""
def __init__(self, a, b, *, bounce_time=None, pin_factory=None, name=None):
super().__init__(name=name)
Expand Down Expand Up @@ -442,11 +443,11 @@ class TwinButton(NameMixin):

It is not necessary to configure all actions.

:param pull_up: See `Button`_
:param pull_up: See #Button

:param active_state: See `Button`_
:param active_state: See #Button

:param bounce_time: See `Button`_
:param bounce_time: See #Button

:param hold_time: The time in seconds to differentiate if it is a short or long press. If the button is released before
this time, it is a short press. As soon as the button is held for :attr:`hold_time` it is a long press and the
Expand All @@ -455,9 +456,9 @@ class TwinButton(NameMixin):
:param hold_repeat: If :data:`True` repeat the long press action every :attr:`hold_time` seconds after first long press
action. A long dual press is never repeated independent of this setting

:param pin_factory: See `Button`_
:param pin_factory: See #Button

:param name: See `Button`_
:param name: See #Button
"""

class StateVar(Enum):
Expand Down
3 changes: 2 additions & 1 deletion src/jukebox/components/gpio/gpioz/core/mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ def patch_mock_outputs_with_callback():
This targets to represent the state in the TK GUI.
Other output devices cannot be represented in the GUI and are silently ignored.

..note:: Only for developing purposes!"""
> [!NOTE]
> Only for developing purposes!"""
gpiozero.LED._write_orig = gpiozero.LED._write
gpiozero.LED._write = rewrite
gpiozero.LED.on_change_callback = None
Expand Down
3 changes: 2 additions & 1 deletion src/jukebox/components/gpio/gpioz/core/output_devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
with parameters for this device and optional parameters from another device. Unused/unsupported parameters
are silently ignored. This is done to reduce the amount of coding required for connectivity functions.

For examples how to use the devices from the configuration files, see :ref:`userguide/gpioz:Output devices`
For examples how to use the devices from the configuration files, see
[GPIO: Output Devices](../../builders/gpio.md#output-devices).
"""

from typing import Optional, List
Expand Down
12 changes: 6 additions & 6 deletions src/jukebox/components/gpio/gpioz/plugin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ class ServiceIsRunningCallbacks(CallbackHandler):
"""
Callbacks are executed when

* Jukebox app started
* Jukebox shuts down
* Jukebox app started
* Jukebox shuts down

This is intended to e.g. signal an LED to change state.
This is integrated into this module because:

* we need the GPIO to control a LED (it must be available when the status callback comes)
* the plugin callback functions provide all the functionality to control the status of the LED
* which means no need to adapt other modules
* we need the GPIO to control a LED (it must be available when the status callback comes)
* the plugin callback functions provide all the functionality to control the status of the LED
* which means no need to adapt other modules
"""

def register(self, func: Callable[[int], None]):
Expand All @@ -76,7 +76,7 @@ def register(self, func: Callable[[int], None]):
.. py:function:: func(status: int)
:noindex:

:param status: 1 if app started, 0 if app shuts down
:param status: 1 if app started, 0 if app shuts down
"""
super().register(func)

Expand Down
Loading