dvg-pyqt-filelogger


Namedvg-pyqt-filelogger JSON
Version 1.4.0 PyPI version JSON
download
home_pagehttps://github.com/Dennis-van-Gils/python-dvg-pyqt-filelogger
SummaryPyQt/PySide interface to handle logging data to file particularly well suited for multithreaded programs.
upload_time2024-06-25 16:35:14
maintainerNone
docs_urlNone
authorDennis van Gils
requires_python>=3.6
licenseMIT
keywords pyqt5 pyqt6 pyside2 pyside6 log data multithread
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            .. image:: https://img.shields.io/pypi/v/dvg-pyqt-filelogger
    :target: https://pypi.org/project/dvg-pyqt-filelogger
.. image:: https://img.shields.io/pypi/pyversions/dvg-pyqt-filelogger
    :target: https://pypi.org/project/dvg-pyqt-filelogger
.. image:: https://github.com/Dennis-van-Gils/python-dvg-pyqt-filelogger/actions/workflows/python-package.yml/badge.svg
    :target: https://github.com/Dennis-van-Gils/python-dvg-pyqt-filelogger/actions/workflows/python-package.yml
.. image:: https://coveralls.io/repos/github/Dennis-van-Gils/python-dvg-pyqt-filelogger/badge.svg
    :target: https://coveralls.io/github/Dennis-van-Gils/python-dvg-pyqt-filelogger
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
    :target: https://github.com/psf/black
.. image:: https://img.shields.io/badge/License-MIT-purple.svg
    :target: https://github.com/Dennis-van-Gils/python-dvg-pyqt-filelogger/blob/master/LICENSE.txt

DvG_PyQt_FileLogger
===================
*Provides a PyQt interface to handle logging data to a file particularly well
suited for multithreaded programs.*

Supports PyQt5, PyQt6, PySide2 and PySide6.

- Github: https://github.com/Dennis-van-Gils/python-dvg-pyqt-filelogger
- PyPI: https://pypi.org/project/dvg-pyqt-filelogger

Installation::

    pip install dvg-pyqt-filelogger

Example usage
-------------

The following are snippets of code, not a full program.

.. code-block:: python

    from qtpy import QtWidgets as QtWid
    from dvg_pyqt_filelogger import FileLogger

    # Main/GUI thread
    # ---------------

    class MainWindow(QtWid.QWidget):
        def __init__(
            self,
            log: FileLogger,
            parent=None,
            **kwargs
        ):
            super().__init__(parent, **kwargs)

            # Create a record button
            self.record_button = QtWid.QPushButton("Click to start recording to file")
            self.record_button.setCheckable(True)
            self.record_button.clicked.connect(lambda state: log.record(state))

    class YourDataGeneratingDevice:
        reading_1 = 0.0

    device = YourDataGeneratingDevice()

    def write_header_to_log():
        log.write("elapsed [s]\treading_1\n")

    def write_data_to_log():
        log.write(f"{log.elapsed():.3f}\t{device.reading_1:.4f}\n")

    log = FileLogger(
        write_header_function=write_header_to_log,
        write_data_function=write_data_to_log
    )

    log.signal_recording_started.connect(
        lambda filepath: window.record_button.setText(
            f"Recording to file: {filepath}"
        )
    )
    log.signal_recording_stopped.connect(
        lambda: window.record_button.setText(
            "Click to start recording to file"
        )
    )

    window = MainWindow(log)

    # Data acquisition and/or logging thread
    # --------------------------------------

    # New data got acquired
    device.reading_1 = 20.3

    # Must be called whenever new data has become available
    log.update()

API
===


Class FileLogger
----------------

.. code-block:: python

    FileLogger(
        write_header_function: Callable | None = None,
        write_data_function: Callable | None = None,
        encoding: str = "utf-8",
    )

