{"id":15070069,"url":"https://github.com/python-useful-helpers/logwrap","last_synced_at":"2025-04-10T17:12:52.497Z","repository":{"id":62576807,"uuid":"72348479","full_name":"python-useful-helpers/logwrap","owner":"python-useful-helpers","description":"logwrap is a helper for logging in human-readable format function arguments and call result on function call","archived":false,"fork":false,"pushed_at":"2025-03-24T12:18:48.000Z","size":1151,"stargazers_count":13,"open_issues_count":2,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-24T14:51:26.609Z","etag":null,"topics":["decorator","log-message","pretty-print","py3","python","python-3","python3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/python-useful-helpers.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-10-30T12:36:11.000Z","updated_at":"2025-02-01T18:54:54.000Z","dependencies_parsed_at":"2024-03-05T11:29:01.769Z","dependency_job_id":"80d615a8-7000-418b-a3ea-539fbda417ca","html_url":"https://github.com/python-useful-helpers/logwrap","commit_stats":{"total_commits":516,"total_committers":5,"mean_commits":103.2,"dds":"0.16279069767441856","last_synced_commit":"939bf68d8df16eff6bae17a2076f4a46061cf82b"},"previous_names":[],"tags_count":139,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/python-useful-helpers%2Flogwrap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/python-useful-helpers%2Flogwrap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/python-useful-helpers%2Flogwrap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/python-useful-helpers%2Flogwrap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/python-useful-helpers","download_url":"https://codeload.github.com/python-useful-helpers/logwrap/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248261908,"owners_count":21074225,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["decorator","log-message","pretty-print","py3","python","python-3","python3"],"created_at":"2024-09-25T01:46:51.833Z","updated_at":"2025-04-10T17:12:52.477Z","avatar_url":"https://github.com/python-useful-helpers.png","language":"Python","readme":"logwrap\n=======\n\n.. image:: https://github.com/python-useful-helpers/logwrap/workflows/Python%20package/badge.svg\n    :target: https://github.com/python-useful-helpers/logwrap/actions\n.. image:: https://coveralls.io/repos/github/python-useful-helpers/logwrap/badge.svg?branch=master\n    :target: https://coveralls.io/github/python-useful-helpers/logwrap?branch=master\n.. image:: https://readthedocs.org/projects/logwrap/badge/?version=latest\n    :target: http://logwrap.readthedocs.io/\n    :alt: Documentation Status\n.. image:: https://img.shields.io/pypi/v/logwrap.svg\n    :target: https://pypi.python.org/pypi/logwrap\n.. image:: https://img.shields.io/pypi/pyversions/logwrap.svg\n    :target: https://pypi.python.org/pypi/logwrap\n.. image:: https://img.shields.io/pypi/status/logwrap.svg\n    :target: https://pypi.python.org/pypi/logwrap\n.. image:: https://img.shields.io/github/license/python-useful-helpers/logwrap.svg\n    :target: https://raw.githubusercontent.com/python-useful-helpers/logwrap/master/LICENSE\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n    :target: https://github.com/ambv/black\n\n\nlogwrap is a helper for logging in human-readable format function arguments and call result on function call.\nWhy? Because logging of `*args, **kwargs` become useless with project grow and you need more details in call log.\n\nCons:\n\n* Log records are not single line.\n\nPros:\n\n* Log records are not single 100500 symbols length line.\n  (Especially actual for testing/development environments and for Kibana users).\n* Service free: job is done by this library and it's dependencies. It works at virtualenv\n* Free software: Apache license\n* Open Source: https://github.com/python-useful-helpers/logwrap\n* PyPI packaged: https://pypi.python.org/pypi/logwrap\n* Self-documented code: docstrings with types in comments\n* Tested: see bages on top\n\nThis package includes helpers:\n\n* `logwrap` - main helper. The same is `LogWrap`.\n\n* `LogWrap` - class with `logwrap` implementation. May be used directly.\n\n* `pretty_repr`\n\n* `pretty_str`\n\n* `PrettyFormat`\n\n* `LogOnAccess` - property with logging on successful get/set/delete or failure.\n\nUsage\n=====\n\nlogwrap\n-------\nThe main decorator. Could be used as not argumented (`@logwrap.logwrap`) and argumented (`@logwrap.logwrap()`).\nNot argumented usage simple calls with default values for all positions.\n\n.. note:: Argumens should be set via keywords only.\n\nArgumented usage with arguments from signature:\n\n.. code-block:: python\n\n    @logwrap.logwrap(\n        log=None,  # if not set: try to find LOGGER, LOG, logger or log object in target module and use it if it logger instance. Fallback: logger named logwrap\n        log_level=logging.DEBUG,\n        exc_level=logging.ERROR,\n        max_indent=20,  # forwarded to the pretty_repr,\n        max_iter=0,  # forwarded to the pretty_repr, max number of items in the Iterable before ellipsis. Unlimited if 0.\n        blacklisted_names=None,  # list argument names, which should be dropped from log\n        blacklisted_exceptions=None,  # Exceptions to skip details in log (no traceback, no exception details - just class name)\n        log_call_args=True,  # Log call arguments before call\n        log_call_args_on_exc=True,  # Log call arguments if exception happens\n        log_traceback = True,  # Log traceback if exception happens\n        log_result_obj=True,  # Log result object\n    )\n\nUsage examples:\n\n.. code-block:: python\n\n    @logwrap.logwrap()\n    def foo():\n        pass\n\nis equal to:\n\n.. code-block:: python\n\n    @logwrap.logwrap\n    def foo():\n        pass\n\nGet decorator for use without parameters:\n\n.. code-block:: python\n\n    get_logs = logwrap.logwrap()  # set required parameters via arguments\n\n    type(get_logs) == LogWrap  # All logic is implemented in LogWrap class starting from version 2.2.0\n\n    @get_logs\n    def foo():\n        pass\n\nCall example (python 3.8):\n\n.. code-block:: python\n\n   import logwrap\n\n   @logwrap.logwrap\n   def example_function1(\n           arg0: str,\n           /,\n           arg1: str,\n           arg2: str='arg2',\n           *args,\n           kwarg1: str,\n           kwarg2: str='kwarg2',\n           **kwargs\n   ) -\u003e tuple():\n       return (arg0, arg1, arg2, args, kwarg1, kwarg2, kwargs)\n\n   example_function1('arg0', 'arg1', kwarg1='kwarg1', kwarg3='kwarg3')\n\nThis code during execution will produce log records:\n\n::\n\n    Calling:\n    'example_function1'(\n        # POSITIONAL_ONLY:\n        arg0='arg0',  # type: str\n        # POSITIONAL_OR_KEYWORD:\n        arg1='arg1',  # type: str\n        arg2='arg2',  # type: str\n        # VAR_POSITIONAL:\n        args=(),\n        # KEYWORD_ONLY:\n        kwarg1='kwarg1',  # type: str\n        kwarg2='kwarg2',  # type: str\n        # VAR_KEYWORD:\n        kwargs={\n            'kwarg3': 'kwarg3',\n        },\n    )\n    Done: 'example_function1' with result:\n\n     (\n        'arg0',\n        'arg1',\n        'arg2',\n        (),\n        'kwarg1',\n        'kwarg2',\n        {\n            'kwarg3': 'kwarg3',\n        },\n     )\n\nLogWrap\n-------\nExample construction and read from test:\n\n.. code-block:: python\n\n    log_call = logwrap.LogWrap()\n    log_call.log_level == logging.DEBUG\n    log_call.exc_level == logging.ERROR\n    log_call.max_indent == 20\n    log_call.blacklisted_names == []\n    log_call.blacklisted_exceptions == []\n    log_call.log_call_args == True\n    log_call.log_call_args_on_exc == True\n    log_call.log_traceback == True\n    log_call.log_result_obj == True\n\nOn object change, variable types is validated.\n\nIn special cases, when special processing required for parameters logging (hide or change parameters in log),\nit can be done by override `pre_process_param` and `post_process_param`.\n\nSee API documentation for details.\n\n\npretty_repr\n-----------\nThis is specified helper for making human-readable repr on complex objects.\nSignature is self-documenting:\n\n.. code-block:: python\n\n    def pretty_repr(\n        src,  # object for repr\n        indent=0,  # start indent\n        no_indent_start=False,  # do not indent the first level\n        max_indent=20,  # maximum allowed indent level\n        indent_step=4,  # step between indents\n    )\n\n\npretty_str\n----------\nThis is specified helper for making human-readable str on complex objects.\nSignature is self-documenting:\n\n.. code-block:: python\n\n    def pretty_str(\n        src,  # object for __str__\n        indent=0,  # start indent\n        no_indent_start=False,  # do not indent the first level\n        max_indent=20,  # maximum allowed indent level\n        indent_step=4,  # step between indents\n    )\n\nLimitations:\n    Dict like objects is always marked inside `{}` for readability, even if it is `collections.OrderedDict` (standard repr as list of tuples).\n\n    Iterable types is not declared, only brackets is used.\n\n    String and bytes looks the same (its __str__, not __repr__).\n\nPrettyFormat\n------------\nPrettyFormat is the main formatting implementation class.\n`pretty_repr` and `pretty_str` uses instances of subclasses `PrettyRepr` and `PrettyStr` from this class.\nThis class is mostly exposed for typing reasons.\nObject signature:\n\n.. code-block:: python\n\n    def __init__(\n        self,\n        max_indent=20,  # maximum allowed indent level\n        indent_step=4,  # step between indents\n    )\n\nCallable object (`PrettyFormat` instance) signature:\n\n.. code-block:: python\n\n    def __call__(\n        self,\n        src,  # object for repr\n        indent=0,  # start indent\n        no_indent_start=False  # do not indent the first level\n    )\n\nAdopting your code\n------------------\npretty_repr behavior could be overridden for your classes by implementing specific magic method:\n\n.. code-block:: python\n\n    def __pretty_repr__(\n        self,\n        parser  # PrettyFormat class instance,\n        indent  # start indent,\n        no_indent_start  # do not indent the first level\n    ):\n        return ...\n\nThis method will be executed instead of __repr__ on your object.\n\n.. code-block:: python\n\n    def __pretty_str__(\n        self,\n        parser  # PrettyFormat class instance,\n        indent  # start indent,\n        no_indent_start  # do not indent the first level\n    ):\n        return ...\n\nThis method will be executed instead of __str__ on your object.\n\nLogOnAccess\n-----------\n\nThis special case of property is useful in cases, where a lot of properties should be logged by similar way without writing a lot of code.\n\nBasic API is conform with `property`, but in addition it is possible to customize logger, log levels and log conditions.\n\nUsage examples:\n\n1. Simple usage. All by default.\n   logger is re-used:\n\n    * from instance if available with names `logger` or `log`,\n    * from instance module if available with names `LOGGER`, `log`,\n    * else used internal `logwrap.log_on_access` logger.\n\n  .. code-block:: python\n\n    import logging\n\n    class Target(object):\n\n        def init(self, val='ok')\n            self.val = val\n            self.logger = logging.get_logger(self.__class__.__name__)  # Single for class, follow subclassing\n\n        def __repr__(self):\n            return \"{cls}(val={self.val})\".format(cls=self.__class__.__name__, self=self)\n\n        @logwrap.LogOnAccess\n        def ok(self):\n            return self.val\n\n        @ok.setter\n        def ok(self, val):\n            self.val = val\n\n        @ok.deleter\n        def ok(self):\n            self.val = \"\"\n\n2. Use with global logger for class:\n\n  .. code-block:: python\n\n    class Target(object):\n\n      def init(self, val='ok')\n          self.val = val\n\n      def __repr__(self):\n          return \"{cls}(val={self.val})\".format(cls=self.__class__.__name__, self=self)\n\n      @logwrap.LogOnAccess\n      def ok(self):\n          return self.val\n\n      @ok.setter\n      def ok(self, val):\n          self.val = val\n\n      @ok.deleter\n      def ok(self):\n          self.val = \"\"\n\n      ok.logger = 'test_logger'\n      ok.log_level = logging.INFO\n      ok.exc_level = logging.ERROR\n      ok.log_object_repr = True  # As by default\n      ok.log_before = True  # As by default\n      ok.log_success = True  # As by default\n      ok.log_failure = True  # As by default\n      ok.log_traceback = True  # As by default\n      ok.override_name = None  # As by default: use original name\n\nTesting\n=======\nThe main test mechanism for the package `logwrap` is using `tox`.\nAvailable environments can be collected via `tox -l`\n\nCI/CD systems\n=============\n\n`GitHub: \u003chttps://github.com/python-useful-helpers/logwrap/actions\u003e`_ is used for functional tests.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpython-useful-helpers%2Flogwrap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpython-useful-helpers%2Flogwrap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpython-useful-helpers%2Flogwrap/lists"}