advanced-descriptors


Nameadvanced-descriptors JSON
Version 4.0.3 PyPI version JSON
download
home_page
SummaryAdvanced descriptors for special cases.
upload_time2022-12-16 11:59:53
maintainer
docs_urlNone
author
requires_python>=3.7.0
licenseApache License, Version 2.0
keywords descriptor property classmethod development
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            Advanced descriptors
====================

.. image:: https://github.com/python-useful-helpers/advanced-descriptors/workflows/Python%20package/badge.svg
    :target: https://github.com/python-useful-helpers/advanced-descriptors/actions
.. image:: https://readthedocs.org/projects/advanced-descriptors/badge/?version=latest
    :target: http://advanced-descriptors.readthedocs.io/
    :alt: Documentation Status
.. image:: https://img.shields.io/pypi/v/advanced-descriptors.svg
    :target: https://pypi.python.org/pypi/advanced-descriptors
.. image:: https://img.shields.io/pypi/pyversions/advanced-descriptors.svg
    :target: https://pypi.python.org/pypi/advanced-descriptors
.. image:: https://img.shields.io/pypi/status/advanced-descriptors.svg
    :target: https://pypi.python.org/pypi/advanced-descriptors
.. image:: https://img.shields.io/github/license/python-useful-helpers/advanced-descriptors.svg
    :target: https://raw.githubusercontent.com/python-useful-helpers/advanced-descriptors/master/LICENSE
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
    :target: https://github.com/ambv/black

This package includes helpers for special cases:

* `SeparateClassMethod` - allow to have classmethod and normal method both with the same name.

* `AdvancedProperty` - property with possibility to set class wide getter.

* `LogOnAccess` - property with logging on successful get/set/delete or failure.

SeparateClassMethod
-------------------

This descriptor can be set using standard decorator syntax.
Create instance with arguments:

.. code-block:: python

  def imeth(instance):
      return instance.value

  def cmeth(owner):
      return owner.value

  class Target(object):
      value = 1

      def __init__(self):
          self.value = 2
      getval = advanced_descriptors.SeparateClassMethod(
          imeth, cmeth
      )

Create instance wrapping as decorator:

.. code-block:: python

  class Target(object):
      value = 1

      def __init__(self):
          self.value = 2

      @advanced_descriptors.SeparateClassMethod
      def getval(self):
          return self.value

      @getval.class_method
      def getval(cls):
          return cls.value

Cases with method only and classmethod only is useless:
method as-is and `@classmethod` should be used in corresponding cases.

.. note::

  classmethod receives class as argument. IDE's don't know about custom descriptors and substitutes `self` by default.

AdvancedProperty
----------------

This descriptor should be used in cases, when in addition to normal property API, class getter is required.
If class-wide setter and deleter also required - you should use standard propery in metaclass.

Usage examples:

1. In addition to normal property API:

  .. code-block:: python

    class Target(object):
        _value = 777

        def __init__(self):
            self._value = 42

        @advanced_descriptors.AdvancedProperty
        def val(self):
            return self._value

        @val.setter
        def val(self, value):
            self._value = value

        @val.deleter
        def val(self):
            self._value = 0

        @val.cgetter
        def val(cls):
            return cls._value

2. Use class-wide getter for instance too:

  .. code-block:: python

    class Target(object):
        _value = 1

        val = advanced_descriptors.AdvancedProperty()

        @val.cgetter
            def val(cls):
                return cls._value

.. note::

  class-wide getter receives class as argument. IDE's don't know about custom descriptors and substitutes `self` by default.

LogOnAccess
-----------

This 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.

Basic API is conform with `property`, but in addition it is possible to customize logger, log levels and log conditions.

Usage examples:

1. Simple usage.
   All by default.
   logger is re-used from instance if available with names `logger` or `log` else used internal `advanced_descriptors.log_on_access` logger:

  .. code-block:: python

    import logging

    class Target(object):

        def init(self, val='ok')
            self.val = val
            self.logger = logging.get_logger(self.__class__.__name__)  # Single for class, follow subclassing

        def __repr__(self):
            return "{cls}(val={self.val})".format(cls=self.__class__.__name__, self=self)

        @advanced_descriptors.LogOnAccess
        def ok(self):
            return self.val

        @ok.setter
        def ok(self, val):
            self.val = val

        @ok.deleter
        def ok(self):
            self.val = ""