.. Note:: Inherits from: ``PySide6.QtCore.QObject``

    Handles logging data to a file particularly well suited for multithreaded
    programs where one thread is writing data to the log and the other thread
    (the main/GUI thread) requests starting and stopping of the log, e.g.,
    by the user pressing a button.

    The methods ``start_recording()``, ``stop_recording()`` and ``record(bool)``
    can be directly called from the main/GUI thread.

    In the logging thread you repeatedly need to call ``update()``. This method
    takes cares of the state machine behind ``FileLogger`` and will perform the
    appropiate action, such as creating a file on disk, creating the header or
    writing new data to the log.

    Args:
        write_header_function (``Callable``, optional):
            Reference to a function that contains your specific code to write a
            header to the log file. This will get called during ``update()``.

            The passed function can contain calls to this object's member
            methods ``write()``, ``elapsed()`` and ``np_savetxt()``.

            Default: ``None``

        write_data_function (``Callable``, optional):
            Reference to a function that contains your specific code to write
            new data to the log file. This will get called during ``update()``.

            The passed function can contain calls to this object's member
            methods ``write()``, ``elapsed()`` and ``np_savetxt()``.

            Default: ``None``

    NOTE:
        This class lacks a mutex and is hence not threadsafe from the get-go.
        As long as ``update()`` is being called from inside another mutex, such
        as a data-acquisition mutex for instance, it is safe.

    NOTE:
        By design the code in this class will continue on when exceptions occur.
        They are reported to the command line.

    Signals:
        ``signal_recording_started (str)``:
            Emitted whenever a new recording has started. Useful for, e.g.,
            updating text of a record button.

            Returns:
                The filepath (``str``) of the newly created log file.

            Type:
                ``PySide6.QtCore.Signal()``

        ``signal_recording_stopped (pathlib.Path)``:
            Emitted whenever the recording has stopped. Useful for, e.g., updating
            text of a record button.

            Returns:
                The filepath as (``pathlib.Path()``) of the newly created log file.
                You could use this to, e.g., automatically navigate to the log in
                the file explorer or ask the user for a 'save to' destination.

            Type:
                ``PySide6.QtCore.Signal()``

    Methods:
        * ``set_write_header_function(write_header_function: Callable)``
            Will change the parameter ``write_header_function`` as originally
            passed during instantiation to this new callable.

            Args:
                write_header_function (``Callable``):
                    Reference to a function that contains your specific code to
                    write a header to the log file. This will get called during
                    ``update()``.

                    The passed function can contain calls to this object's member
                    methods ``write()``, ``elapsed()`` and ``np_savetxt()``.

        * ``set_write_data_function(write_data_function: Callable)``
            Will change the parameter ``write_data_function`` as originally
            passed during instantiation to this new callable.

            Args:
                write_data_function (``Callable``):
                    Reference to a function that contains your specific code to
                    write new data to the log file. This will get called during
                    ``update()``.

                    The passed function can contain calls to this object's member
                    methods ``write()``, ``elapsed()`` and ``np_savetxt()``.

        * ``record(state: bool = True)``
            Start or stop recording as given by argument `state`. Can be called
            from any thread.

        * ``start_recording()``
            Start recording. Can be called from any thread.

        * ``stop_recording()``
            Stop recording. Can be called from any thread.

        * ``update(filepath: str = "", mode: str = "a")``
            This method will have to get called repeatedly, presumably in the
            thread where logging is required, e.g., the data-generation thread.
            This method takes cares of the state machine behind ``FileLogger`` and
            will perform the appropriate action, such as creating a file on disk,
            creating the header or writing new data to the log.

            Args:
                filepath (``str``):
                    Location of the log file in case it has to be created or opened
                    for write access.

                    Default: ``"{yyMMdd_HHmmss}.txt"`` denoting the current date and time.

                mode (``str``, optional):
                    Mode in which the log file is to be opened, see ``open()`` for
                    more details. Most common options:

                        ``w``: Open for writing, truncating the file first.

                        ``a``: Open for writing, appending to the end of the file if it exists.

                    Defaults: ``a``

        * ``write(data: AnyStr) -> bool``
            Write binary or ASCII data to the currently opened log file.

            By design any exceptions occurring in this method will not terminate the
            execution, but it will report the error to the command line and continue
            on instead.

            Returns True if successful, False otherwise.

        * ``np_savetxt(*args, **kwargs) -> bool``
            Write 1D or 2D array_like data to the currently opened log file. This
            method passes all arguments directly to ``numpy.savetxt()``, see
            https://numpy.org/doc/stable/reference/generated/numpy.savetxt.html.
            This method outperforms ``FileLogger.write()``, especially when large
            chunks of 2D data are passed (my test shows 8x faster).

            By design any exceptions occurring in this method will not terminate the
            execution, but it will report the error to the command line and continue
            on instead.

            Returns True if successful, False otherwise.

        * ``flush()``
            Force-flush the contents in the OS buffer to file as soon as
            possible. Do not call repeatedly, because it causes overhead.

        * ``close()``
            Close the log file.

        * ``get_filepath() -> Path | None``
            Return the filepath (``pathlib.Path`` | ``None``) of the log.

        * ``is_recording() -> bool``
            Is the log currently set to recording?

        * ``elapsed() -> float``
            Return the time in seconds (``float``) since start of recording.

        * ``pretty_elapsed() -> str``
            Return the time as "h:mm:ss" (``str``) since start of recording.

