Oliver Fabel 1 год назад
Родитель
Сommit
8db9d9a213
6 измененных файлов с 657 добавлено и 8 удалено
  1. 16 1
      docs/pages/conf.py
  2. 65 6
      docs/pages/reference.rst
  3. 47 0
      flipperzero/_uart.py
  4. 366 0
      flipperzero/io.py
  5. 162 0
      flipperzero/logging.py
  6. 1 1
      lib/micropython

+ 16 - 1
docs/pages/conf.py

@@ -5,11 +5,26 @@ import sys
 base = pathlib.Path(__file__).parent.parent.parent
 base = pathlib.Path(__file__).parent.parent.parent
 root = base.__str__()
 root = base.__str__()
 flipperzero = base.joinpath('flipperzero').__str__()
 flipperzero = base.joinpath('flipperzero').__str__()
-now = datetime.datetime.now()
 
 
 sys.path.append(root)
 sys.path.append(root)
 sys.path.append(flipperzero)
 sys.path.append(flipperzero)
 
 
+def copy_dict(source, target):
+    for key, value in source.__dict__.items():
+        target.__dict__[key] = value
+
+import flipperzero.logging
+import logging
+
+copy_dict(flipperzero.logging, logging)
+
+import flipperzero.io
+import io
+
+copy_dict(flipperzero.io, io)
+
+now = datetime.datetime.now()
+
 project = 'uPython'
 project = 'uPython'
 copyright = str(now.year) + ', Oliver Fabel'
 copyright = str(now.year) + ', Oliver Fabel'
 author = 'Oliver Fabel'
 author = 'Oliver Fabel'

+ 65 - 6
docs/pages/reference.rst

@@ -416,7 +416,62 @@ Classes
 ~~~~~~~
 ~~~~~~~
 
 
 .. autoclass:: flipperzero.UART
 .. autoclass:: flipperzero.UART
-   :members: read, readline, readlines, write, flush
+   :members: read, readline, readlines, write, flush, close, __enter__, __exit__, __del__
+
+Logging
+-------
+
+Log messages to the Flipper's own logging backend.
+Check out the `Flipper Zero docs <https://docs.flipper.net/development/cli#_yZ2E>`_ on how to reveal them in the CLI.
+Be aware, that you can't change Flipper's global log level from within your script.
+Change the `corresponding settings <https://docs.flipper.net/basics/settings#d5TAt>`_ instead or use the **log** command in the CLI with the desired log level as the first argument.
+
+Levels
+~~~~~~
+
+.. autodata:: logging.TRACE
+.. autodata:: logging.DEBUG
+.. autodata:: logging.INFO
+.. autodata:: logging.WARN
+.. autodata:: logging.ERROR
+.. autodata:: logging.NONE
+.. autodata:: logging.level
+
+Functions
+~~~~~~~~~
+
+.. autofunction:: logging.setLevel
+.. autofunction:: logging.getEffectiveLevel
+.. autofunction:: logging.trace
+.. autofunction:: logging.debug
+.. autofunction:: logging.info
+.. autofunction:: logging.warn
+.. autofunction:: logging.error
+.. autofunction:: logging.log
+
+I/O
+---
+
+Constants
+~~~~~~~~~
+
+.. autodata:: io.SEEK_SET
+.. autodata:: io.SEEK_CUR
+.. autodata:: io.SEEK_END
+
+Functions
+~~~~~~~~~
+
+.. autofunction:: io.open
+
+Classes
+~~~~~~~
+
+.. autoclass:: io.BinaryFileIO
+   :members: name, read, readline, readlines, readable, writable, write, flush, seek, tell, close, __enter__, __exit__, __del__
+
+.. autoclass:: io.TextFileIO
+   :members: name, read, readline, readlines, readable, writable, write, flush, seek, tell, close, __enter__, __exit__, __del__
 
 
 Built-In
 Built-In
 --------
 --------