2. Use with global logger for class:

  .. code-block:: python

    class Target(object):

      def init(self, val='ok')
          self.val = val

      def __repr__(self):
          return "{cls}(val={self.val})".format(cls=self.__class__.__name__, self=self)

      @advanced_descriptors.LogOnAccess
      def ok(self):
          return self.val

      @ok.setter
      def ok(self, val):
          self.val = val

      @ok.deleter
      def ok(self):
          self.val = ""

      ok.logger = 'test_logger'
      ok.log_level = logging.INFO
      ok.exc_level = logging.ERROR
      ok.log_object_repr = True  # As by default
      ok.log_success = True  # As by default
      ok.log_failure = True  # As by default
      ok.log_traceback = True  # As by default
      ok.override_name = None  # As by default: use original name

Testing
=======
The main test mechanism for the package `advanced-descriptors` is using `tox`.
Available environments can be collected via `tox -l`

CI systems
==========
For CI/CD GitHub actions is used:

`GitHub actions: <https://github.com/python-useful-helpers/advanced-descriptors/actions>`_ is used for checking: PEP8, pylint, bandit, installation possibility and unit tests.

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "advanced-descriptors",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7.0",
    "maintainer_email": "Alexey Stepanov <penguinolog@gmail.com>, Antonio Esposito <esposito.cloud@gmail.com>, Dennis Dmitriev <dis-xcom@gmail.com>",
    "keywords": "descriptor,property,classmethod,development",
    "author": "",
    "author_email": "Alexey Stepanov <penguinolog@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/ec/08/d726ac712f5d0dec1c1630bb129586b26a30668ca9e53f09033caa5e3861/advanced-descriptors-4.0.3.tar.gz",
    "platform": null,
    "description": "Advanced descriptors\n====================\n\n.. image:: https://github.com/python-useful-helpers/advanced-descriptors/workflows/Python%20package/badge.svg\n    :target: https://github.com/python-useful-helpers/advanced-descriptors/actions\n.. image:: https://readthedocs.org/projects/advanced-descriptors/badge/?version=latest\n    :target: http://advanced-descriptors.readthedocs.io/\n    :alt: Documentation Status\n.. image:: https://img.shields.io/pypi/v/advanced-descriptors.svg\n    :target: https://pypi.python.org/pypi/advanced-descriptors\n.. image:: https://img.shields.io/pypi/pyversions/advanced-descriptors.svg\n    :target: https://pypi.python.org/pypi/advanced-descriptors\n.. image:: https://img.shields.io/pypi/status/advanced-descriptors.svg\n    :target: https://pypi.python.org/pypi/advanced-descriptors\n.. image:: https://img.shields.io/github/license/python-useful-helpers/advanced-descriptors.svg\n    :target: https://raw.githubusercontent.com/python-useful-helpers/advanced-descriptors/master/LICENSE\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n    :target: https://github.com/ambv/black\n\nThis package includes helpers for special cases:\n\n* `SeparateClassMethod` - allow to have classmethod and normal method both with the same name.\n\n* `AdvancedProperty` - property with possibility to set class wide getter.\n\n* `LogOnAccess` - property with logging on successful get/set/delete or failure.\n\nSeparateClassMethod\n-------------------\n\nThis descriptor can be set using standard decorator syntax.\nCreate instance with arguments:\n\n.. code-block:: python\n\n  def imeth(instance):\n      return instance.value\n\n  def cmeth(owner):\n      return owner.value\n\n  class Target(object):\n      value = 1\n\n      def __init__(self):\n          self.value = 2\n      getval = advanced_descriptors.SeparateClassMethod(\n          imeth, cmeth\n      )\n\nCreate instance wrapping as decorator:\n\n.. code-block:: python\n\n  class Target(object):\n      value = 1\n\n      def __init__(self):\n          self.value = 2\n\n      @advanced_descriptors.SeparateClassMethod\n      def getval(self):\n          return self.value\n\n      @getval.class_method\n      def getval(cls):\n          return cls.value\n\nCases with method only and classmethod only is useless:\nmethod as-is and `@classmethod` should be used in corresponding cases.\n\n.. note::\n\n  classmethod receives class as argument. IDE's don't know about custom descriptors and substitutes `self` by default.\n\nAdvancedProperty\n----------------\n\nThis descriptor should be used in cases, when in addition to normal property API, class getter is required.\nIf class-wide setter and deleter also required - you should use standard propery in metaclass.\n\nUsage examples:\n\n1. In addition to normal property API:\n\n  .. code-block:: python\n\n    class Target(object):\n        _value = 777\n\n        def __init__(self):\n            self._value = 42\n\n        @advanced_descriptors.AdvancedProperty\n        def val(self):\n            return self._value\n\n        @val.setter\n        def val(self, value):\n            self._value = value\n\n        @val.deleter\n        def val(self):\n            self._value = 0\n\n        @val.cgetter\n        def val(cls):\n            return cls._value\n\n2. Use class-wide getter for instance too:\n\n  .. code-block:: python\n\n    class Target(object):\n        _value = 1\n\n        val = advanced_descriptors.AdvancedProperty()\n\n        @val.cgetter\n            def val(cls):\n                return cls._value\n\n.. note::\n\n  class-wide getter receives class as argument. IDE's don't know about custom descriptors and substitutes `self` by default.\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.\n   All by default.\n   logger is re-used from instance if available with names `logger` or `log` else used internal `advanced_descriptors.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        @advanced_descriptors.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      @advanced_descriptors.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_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 `advanced-descriptors` is using `tox`.\nAvailable environments can be collected via `tox -l`\n\nCI systems\n==========\nFor CI/CD GitHub actions is used:\n\n`GitHub actions: <https://github.com/python-useful-helpers/advanced-descriptors/actions>`_ is used for checking: PEP8, pylint, bandit, installation possibility and unit tests.\n",
    "bugtrack_url": null,
    "license": "Apache License, Version 2.0",
    "summary": "Advanced descriptors for special cases.",
    "version": "4.0.3",
    "split_keywords": [
        "descriptor",
        "property",
        "classmethod",
        "development"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "md5": "6ed7c5958b2bca05c59d76c524ebdbe8",
                "sha256": "433fa4bbd21c099a7c0f60d5777efde6e3a4b088d7d68e679e1c5a02bd95a78c"
            },
            "downloads": -1,
            "filename": "advanced_descriptors-4.0.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "6ed7c5958b2bca05c59d76c524ebdbe8",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7.0",
            "size": 16937,
            "upload_time": "2022-12-16T11:59:52",
            "upload_time_iso_8601": "2022-12-16T11:59:52.130994Z",
            "url": "https://files.pythonhosted.org/packages/a4/e4/1aa2b3aed1ae5f785c27d1bfbf13900c06555919e4361c65818e2d800b2f/advanced_descriptors-4.0.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "md5": "5300a6f39607a1c2556aec2f3a2a4aaa",
                "sha256": "32de74f9ea432b394214ea615aea2f09bdd9389483826e251c97a18271b673e5"
            },
            "downloads": -1,
            "filename": "advanced-descriptors-4.0.3.tar.gz",
            "has_sig": false,
            "md5_digest": "5300a6f39607a1c2556aec2f3a2a4aaa",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7.0",
            "size": 18133,
            "upload_time": "2022-12-16T11:59:53",
            "upload_time_iso_8601": "2022-12-16T11:59:53.819219Z",
            "url": "https://files.pythonhosted.org/packages/ec/08/d726ac712f5d0dec1c1630bb129586b26a30668ca9e53f09033caa5e3861/advanced-descriptors-4.0.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2022-12-16 11:59:53",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "lcname": "advanced-descriptors"
}
        
Elapsed time: 0.16391s