Changelog
=========

1.4.0 (2024-06-24)
------------------
* Using ``qtpy`` library instead of my own Qt5/6 mechanism
* Support for Numpy 2.0
* Extended API and docstrings
* Added argument `encoding`, defaulting to "utf-8"
* Added type hints
* Added method `get_filepath()`

1.3.0 (2023-02-27)
------------------
* Raise `ImportError` instead of general `Exception`

1.2.0 (2022-09-13)
------------------
* Added support for PyQt5, PyQt6, PySide2 and PySide6

1.1.0 (2021-05-13)
------------------
* Added support for `numpy.savetxt()`

1.0.0 (2020-08-11)
------------------
* First release on PyPI

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/Dennis-van-Gils/python-dvg-pyqt-filelogger",
    "name": "dvg-pyqt-filelogger",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": null,
    "keywords": "PyQt5, PyQt6, PySide2, PySide6, log, data, multithread",
    "author": "Dennis van Gils",
    "author_email": "vangils.dennis@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/0a/62/5c892c03d0606040b46628b12b4b5ea1f77443f1ef0640f8e5dc09a961ab/dvg_pyqt_filelogger-1.4.0.tar.gz",
    "platform": null,
    "description": ".. image:: https://img.shields.io/pypi/v/dvg-pyqt-filelogger\r\n    :target: https://pypi.org/project/dvg-pyqt-filelogger\r\n.. image:: https://img.shields.io/pypi/pyversions/dvg-pyqt-filelogger\r\n    :target: https://pypi.org/project/dvg-pyqt-filelogger\r\n.. image:: https://github.com/Dennis-van-Gils/python-dvg-pyqt-filelogger/actions/workflows/python-package.yml/badge.svg\r\n    :target: https://github.com/Dennis-van-Gils/python-dvg-pyqt-filelogger/actions/workflows/python-package.yml\r\n.. image:: https://coveralls.io/repos/github/Dennis-van-Gils/python-dvg-pyqt-filelogger/badge.svg\r\n    :target: https://coveralls.io/github/Dennis-van-Gils/python-dvg-pyqt-filelogger\r\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\r\n    :target: https://github.com/psf/black\r\n.. image:: https://img.shields.io/badge/License-MIT-purple.svg\r\n    :target: https://github.com/Dennis-van-Gils/python-dvg-pyqt-filelogger/blob/master/LICENSE.txt\r\n\r\nDvG_PyQt_FileLogger\r\n===================\r\n*Provides a PyQt interface to handle logging data to a file particularly well\r\nsuited for multithreaded programs.*\r\n\r\nSupports PyQt5, PyQt6, PySide2 and PySide6.\r\n\r\n- Github: https://github.com/Dennis-van-Gils/python-dvg-pyqt-filelogger\r\n- PyPI: https://pypi.org/project/dvg-pyqt-filelogger\r\n\r\nInstallation::\r\n\r\n    pip install dvg-pyqt-filelogger\r\n\r\nExample usage\r\n-------------\r\n\r\nThe following are snippets of code, not a full program.\r\n\r\n.. code-block:: python\r\n\r\n    from qtpy import QtWidgets as QtWid\r\n    from dvg_pyqt_filelogger import FileLogger\r\n\r\n    # Main/GUI thread\r\n    # ---------------\r\n\r\n    class MainWindow(QtWid.QWidget):\r\n        def __init__(\r\n            self,\r\n            log: FileLogger,\r\n            parent=None,\r\n            **kwargs\r\n        ):\r\n            super().__init__(parent, **kwargs)\r\n\r\n            # Create a record button\r\n            self.record_button = QtWid.QPushButton(\"Click to start recording to file\")\r\n            self.record_button.setCheckable(True)\r\n            self.record_button.clicked.connect(lambda state: log.record(state))\r\n\r\n    class YourDataGeneratingDevice:\r\n        reading_1 = 0.0\r\n\r\n    device = YourDataGeneratingDevice()\r\n\r\n    def write_header_to_log():\r\n        log.write(\"elapsed [s]\\treading_1\\n\")\r\n\r\n    def write_data_to_log():\r\n        log.write(f\"{log.elapsed():.3f}\\t{device.reading_1:.4f}\\n\")\r\n\r\n    log = FileLogger(\r\n        write_header_function=write_header_to_log,\r\n        write_data_function=write_data_to_log\r\n    )\r\n\r\n    log.signal_recording_started.connect(\r\n        lambda filepath: window.record_button.setText(\r\n            f\"Recording to file: {filepath}\"\r\n        )\r\n    )\r\n    log.signal_recording_stopped.connect(\r\n        lambda: window.record_button.setText(\r\n            \"Click to start recording to file\"\r\n        )\r\n    )\r\n\r\n    window = MainWindow(log)\r\n\r\n    # Data acquisition and/or logging thread\r\n    # --------------------------------------\r\n\r\n    # New data got acquired\r\n    device.reading_1 = 20.3\r\n\r\n    # Must be called whenever new data has become available\r\n    log.update()\r\n\r\nAPI\r\n===\r\n\r\n\r\nClass FileLogger\r\n----------------\r\n\r\n.. code-block:: python\r\n\r\n    FileLogger(\r\n        write_header_function: Callable | None = None,\r\n        write_data_function: Callable | None = None,\r\n        encoding: str = \"utf-8\",\r\n    )\r\n\r\n.. Note:: Inherits from: ``PySide6.QtCore.QObject``\r\n\r\n    Handles logging data to a file particularly well suited for multithreaded\r\n    programs where one thread is writing data to the log and the other thread\r\n    (the main/GUI thread) requests starting and stopping of the log, e.g.,\r\n    by the user pressing a button.\r\n\r\n    The methods ``start_recording()``, ``stop_recording()`` and ``record(bool)``\r\n    can be directly called from the main/GUI thread.\r\n\r\n    In the logging thread you repeatedly need to call ``update()``. This method\r\n    takes cares of the state machine behind ``FileLogger`` and will perform the\r\n    appropiate action, such as creating a file on disk, creating the header or\r\n    writing new data to the log.\r\n\r\n    Args:\r\n        write_header_function (``Callable``, optional):\r\n            Reference to a function that contains your specific code to write a\r\n            header to the log file. This will get called during ``update()``.\r\n\r\n            The passed function can contain calls to this object's member\r\n            methods ``write()``, ``elapsed()`` and ``np_savetxt()``.\r\n\r\n            Default: ``None``\r\n\r\n        write_data_function (``Callable``, optional):\r\n            Reference to a function that contains your specific code to write\r\n            new data to the log file. This will get called during ``update()``.\r\n\r\n            The passed function can contain calls to this object's member\r\n            methods ``write()``, ``elapsed()`` and ``np_savetxt()``.\r\n\r\n            Default: ``None``\r\n\r\n    NOTE:\r\n        This class lacks a mutex and is hence not threadsafe from the get-go.\r\n        As long as ``update()`` is being called from inside another mutex, such\r\n        as a data-acquisition mutex for instance, it is safe.\r\n\r\n    NOTE:\r\n        By design the code in this class will continue on when exceptions occur.\r\n        They are reported to the command line.\r\n\r\n    Signals:\r\n        ``signal_recording_started (str)``:\r\n            Emitted whenever a new recording has started. Useful for, e.g.,\r\n            updating text of a record button.\r\n\r\n            Returns:\r\n                The filepath (``str``) of the newly created log file.\r\n\r\n            Type:\r\n                ``PySide6.QtCore.Signal()``\r\n\r\n        ``signal_recording_stopped (pathlib.Path)``:\r\n            Emitted whenever the recording has stopped. Useful for, e.g., updating\r\n            text of a record button.\r\n\r\n            Returns:\r\n                The filepath as (``pathlib.Path()``) of the newly created log file.\r\n                You could use this to, e.g., automatically navigate to the log in\r\n                the file explorer or ask the user for a 'save to' destination.\r\n\r\n            Type:\r\n                ``PySide6.QtCore.Signal()``\r\n\r\n    Methods:\r\n        * ``set_write_header_function(write_header_function: Callable)``\r\n            Will change the parameter ``write_header_function`` as originally\r\n            passed during instantiation to this new callable.\r\n\r\n            Args:\r\n                write_header_function (``Callable``):\r\n                    Reference to a function that contains your specific code to\r\n                    write a header to the log file. This will get called during\r\n                    ``update()``.\r\n\r\n                    The passed function can contain calls to this object's member\r\n                    methods ``write()``, ``elapsed()`` and ``np_savetxt()``.\r\n\r\n        * ``set_write_data_function(write_data_function: Callable)``\r\n            Will change the parameter ``write_data_function`` as originally\r\n            passed during instantiation to this new callable.\r\n\r\n            Args:\r\n                write_data_function (``Callable``):\r\n                    Reference to a function that contains your specific code to\r\n                    write new data to the log file. This will get called during\r\n                    ``update()``.\r\n\r\n                    The passed function can contain calls to this object's member\r\n                    methods ``write()``, ``elapsed()`` and ``np_savetxt()``.\r\n\r\n        * ``record(state: bool = True)``\r\n            Start or stop recording as given by argument `state`. Can be called\r\n            from any thread.\r\n\r\n        * ``start_recording()``\r\n            Start recording. Can be called from any thread.\r\n\r\n        * ``stop_recording()``\r\n            Stop recording. Can be called from any thread.\r\n\r\n        * ``update(filepath: str = \"\", mode: str = \"a\")``\r\n            This method will have to get called repeatedly, presumably in the\r\n            thread where logging is required, e.g., the data-generation thread.\r\n            This method takes cares of the state machine behind ``FileLogger`` and\r\n            will perform the appropriate action, such as creating a file on disk,\r\n            creating the header or writing new data to the log.\r\n\r\n            Args:\r\n                filepath (``str``):\r\n                    Location of the log file in case it has to be created or opened\r\n                    for write access.\r\n\r\n                    Default: ``\"{yyMMdd_HHmmss}.txt\"`` denoting the current date and time.\r\n\r\n                mode (``str``, optional):\r\n                    Mode in which the log file is to be opened, see ``open()`` for\r\n                    more details. Most common options:\r\n\r\n                        ``w``: Open for writing, truncating the file first.\r\n\r\n                        ``a``: Open for writing, appending to the end of the file if it exists.\r\n\r\n                    Defaults: ``a``\r\n\r\n        * ``write(data: AnyStr) -> bool``\r\n            Write binary or ASCII data to the currently opened log file.\r\n\r\n            By design any exceptions occurring in this method will not terminate the\r\n            execution, but it will report the error to the command line and continue\r\n            on instead.\r\n\r\n            Returns True if successful, False otherwise.\r\n\r\n        * ``np_savetxt(*args, **kwargs) -> bool``\r\n            Write 1D or 2D array_like data to the currently opened log file. This\r\n            method passes all arguments directly to ``numpy.savetxt()``, see\r\n            https://numpy.org/doc/stable/reference/generated/numpy.savetxt.html.\r\n            This method outperforms ``FileLogger.write()``, especially when large\r\n            chunks of 2D data are passed (my test shows 8x faster).\r\n\r\n            By design any exceptions occurring in this method will not terminate the\r\n            execution, but it will report the error to the command line and continue\r\n            on instead.\r\n\r\n            Returns True if successful, False otherwise.\r\n\r\n        * ``flush()``\r\n            Force-flush the contents in the OS buffer to file as soon as\r\n            possible. Do not call repeatedly, because it causes overhead.\r\n\r\n        * ``close()``\r\n            Close the log file.\r\n\r\n        * ``get_filepath() -> Path | None``\r\n            Return the filepath (``pathlib.Path`` | ``None``) of the log.\r\n\r\n        * ``is_recording() -> bool``\r\n            Is the log currently set to recording?\r\n\r\n        * ``elapsed() -> float``\r\n            Return the time in seconds (``float``) since start of recording.\r\n\r\n        * ``pretty_elapsed() -> str``\r\n            Return the time as \"h:mm:ss\" (``str``) since start of recording.\r\n\r\nChangelog\r\n=========\r\n\r\n1.4.0 (2024-06-24)\r\n------------------\r\n* Using ``qtpy`` library instead of my own Qt5/6 mechanism\r\n* Support for Numpy 2.0\r\n* Extended API and docstrings\r\n* Added argument `encoding`, defaulting to \"utf-8\"\r\n* Added type hints\r\n* Added method `get_filepath()`\r\n\r\n1.3.0 (2023-02-27)\r\n------------------\r\n* Raise `ImportError` instead of general `Exception`\r\n\r\n1.2.0 (2022-09-13)\r\n------------------\r\n* Added support for PyQt5, PyQt6, PySide2 and PySide6\r\n\r\n1.1.0 (2021-05-13)\r\n------------------\r\n* Added support for `numpy.savetxt()`\r\n\r\n1.0.0 (2020-08-11)\r\n------------------\r\n* First release on PyPI\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "PyQt/PySide interface to handle logging data to file particularly well suited for multithreaded programs.",
    "version": "1.4.0",
    "project_urls": {
        "Homepage": "https://github.com/Dennis-van-Gils/python-dvg-pyqt-filelogger",
        "Issue Tracker": "https://github.com/Dennis-van-Gils/python-dvg-pyqt-filelogger/issues"
    },
    "split_keywords": [
        "pyqt5",
        " pyqt6",
        " pyside2",
        " pyside6",
        " log",
        " data",
        " multithread"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "25cee47b5801ac516a5b4743f22f01b0831b847627cf0fa200c1f6ba87da7322",
                "md5": "d696139af0578ce21407fdad490e6bfe",
                "sha256": "5fac1d8cc9b79668c9a5dddb8e50f26dfffb270d38aef8138652c18d4bc50326"
            },
            "downloads": -1,
            "filename": "dvg_pyqt_filelogger-1.4.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d696139af0578ce21407fdad490e6bfe",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 9631,
            "upload_time": "2024-06-25T16:35:13",
            "upload_time_iso_8601": "2024-06-25T16:35:13.027520Z",
            "url": "https://files.pythonhosted.org/packages/25/ce/e47b5801ac516a5b4743f22f01b0831b847627cf0fa200c1f6ba87da7322/dvg_pyqt_filelogger-1.4.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0a625c892c03d0606040b46628b12b4b5ea1f77443f1ef0640f8e5dc09a961ab",
                "md5": "eb7a89382ceccd586128928ccfe899a7",
                "sha256": "5245742f95ce9a571584fe2d5f046993e9553ccb9067de2d6752d3579d6f3f3d"
            },
            "downloads": -1,
            "filename": "dvg_pyqt_filelogger-1.4.0.tar.gz",
            "has_sig": false,
            "md5_digest": "eb7a89382ceccd586128928ccfe899a7",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 10289,
            "upload_time": "2024-06-25T16:35:14",
            "upload_time_iso_8601": "2024-06-25T16:35:14.241312Z",
            "url": "https://files.pythonhosted.org/packages/0a/62/5c892c03d0606040b46628b12b4b5ea1f77443f1ef0640f8e5dc09a961ab/dvg_pyqt_filelogger-1.4.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-06-25 16:35:14",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Dennis-van-Gils",
    "github_project": "python-dvg-pyqt-filelogger",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "dvg-pyqt-filelogger"
}
        
Elapsed time: 0.46075s