@@ -424,17 +479,21 @@ Built-In
 The functions in this section are `not` part of the ``flipperzero`` module.
 The functions in this section are `not` part of the ``flipperzero`` module.
 They're members of the global namespace instead.
 They're members of the global namespace instead.
 
 
-.. py:function:: print(*objects, sep=' ', end='\n', file=None, flush=False) -> None
+.. py:function:: print(*objects, sep=' ', end='\n') -> None
 
 
    The standard Python `print <https://docs.python.org/3/library/functions.html#print>`_ function.
    The standard Python `print <https://docs.python.org/3/library/functions.html#print>`_ function.
+   Where the output of this function will be redirected depends on how the script is invoked:
+
+      * When invoked from the UI, the output will be sent to the Flipper's log buffer.
+        Check out the `Flipper Zero docs <https://docs.flipper.net/development/cli#_yZ2E>`_ on how to view them in the CLI interface.
+      * In the REPL, the output will be sent to the standard output buffer.
+      * When invoked by the **py** command, the output will be sent to the standard output buffer.
 
 
    :param objects: The objects to print (mostly a single string).
    :param objects: The objects to print (mostly a single string).
    :param sep: The separator to use between the objects.
    :param sep: The separator to use between the objects.
    :param end: The line terminator character to use.
    :param end: The line terminator character to use.
 
 
    .. versionadded:: 1.0.0
    .. versionadded:: 1.0.0
+   .. versionchanged:: 1.5.0
 
 
-   .. attention::
-      
-      This function prints to the internal log buffer.
-      Check out the `Flipper Zero docs <https://docs.flipper.net/development/cli#_yZ2E>`_ on how to reveal them in the CLI interface.
+      Output redirection, based on script invocation.

+ 47 - 0
flipperzero/_uart.py

@@ -29,6 +29,15 @@ class UART:
 
 
         with f0.open(f0.UART_MODE_USART, 115200) as uart:
         with f0.open(f0.UART_MODE_USART, 115200) as uart:
             lines = [line for line in uart]
             lines = [line for line in uart]
+    
+    An :class:`UART` instance can be used with a `context manager <https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers>`_:
+
+    .. code-block::
+
+        import flipperzero as f0
+
+        with f0.open(f0.UART_MODE_USART, 115200) as uart:
+            ...
 
 
     .. hint::
     .. hint::
 
 
@@ -94,6 +103,44 @@ class UART:
         '''
         '''
         Flush the transmission buffer to the underlying UART connection.
         Flush the transmission buffer to the underlying UART connection.
         This method blocks until all data is sent.
         This method blocks until all data is sent.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def close(self) -> None:
+        '''
+        Close the UART connection.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def __enter__(self) -> 'UART':
+        '''
+        This method is invoked, when the instance enters a runtime context.
+
+        :returns: The :class:`UART` connection.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def __exit__(self, *args, **kwargs) -> None:
+        '''
+        This method is invoked, when the instance leavs a runtime context.
+        This basically calls :meth:`close` on the instance.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def __del__(self) -> None:
+        '''
+        This method is invoked, when the garbage collector removes the object.
+        This basically calls :meth:`close` on the instance.
+
+        .. versionadded:: 1.5.0
         '''
         '''
         pass
         pass
 
 

+ 366 - 0
flipperzero/io.py

