Skip to content

Commit e290872

Browse files
committed
fix docu
1 parent bc29eb0 commit e290872

File tree

5 files changed

+104
-41
lines changed

5 files changed

+104
-41
lines changed

README.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ CircuitPython helper library to handle serial user input in an nonblocking way.
2626

2727
Dependencies
2828
=============
29-
This driver depends on:
29+
This helper library depends on:
3030

3131
* `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_
3232

@@ -62,8 +62,9 @@ Or the following command to update an existing version:
6262
Usage Example
6363
=============
6464

65-
.. todo:: Add a quick, simple example. It and other examples should live in the
66-
examples folder and be included in docs/examples.rst.
65+
.. literalinclude:: ./examples/nonblocking_serialinput_simpletest.py
66+
:caption: examples/nonblocking_serialinput_simpletest.py
67+
:linenos:
6768

6869

6970
Contributing

docs/examples.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,19 @@ Ensure your device works with this simple test.
66
.. literalinclude:: ../examples/nonblocking_serialinput_simpletest.py
77
:caption: examples/nonblocking_serialinput_simpletest.py
88
:linenos:
9+
10+
11+
Advanced Usage
12+
--------------
13+
14+
.. literalinclude:: ../examples/nonblocking_serialinput_advanced.py
15+
:caption: examples/nonblocking_serialinput_advanced.py
16+
:linenos:
17+
18+
19+
Advanced Usage with class based approach
20+
----------------------------------------
21+
22+
.. literalinclude:: ../examples/nonblocking_serialinput_advanced_class.py
23+
:caption: examples/nonblocking_serialinput_advanced_class.py
24+
:linenos:

docs/examples.rst.license

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
21
SPDX-FileCopyrightText: Copyright (c) 2021 Stefan Krüger for s-light
32

43
SPDX-License-Identifier: MIT

docs/index.rst

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,9 @@ Table of Contents
2424
.. toctree::
2525
:caption: Tutorials
2626

27-
.. todo:: Add any Learn guide links here. If there are none, then simply delete this todo and leave
28-
the toctree above for use later.
29-
3027
.. toctree::
3128
:caption: Related Products
3229

33-
.. todo:: Add any product links here. If there are none, then simply delete this todo and leave
34-
the toctree above for use later.
35-
3630
.. toctree::
3731
:caption: Other Links
3832

nonblocking_serialinput.py

Lines changed: 84 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
2-
# SPDX-FileCopyrightText: Copyright (c) 2021 Stefan Krüger for s-light
1+
# SPDX-FileCopyrightText: Copyright (c) 2021 Stefan Krüger s-light.eu
32
#
43
# SPDX-License-Identifier: MIT
54
"""
@@ -16,9 +15,6 @@
1615
1716
**Hardware:**
1817
19-
.. todo:: Add links to any specific hardware product page(s), or category page(s).
20-
Use unordered list & hyperlink rST inline format: "* `Link Text <url>`_"
21-
2218
**Software and Dependencies:**
2319
2420
* Adafruit CircuitPython firmware `>= 7.0.0 for the supported boards.
@@ -38,7 +34,41 @@
3834

3935

4036
class NonBlockingSerialInput:
41-
"""docstring for NonBlockingSerialInput."""
37+
"""Non Blocking Serial Input Class.
38+
39+
This CircuitPython helper class can be used as non-blocking *drop-in* for the build
40+
in ``input()`` method.
41+
And also as event / callback based handling.
42+
It implements the full input buffer handling and line-end parsing.
43+
44+
all parameters are keyword parameters.
45+
46+
:param function input_handling_fn: function to call if there is one ore more
47+
fully received new lines. ``input_handling(input_string: string)``
48+
Default: None
49+
:param function print_help_fn:function to call when a help text should be printed
50+
fully received new lines. ``print_help()``
51+
Default: None
52+
:param ~usb_cdc.Serial serial: serial connection object to use
53+
Default: usb_cdc.console
54+
:param bool echo: enable/disable remote echo
55+
Default: True
56+
:param bool statusline: enable/disable status line handling - `Not implemented yet - issue #1:
57+
<https://github.com/s-light/CircuitPython_nonblocking_serialinput/issues/1>`_
58+
Default: False
59+
:param string encoding: input string encoding
60+
Default: "utf-8"
61+
:param string, list line_end_custom: set custom line ends
62+
Default: None
63+
:param bool use_universal_line_end_basic: use a basic default set of line_ends
64+
[`\n`, '\r', '\r\n']
65+
Default: True
66+
:param bool use_universal_line_end_advanced: use a advanced default set of line_ends
67+
['\v', '\f', '\x1c',...]
68+
Default: False
69+
:param bool verbose: print debugging information in some internal functions. Default to False
70+
71+
"""
4272

4373
def __init__(
4474
self,
@@ -52,6 +82,7 @@ def __init__(
5282
line_end_custom=None,
5383
use_universal_line_end_basic=True,
5484
use_universal_line_end_advanced=False,
85+
verbose=False,
5586
):
5687
super()
5788
self.input_handling_fn = input_handling_fn
@@ -67,6 +98,7 @@ def __init__(
6798
self.line_end_list.extend(universal_line_end_basic)
6899
if use_universal_line_end_advanced:
69100
self.line_end_list.extend(universal_line_end_advanced)
101+
self.verbose = verbose
70102

71103
# no block:
72104
self.serial.timeout = 0
@@ -96,30 +128,28 @@ def _buffer_endswith_line_end(self):
96128

97129
def _buffer_check_and_handle_line_ends(self):
98130
if self._buffer_count_line_ends():
99-
# we have at minimum one full command.
100-
# let us extract this.
101-
# buffer_endswith = self._buffer_endswith_line_end()
102-
# if buffer_endswith:
103-
# # just split the lines and all is fine..
104-
# pass
105-
# else:
106-
# # we have to leave the last part in place..
107-
# pass
108-
# self.input_list.extend(self.input_buffer.splitlines(self.line_end_list))
109131
lines, rest = splitlines_advanced(self.input_buffer, self.line_end_list)
110-
# print("lines: {}; rest: {}".format(repr(lines), repr(rest)))
111132
self.input_list.extend(lines)
112-
# print("self.input_list: {}".format(repr(self.input_list)))
133+
if self.verbose:
134+
print("lines: {}; rest: {}".format(repr(lines), repr(rest)))
135+
print("self.input_list: {}".format(repr(self.input_list)))
113136
if rest:
114137
self.input_buffer = rest
115138
else:
116139
self.input_buffer = ""
117140

118141
def input(self):
119-
"""get oldest input string if there is any available. Otherwise an emtpy string."""
142+
"""
143+
Input.
144+
145+
get oldest input string if there is any available. Otherwise an emtpy string.
146+
147+
:return string: if available oldest input_line. Otherwise `""`
148+
"""
120149
try:
121150
result = self.input_list.pop(0)
122-
# print("result: {}".format(repr(result)))
151+
if self.verbose:
152+
print("result: {}".format(repr(result)))
123153
except IndexError:
124154
result = None
125155
return result
@@ -132,11 +162,10 @@ def update(self):
132162
raw = self.serial.read(available)
133163
if self.echo and not self.statusline:
134164
self.serial.write(raw)
135-
self.input_buffer += raw.decode(
136-
self.encoding,
137-
# encoding=self.encoding,
138-
# errors="strict",
139-
)
165+
self.input_buffer += raw.decode(self.encoding)
166+
# decode: keyword argeuments and errors not supported by CircuitPython
167+
# encoding=self.encoding,
168+
# errors="strict",
140169
self._buffer_check_and_handle_line_ends()
141170
available = self.serial.in_waiting
142171
parsed_input = False
@@ -153,8 +182,13 @@ def update(self):
153182
##########################################
154183
# helper
155184

156-
# source for universal_line_end
157-
# https://docs.python.org/3.8/library/stdtypes.html#str.splitlines
185+
"""
186+
source for universal_line_end
187+
https://docs.python.org/3.8/library/stdtypes.html#str.splitlines
188+
189+
:attribute list: universal_line_end_basic
190+
:attribute list: universal_line_end_advanced
191+
"""
158192
universal_line_end_basic = [
159193
# Line Feed
160194
"\n",
@@ -204,9 +238,15 @@ def update(self):
204238
# return result
205239

206240

241+
# def find_first_line_end(input_string, line_end_list=None, start=0, return_line_end=False):
207242
def find_first_line_end(input_string, line_end_list=None, start=0):
208243
"""
209-
Find first line_end in input_string.
244+
Find first line_end from line_end_list in input_string.
245+
246+
:param string input_string: input search
247+
:param list line_end_list: list with strings to search for.
248+
:param int start: start position for search. (default = 0)
249+
:return int: index of first found line_end; `-1` if nothing is found.
210250
"""
211251
result = None
212252
if line_end_list is None:
@@ -228,10 +268,20 @@ def find_first_line_end(input_string, line_end_list=None, start=0):
228268
def splitlines_advanced(input_string, line_end_list=None):
229269
"""
230270
Split lines in input_string at all line_ends in line_end_list.
271+
272+
This function searches for the all occurenc of all of strings in line_end_list.
273+
then splits at these points. the resulting list is returned.
274+
this also returns empty string segments.
275+
the search happens in the order of line_end_list.
276+
if the string does not end with a line_end symbol this last part will be returned in `rest`
277+
278+
:param string input_string: input to split
279+
:param list line_end_list: list with strings where the splitting should happen.
280+
:return tuple: Tuple (result_list, rest);
231281
"""
232282
if line_end_list is None:
233283
line_end_list = universal_line_end_basic
234-
result = []
284+
result_list = []
235285
rest = None
236286
# we have to do the splitting manually as we have a list of available seperators..
237287
pos_last = 0
@@ -240,7 +290,7 @@ def splitlines_advanced(input_string, line_end_list=None):
240290
) > -1:
241291
# print("pos: {}".format(repr(pos)))
242292
# print("input_string[pos_last:pos]: {}".format(repr(input_string[pos_last:pos])))
243-
result.append(input_string[pos_last:pos])
293+
result_list.append(input_string[pos_last:pos])
244294
pos_last = pos + 1
245295
# print("pos_last: {}".format(repr(pos_last)))
246296
# print("pos_last: {}".format(repr(pos_last)))
@@ -249,7 +299,7 @@ def splitlines_advanced(input_string, line_end_list=None):
249299
# print(" rest handling:")
250300
# print("input_string[pos_last:]: {}".format(repr(input_string[pos_last:])))
251301
rest = input_string[pos_last:]
252-
return (result, rest)
302+
return (result_list, rest)
253303

254304

255305
"""
@@ -308,6 +358,9 @@ def is_number(value):
308358
309359
based on
310360
https://stackoverflow.com/questions/354038/how-do-i-check-if-a-string-is-a-number-float
361+
362+
:param string value: input to check
363+
:return bool: True if value is a number, otherwise False.
311364
"""
312365
try:
313366
float(value)

0 commit comments

Comments
 (0)