@@ -0,0 +1,366 @@
+import typing
+import io
+
+_open = io.open
+
+SEEK_SET: int = 0
+'''
+Set the pointer position relative to the beginning of the stream.
+
+.. versionadded:: 1.5.0
+'''
+
+SEEK_CUR: int = 1
+'''
+Set the pointer position relative to the current position.
+
+.. versionadded:: 1.5.0
+'''
+
+SEEK_END: int = 2
+'''
+Set the pointer position relative to the end of the stream.
+
+.. versionadded:: 1.5.0
+'''
+
+class BinaryFileIO:
+    '''
+    Represents a file, opened in binary mode.
+
+    .. versionadded:: 1.5.0
+    '''
+
+    name: str
+    '''
+    The name of the file.
+
+    .. versionadded:: 1.5.0
+    '''
+
+    readable: bool
+    '''
+    Read-only attribute, indicating if the file is readable.
+    
+    .. versionadded:: 1.5.0
+    '''
+
+    writable: bool
+    '''
+    Read-only attribute, indicating if the file is writable.
+    
+    .. versionadded:: 1.5.0
+    '''
+
+    def read(self, size: int = -1) -> bytes:
+        '''
+        Read from the file. 
+        The method will read up to ``size`` bytes and return them.
+        If ``size`` is not specified, all content up to EOF will be returned.
+        If the internal pointer is already at EOF, an empty byte string ``b''`` will be returned.
+
+        :param size: The maximum number of bytes to read.
+        :returns: Up to ``size`` bytes.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def readline(self, size: int = -1) -> bytes:
+        '''
+        Read and return one line from the file.
+        If ``size`` is specified, at most ``size`` bytes will be read.
+        The line terminator is defined as ``b'\\n'``.
+        The new line character is included in the return value.
+        If the internal pointer is at EOF, an empty byte string ``b''`` will be returned.
+
+        :param size: The maximum number of bytes to read.
+        :returns: Up to ``size`` bytes.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def readlines(self) -> typing.List[bytes]:
+        '''
+        Read and return a list of lines from the file.
+        The line terminator is defined as ``b'\\n'``.
+        The new line character is included in the return value.
+        If the internal pointer is at EOF, an empty list will be returned.
+
+        :returns: A list of bytes.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def write(self, data: bytes) -> int:
+        '''
+        Write the given bytes to the file.
+        The number of written bytes will be returned.
+        This can be less than the length of the provided data.
+
+        :param data: The data to write.
+        :returns: The number of bytes written.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def flush(self) -> None:
+        '''
+        Write the contents of the file buffer to the file on the SD card.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def seek(self, offset: int, whence: int = SEEK_SET) -> int:
+        '''
+        Set the pointer position by the given ``offset``, relative to the position indicated by ``whence``.
+        The new absolute position will be returned.
+
+        :param offset: The offset to use.
+        :param whence: How to interpret the offset (e.g. :const:`SEEK_SET`).
+        :returns: The new absolute position.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def tell(self) -> int:
+        '''
+        Get the current pointer position.
+
+        :returns: The absolute position of the pointer.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def close(self) -> None:
+        '''
+        Close the file handle.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def __enter__(self) -> 'BinaryFileIO':
+        '''
+        This method is invoked, when the instance enters a runtime context.
+
+        :returns: The :class:`BinaryFileIO` instance.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def __exit__(self, *args, **kwargs) -> None:
+        '''
+        This method is invoked, when the instance leavs a runtime context.
+        This basically calls :meth:`close` on the instance.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def __del__(self) -> None:
+        '''
+        This method is invoked, when the garbage collector removes the object.
+        This basically calls :meth:`close` on the instance.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+class TextFileIO:
+    '''
+    Represents a file, opened in text mode.
+
+    .. versionadded:: 1.5.0
+    '''
+
+    name: str
+    '''
+    The name of the file.
+
+    .. versionadded:: 1.5.0
+    '''
+
+    readable: bool
+    '''
+    Read-only attribute, indicating if the file is readable.
+    
+    .. versionadded:: 1.5.0
+    '''
+
+    writable: bool
+    '''
+    Read-only attribute, indicating if the file is writable.
+    
+    .. versionadded:: 1.5.0
+    '''
+
+    def read(self, size: int = -1) -> str:
+        '''
+        Read from the file. 
+        The method will read up to ``size`` characters and return them.
+        If ``size`` is not specified, all content up to EOF will be returned.
+        If the internal pointer is already at EOF, an empty string will be returned.
+
+        :param size: The maximum number of characters to read.
+        :returns: Up to ``size`` characters.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def readline(self, size: int = -1) -> str:
+        '''
+        Read and return one line from the file.
+        If ``size`` is specified, at most ``size`` characters will be read.
+        The line terminator is defined as ``'\\n'``.
+        The new line character is included in the return value.
+        If the internal pointer is at EOF, an empty string will be returned.
+
+        :param size: The maximum number of characters to read.
+        :returns: Up to ``size`` characters.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def readlines(self) -> typing.List[str]:
+        '''
+        Read and return a list of lines from the file.
+        The line terminator is defined as ``'\\n'``.
+        The new line character is included in the return value.
+        If the internal pointer is at EOF, an empty list will be returned.
+
+        :returns: A list of strings.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def write(self, data: str) -> int:
+        '''
+        Write the given string to the file.
+        The number of written characters will be returned.
+        This can be less than the length of the provided data.
+
+        :param data: The data to write.
+        :returns: The number of characters written.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def flush(self) -> None:
+        '''
+        Write the contents of the file buffer to the file on the SD card.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def seek(self, offset: int, whence: int = SEEK_SET) -> int:
+        '''
+        Set the pointer position by the given ``offset``, relative to the position indicated by ``whence``.
+        The new absolute position will be returned.
+
+        :param offset: The offset to use.
+        :param whence: How to interpret the offset (e.g. :const:`SEEK_SET`).
+        :returns: The new absolute position.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def tell(self) -> int:
+        '''
+        Get the current pointer position.
+
+        :returns: The absolute position of the pointer.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def close(self) -> None:
+        '''
+        Close the file handle.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def __enter__(self) -> 'TextFileIO':
+        '''
+        This method is invoked, when the instance enters a runtime context.
+
+        :returns: The :class:`BinaryFileIO` instance.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def __exit__(self, *args, **kwargs) -> None:
+        '''
+        This method is invoked, when the instance leavs a runtime context.
+        This basically calls :meth:`close` on the instance.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+    def __del__(self) -> None:
+        '''
+        This method is invoked, when the garbage collector removes the object.
+        This basically calls :meth:`close` on the instance.
+
+        .. versionadded:: 1.5.0
+        '''
+        pass
+
+def open(path: str, mode: str, *args, **kwargs) -> BinaryFileIO | TextFileIO:
+    '''
+    Open a file on the file system with the specified mode.
+    The file path must always be absolute, beginning with ``/ext``.
+    The following modifiers are available:
+
+    .. list-table::
+        :header-rows: 1
+        :width: 90%
+
+        * - Character
+          - Description
+        * - ``'r'``
+          - Open for reading.
+            This is the default.
+            Will fail, if the file not exists.
+        * - ``'w'``
+          - Open for writing, truncating an existing file first.
+        * - ``'b'``
+          - Open the file in binary mode. 
+            The return value will be a :class:`BinaryFileIO` instance.
+        * - ``'t'``
+          - Open the in text mode.
+            This is the default.
+            The return value will be a :class:`TextFileIO` instance.
+        * - ``'+'``
+          - Open for reading and writing.
+            Will create the file, if it not exists.
+            The pointer will be placed at the end of the file.
+    
+    The modifiers can be combined, e.g. ``'rb+'`` would open a file for reading and writing in binary mode.
+
+    :param path: The path to the file to open.
+    :param mode: How the file should be opened.
+    :param args: Is ignored at the moment.
+    :param kwargs: Is ignored at the moment.
+
+    .. versionadded:: 1.5.0
+    '''
+    return io._open(path, mode, *args, **kwargs)

+ 162 - 0
flipperzero/logging.py

@@ -0,0 +1,162 @@
+import typing
+
+TRACE: int = 6
+'''
+Constant value for the `trace` log level.
+
+.. versionadded:: 1.5.0
+'''
+
+DEBUG: int = 5
+'''
+Constant value for the `debug` log level.
+
+.. versionadded:: 1.5.0
+'''
+
+INFO: int = 4
+'''
+Constant value for the `info` log level.
+
+.. versionadded:: 1.5.0
+'''
+
+WARN: int = 3
+'''
+Constant value for the `warn` log level.
+
+.. versionadded:: 1.5.0
+'''
+
+ERROR: int = 2
+'''
+Constant value for the `error` log level.
+
+.. versionadded:: 1.5.0
+'''
+
+NONE: int = 1
+'''
+Constant value for logging disabled.
+
+.. versionadded:: 1.5.0
+'''
+
+level: int
+'''
+The threshold log level, as set by the :func:`setLevel` function.
+The initial value is set to the :const:`INFO` level.
+
+.. versionadded:: 1.5.0
+
+.. hint::
+
+    Don't change the value of this variable, use :func:`setLevel` instead.
+'''
+
+def setLevel(level: int) -> None:
+    '''
+    Set the current log level of the application.
+
+    :param level: The log level to set (e.g. :const:`INFO`).
+
+    .. versionadded:: 1.5.0
+
+    .. hint::
+
+        This doesn't change the Flipper's effective log level settings.
+        Check out the Flipper's `documentation <https://docs.flipper.net/basics/settings#d5TAt>`_ for details on this topic.
+    '''
+    pass
+
+def getEffectiveLevel() -> int:
+    '''
+    Get the effective log level from the Flipper's settings.
+
+    :returns: The effective log level.
+
+    .. versionadded:: 1.5.0
+    '''
+    pass
+
+def trace(message: str, *args) -> None:
+    '''
+    Log a message with level :const:`TRACE`.
+    The ``message`` argument can be a format string with ``%`` placeholders.
+    No % formatting operation is performed when ``args`` is empty.
+
+    :param message: The message to log.
+    :param args: Values for the % formatting.
+
+    .. versionadded:: 1.5.0
+
+    .. code-block::
+
+        import logging
+
+        value = 42
+
+        logging.trace('value is %d', value)
+    '''
+    pass
+
+def debug(message: str, *args) -> None:
+    '''
+    Log a message with level :const:`DEBUG`.
+    See :func:`trace` for details on the usage.
+
+    :param message: The message to log.
+    :param args: Values for the % formatting.
+
+    .. versionadded:: 1.5.0
+    '''
+    pass
+
+def info(message: str, *args) -> None:
+    '''
+    Log a message with level :const:`INFO`.
+    See :func:`trace` for details on the usage.
+
+    :param message: The message to log.
+    :param args: Values for the % formatting.
+
+    .. versionadded:: 1.5.0
+    '''
+    pass
+
+def warn(message: str, *args) -> None:
+    '''
+    Log a message with level :const:`WARN`.
+    See :func:`trace` for details on the usage.
+
+    :param message: The message to log.
+    :param args: Values for the % formatting.
+
+    .. versionadded:: 1.5.0
+    '''
+    pass
+
+def error(message: str, *args) -> None:
+    '''
+    Log a message with level :const:`ERROR`.
+    See :func:`trace` for details on the usage.
+
+    :param message: The message to log.
+    :param args: Values for the % formatting.
+
+    .. versionadded:: 1.5.0
+    '''
+    pass
+
+def log(level: int, message: str, *args) -> None:
+    '''
+    Log a message with the given log level.
+    See :func:`trace` for details on the usage.
+
+    :param level: The log level to use (e.g. :const:`INFO`).
+    :param message: The message to log.
+    :param args: Values for the % formatting.
+
+    .. versionadded:: 1.5.0
+    '''
+    pass

+ 1 - 1
lib/micropython

@@ -1 +1 @@
-Subproject commit a9aec44c88a78f16160beabb81474c741287a486
+Subproject commit 29091048ae9a613070da21b373062a450f7ecd08