base-descriptor


Namebase-descriptor JSON
Version 1.2 PyPI version JSON
download
home_pagehttps://github.com/tybruno/base-descriptor
SummaryA simple, fast, typed, and tested abstract and base classes for a python3.6+ Non Data Descriptor, Data Descriptor, and Slottable Data Descriptor.
upload_time2023-10-26 17:39:53
maintainer
docs_urlNone
authorTyler Bruno
requires_python>=3.6
licenseMIT
keywords descriptor data-descriptor non-data-descriptor slottable-data-descriptor
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity)
[![License: MIT](https://img.shields.io/badge/License-MIT-blueviolet.svg)](https://opensource.org/licenses/MIT)
[![codecov](https://codecov.io/gh/tybruno/descriptor/branch/main/graph/badge.svg?token=j6pZAXF6cw)](https://codecov.io/gh/tybruno/descriptor)

# base-descriptor

A simple, fast, typed, and tested abstract and base classes for a python3.6+
Non Data Descriptor, Data Descriptor, and Slottable Data Descriptor. The goal
is to
aid in the creation of descriptors allowing other developers to make
descriptors for their own use case.

#### Key Features:

* **Easy**: Flexable and easy to inherit the prebuilt Non Data Descriptors,
  Data Descriptors, and Slottable Data Descriptors to create your own
  descriptors.
* **Great Developer Experience**: Being fully typed makes it great for editor
  support.
* **Fully Tested**: Our test suit fully tests the functionality to ensure that
  all of the classes in this module run as expected.

## Installation

`pip install base-descriptor`

## Table of Contents

- [Objects Provided in this Module](#objects-provided-in-this-module)
    - [Non Data Descriptors](#non-data-descriptors)
    - [Data Descriptors](#data-descriptors)
    - [Slottable Data Descriptors](#slottable-data-descriptors)
- [Non Data Descriptor Examples](#non-data-descriptor-examples)
    - [AbstractNonDataDescriptor](#abstractnondatadescriptor)
- [Data Descriptor Examples](#data-descriptor-examples)
    - [ReadOnly](#readonly)
    - [DefaultDescriptor](#defaultdescriptor)
    - [BaseDataDescriptor](#basedatadescriptor)
    - [AbstractDataDescriptor](#abstractdatadescriptor)
- [Slottable Data Descriptors](#slottable-data-descriptors-1)
    - [SlottableDefaultDescriptor](#slottabledefaultdescriptor)
    - [BaseSlottableDataDescriptor](#baseslottabledatadescriptor)
- [References](#references)

## Objects Provided in this Module

### Non Data Descriptors

A non-data descriptor in Python is a type of descriptor that only implements
the `__get__()` method. Descriptors are a way to customize attribute access in
Python. When an attribute is
accessed on an object, Python checks if a descriptor exists for that attribute
in the class or its ancestors. If found, the descriptor's `__get__()` method is
called to determine the final
value of the attribute.

| Class                       | Description                                            |
|-----------------------------|--------------------------------------------------------|
| `AbstractNonDataDescriptor` | Abstract Base Class for creating Non Data Descriptors. |

### Data Descriptors

A data descriptor in Python is a type of descriptor that implements
both `__get__()` and either `__set__()` or `__delete__()`. Data descriptors
allow you to define custom behavior for
attribute
access, including setting or deleting the attribute in addition to retrieving
its value.

| Class                    | Description                                                                                        |
|--------------------------|----------------------------------------------------------------------------------------------------|
| `AbstractDataDescriptor` | Abstract Base Class for creating Data Descriptors.                                                 |
| `BaseDataDescriptor`     | Base Class for creating Data Descriptors. Provides the same functionality as a standard attribute. | 
| `DefaultDescriptor`      | A Data Descriptor that has a default value.                                                        |
| `ReadOnly`               | A Data Descriptor that is read only.                                                               |

### Slottable Data Descriptors

A Data Descriptor that plays well with `__slots__`. This module was inspired by
Dr. Fred Baptiste [fbaptiste](https://github.com/fbaptiste).

The slottable data descriptor has the following advantages:

1. Has instance specific storage
2. Does not use the instance for storage, thus works with __slots__.
   `__slots__ = "__weakref__"` must be set.
3. Handles non hashable instances
4. Data storage is clean.

| Class                             | Description                                                                                                  |
|-----------------------------------|--------------------------------------------------------------------------------------------------------------|
| `AbstractSlottableDataDescriptor` | Abstract Base Class for creating Slottable Data Descriptors.                                                 |
| `BaseSlottableDataDescriptor`     | Base Class for creating Slottable Data Descriptors. Provides the same functionality as a standard attribute. |
| `SlottableDefaultDescriptor`      | A Slottable Data Descriptor that has a default value.                                                        |

## Non Data Descriptor Examples

### `AbstractNonDataDescriptor`

Simple way to Inherit from `AbstractNonDataDescriptor` to create your own Non
Data Descriptor.

```python
from base_descriptor import AbstractNonDataDescriptor


class SquareDescriptor(AbstractNonDataDescriptor):
    def __get__(self, instance, owner=None):
        if instance is None:
            # Access through the class, return the descriptor itself
            return self
        return instance._value ** 2


class MyClass:
    square = SquareDescriptor()

    def __init__(self, value):
        self._value = value


# Create an instance of MyClass
my_instance = MyClass(5)

# Access the square attribute using the descriptor
# This will calculate and return the square
print(my_instance.square)  # 25
```

## Data Descriptor Examples

### `ReadOnly`

```python
from base_descriptor import ReadOnly


class Person:
    name = ReadOnly("Guido")


person = Person()
print(person.name)  # Guido
person.name = "Raymond"  # raises AttributeError
```

### `DefaultDescriptor`

Default Descriptor that provides a default value for the attribute.

```python
from base_descriptor import DefaultDescriptor


class Person:
    name = DefaultDescriptor(default="Guido")


print(Person.name)  # <data_descriptor.DefaultDescriptor object at ...>
person = Person()
print(person.name)  # Guido
person.name = "Raymond"
print(person.name)  # Raymond
```

### `BaseDataDescriptor`

Provides the same functionality as a standard attribute.
It enables you to create your own Data Descriptor by overriding
the `__set_name__()`, `__set__()`, `__get__()`,
or `__delete__()` methods to match your requirements.

```python
from base_descriptor import BaseDataDescriptor


class Plus2(BaseDataDescriptor):
    def __set__(self, instance, value):
        value = value + 2
        instance.__dict__[self._property_name] = value


class Foo:
    bar = Plus2()


foo = Foo()
foo.bar = 1
print(foo.bar)  # 3
```

### `AbstractDataDescriptor`

Provides an Abstract Base Class that can be inherited from to help create your
own Data Descriptors.

```python
from base_descriptor import AbstractDataDescriptor


class MyDataDescriptor(AbstractDataDescriptor):
    def __init__(self):
        self._value = None

    def __get__(self, instance, owner):
        return self._value

    def __set__(self, instance, value):
        self._value = value

    def __delete__(self, instance):
        self._value = None


class MyClass:
    my_data_descriptor = MyDataDescriptor()


obj = MyClass()
obj.my_data_descriptor = 1
print(obj.my_data_descriptor)  # 1
```

## Slottable Data Descriptors

### `SlottableDefaultDescriptor`

Slottable Default Descriptor that provides a default value for the attribute.

```python
from base_descriptor import SlottableDefaultDescriptor


class Person:
    __slots__ = "__weakref__"
    first_name = SlottableDefaultDescriptor(default="Guido")


person = Person()
print(person.first_name)  # Guido
person.first_name = "Raymond"
print(person.first_name)  # Raymond
```

### `BaseSlottableDataDescriptor`

Provides the same functionality as a standard attribute.
It enables you to create your own Slottable Data Descriptor by overriding
the `__set_name__()`, `__set__()`, `__get__()`,
or `__delete__()` methods to match your requirements.

```python
from base_descriptor import BaseSlottableDataDescriptor


class MyDescriptor(BaseSlottableDataDescriptor):
    def __set__(self, instance, value):
        print(f"Setting {self._property_name} to {value}")
        instance.__dict__[self._property_name] = value


class Foo:
    __slots__ = "__weakref__"
    bar = MyDescriptor()


foo = Foo()
foo.bar = 1
print(foo.bar)  # 1
```

## References

This module was heavily inspired by the following resources:

1. **Python Deep Dive: Part 4**
    - Author: Dr. Fred Baptiste ([fbaptiste](https://github.com/fbaptiste))
    - Year: 2023
    - Course
      Title: [Python Deep Dive: Part 4](https://www.udemy.com/course/python-3-deep-dive-part-4/)
    - Platform: Udemy

2. **Descriptor HowTo Guide**
    - Source: Python Documentation
    - URL:
      [Descriptor HowTo Guide](https://docs.python.org/3/howto/descriptor.html)



            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/tybruno/base-descriptor",
    "name": "base-descriptor",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": "",
    "keywords": "descriptor data-descriptor non-data-descriptor slottable-data-descriptor",
    "author": "Tyler Bruno",
    "author_email": "",
    "download_url": "https://files.pythonhosted.org/packages/5a/10/460ac28f1e582b8a76f1c30b845ac98858da2c6b21599e35a50fdb2011b3/base-descriptor-1.2.tar.gz",
    "platform": null,
    "description": "[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blueviolet.svg)](https://opensource.org/licenses/MIT)\n[![codecov](https://codecov.io/gh/tybruno/descriptor/branch/main/graph/badge.svg?token=j6pZAXF6cw)](https://codecov.io/gh/tybruno/descriptor)\n\n# base-descriptor\n\nA simple, fast, typed, and tested abstract and base classes for a python3.6+\nNon Data Descriptor, Data Descriptor, and Slottable Data Descriptor. The goal\nis to\naid in the creation of descriptors allowing other developers to make\ndescriptors for their own use case.\n\n#### Key Features:\n\n* **Easy**: Flexable and easy to inherit the prebuilt Non Data Descriptors,\n  Data Descriptors, and Slottable Data Descriptors to create your own\n  descriptors.\n* **Great Developer Experience**: Being fully typed makes it great for editor\n  support.\n* **Fully Tested**: Our test suit fully tests the functionality to ensure that\n  all of the classes in this module run as expected.\n\n## Installation\n\n`pip install base-descriptor`\n\n## Table of Contents\n\n- [Objects Provided in this Module](#objects-provided-in-this-module)\n    - [Non Data Descriptors](#non-data-descriptors)\n    - [Data Descriptors](#data-descriptors)\n    - [Slottable Data Descriptors](#slottable-data-descriptors)\n- [Non Data Descriptor Examples](#non-data-descriptor-examples)\n    - [AbstractNonDataDescriptor](#abstractnondatadescriptor)\n- [Data Descriptor Examples](#data-descriptor-examples)\n    - [ReadOnly](#readonly)\n    - [DefaultDescriptor](#defaultdescriptor)\n    - [BaseDataDescriptor](#basedatadescriptor)\n    - [AbstractDataDescriptor](#abstractdatadescriptor)\n- [Slottable Data Descriptors](#slottable-data-descriptors-1)\n    - [SlottableDefaultDescriptor](#slottabledefaultdescriptor)\n    - [BaseSlottableDataDescriptor](#baseslottabledatadescriptor)\n- [References](#references)\n\n## Objects Provided in this Module\n\n### Non Data Descriptors\n\nA non-data descriptor in Python is a type of descriptor that only implements\nthe `__get__()` method. Descriptors are a way to customize attribute access in\nPython. When an attribute is\naccessed on an object, Python checks if a descriptor exists for that attribute\nin the class or its ancestors. If found, the descriptor's `__get__()` method is\ncalled to determine the final\nvalue of the attribute.\n\n| Class                       | Description                                            |\n|-----------------------------|--------------------------------------------------------|\n| `AbstractNonDataDescriptor` | Abstract Base Class for creating Non Data Descriptors. |\n\n### Data Descriptors\n\nA data descriptor in Python is a type of descriptor that implements\nboth `__get__()` and either `__set__()` or `__delete__()`. Data descriptors\nallow you to define custom behavior for\nattribute\naccess, including setting or deleting the attribute in addition to retrieving\nits value.\n\n| Class                    | Description                                                                                        |\n|--------------------------|----------------------------------------------------------------------------------------------------|\n| `AbstractDataDescriptor` | Abstract Base Class for creating Data Descriptors.                                                 |\n| `BaseDataDescriptor`     | Base Class for creating Data Descriptors. Provides the same functionality as a standard attribute. | \n| `DefaultDescriptor`      | A Data Descriptor that has a default value.                                                        |\n| `ReadOnly`               | A Data Descriptor that is read only.                                                               |\n\n### Slottable Data Descriptors\n\nA Data Descriptor that plays well with `__slots__`. This module was inspired by\nDr. Fred Baptiste [fbaptiste](https://github.com/fbaptiste).\n\nThe slottable data descriptor has the following advantages:\n\n1. Has instance specific storage\n2. Does not use the instance for storage, thus works with __slots__.\n   `__slots__ = \"__weakref__\"` must be set.\n3. Handles non hashable instances\n4. Data storage is clean.\n\n| Class                             | Description                                                                                                  |\n|-----------------------------------|--------------------------------------------------------------------------------------------------------------|\n| `AbstractSlottableDataDescriptor` | Abstract Base Class for creating Slottable Data Descriptors.                                                 |\n| `BaseSlottableDataDescriptor`     | Base Class for creating Slottable Data Descriptors. Provides the same functionality as a standard attribute. |\n| `SlottableDefaultDescriptor`      | A Slottable Data Descriptor that has a default value.                                                        |\n\n## Non Data Descriptor Examples\n\n### `AbstractNonDataDescriptor`\n\nSimple way to Inherit from `AbstractNonDataDescriptor` to create your own Non\nData Descriptor.\n\n```python\nfrom base_descriptor import AbstractNonDataDescriptor\n\n\nclass SquareDescriptor(AbstractNonDataDescriptor):\n    def __get__(self, instance, owner=None):\n        if instance is None:\n            # Access through the class, return the descriptor itself\n            return self\n        return instance._value ** 2\n\n\nclass MyClass:\n    square = SquareDescriptor()\n\n    def __init__(self, value):\n        self._value = value\n\n\n# Create an instance of MyClass\nmy_instance = MyClass(5)\n\n# Access the square attribute using the descriptor\n# This will calculate and return the square\nprint(my_instance.square)  # 25\n```\n\n## Data Descriptor Examples\n\n### `ReadOnly`\n\n```python\nfrom base_descriptor import ReadOnly\n\n\nclass Person:\n    name = ReadOnly(\"Guido\")\n\n\nperson = Person()\nprint(person.name)  # Guido\nperson.name = \"Raymond\"  # raises AttributeError\n```\n\n### `DefaultDescriptor`\n\nDefault Descriptor that provides a default value for the attribute.\n\n```python\nfrom base_descriptor import DefaultDescriptor\n\n\nclass Person:\n    name = DefaultDescriptor(default=\"Guido\")\n\n\nprint(Person.name)  # <data_descriptor.DefaultDescriptor object at ...>\nperson = Person()\nprint(person.name)  # Guido\nperson.name = \"Raymond\"\nprint(person.name)  # Raymond\n```\n\n### `BaseDataDescriptor`\n\nProvides the same functionality as a standard attribute.\nIt enables you to create your own Data Descriptor by overriding\nthe `__set_name__()`, `__set__()`, `__get__()`,\nor `__delete__()` methods to match your requirements.\n\n```python\nfrom base_descriptor import BaseDataDescriptor\n\n\nclass Plus2(BaseDataDescriptor):\n    def __set__(self, instance, value):\n        value = value + 2\n        instance.__dict__[self._property_name] = value\n\n\nclass Foo:\n    bar = Plus2()\n\n\nfoo = Foo()\nfoo.bar = 1\nprint(foo.bar)  # 3\n```\n\n### `AbstractDataDescriptor`\n\nProvides an Abstract Base Class that can be inherited from to help create your\nown Data Descriptors.\n\n```python\nfrom base_descriptor import AbstractDataDescriptor\n\n\nclass MyDataDescriptor(AbstractDataDescriptor):\n    def __init__(self):\n        self._value = None\n\n    def __get__(self, instance, owner):\n        return self._value\n\n    def __set__(self, instance, value):\n        self._value = value\n\n    def __delete__(self, instance):\n        self._value = None\n\n\nclass MyClass:\n    my_data_descriptor = MyDataDescriptor()\n\n\nobj = MyClass()\nobj.my_data_descriptor = 1\nprint(obj.my_data_descriptor)  # 1\n```\n\n## Slottable Data Descriptors\n\n### `SlottableDefaultDescriptor`\n\nSlottable Default Descriptor that provides a default value for the attribute.\n\n```python\nfrom base_descriptor import SlottableDefaultDescriptor\n\n\nclass Person:\n    __slots__ = \"__weakref__\"\n    first_name = SlottableDefaultDescriptor(default=\"Guido\")\n\n\nperson = Person()\nprint(person.first_name)  # Guido\nperson.first_name = \"Raymond\"\nprint(person.first_name)  # Raymond\n```\n\n### `BaseSlottableDataDescriptor`\n\nProvides the same functionality as a standard attribute.\nIt enables you to create your own Slottable Data Descriptor by overriding\nthe `__set_name__()`, `__set__()`, `__get__()`,\nor `__delete__()` methods to match your requirements.\n\n```python\nfrom base_descriptor import BaseSlottableDataDescriptor\n\n\nclass MyDescriptor(BaseSlottableDataDescriptor):\n    def __set__(self, instance, value):\n        print(f\"Setting {self._property_name} to {value}\")\n        instance.__dict__[self._property_name] = value\n\n\nclass Foo:\n    __slots__ = \"__weakref__\"\n    bar = MyDescriptor()\n\n\nfoo = Foo()\nfoo.bar = 1\nprint(foo.bar)  # 1\n```\n\n## References\n\nThis module was heavily inspired by the following resources:\n\n1. **Python Deep Dive: Part 4**\n    - Author: Dr. Fred Baptiste ([fbaptiste](https://github.com/fbaptiste))\n    - Year: 2023\n    - Course\n      Title: [Python Deep Dive: Part 4](https://www.udemy.com/course/python-3-deep-dive-part-4/)\n    - Platform: Udemy\n\n2. **Descriptor HowTo Guide**\n    - Source: Python Documentation\n    - URL:\n      [Descriptor HowTo Guide](https://docs.python.org/3/howto/descriptor.html)\n\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A simple, fast, typed, and tested abstract and base classes for a python3.6+ Non Data Descriptor, Data Descriptor, and Slottable Data Descriptor.",
    "version": "1.2",
    "project_urls": {
        "Homepage": "https://github.com/tybruno/base-descriptor"
    },
    "split_keywords": [
        "descriptor",
        "data-descriptor",
        "non-data-descriptor",
        "slottable-data-descriptor"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "2ace7208b67d58c0a909c98bc94d4f4bbd52c42ae6eaad2350879c43a7c8495d",
                "md5": "05325c068a00cb4090411cb75f330261",
                "sha256": "bb0b8de06ca0a77325c02126e39844b4a9187ed94ecca426257a467947c72c29"
            },
            "downloads": -1,
            "filename": "base_descriptor-1.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "05325c068a00cb4090411cb75f330261",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 10463,
            "upload_time": "2023-10-26T17:39:52",
            "upload_time_iso_8601": "2023-10-26T17:39:52.386244Z",
            "url": "https://files.pythonhosted.org/packages/2a/ce/7208b67d58c0a909c98bc94d4f4bbd52c42ae6eaad2350879c43a7c8495d/base_descriptor-1.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5a10460ac28f1e582b8a76f1c30b845ac98858da2c6b21599e35a50fdb2011b3",
                "md5": "d557b6d6d6ba39101300c11656e2615a",
                "sha256": "af114a7999091b6f8f7d9f125855db40069ec420200a05e68cd56911f769f65b"
            },
            "downloads": -1,
            "filename": "base-descriptor-1.2.tar.gz",
            "has_sig": false,
            "md5_digest": "d557b6d6d6ba39101300c11656e2615a",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 9868,
            "upload_time": "2023-10-26T17:39:53",
            "upload_time_iso_8601": "2023-10-26T17:39:53.690671Z",
            "url": "https://files.pythonhosted.org/packages/5a/10/460ac28f1e582b8a76f1c30b845ac98858da2c6b21599e35a50fdb2011b3/base-descriptor-1.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-10-26 17:39:53",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "tybruno",
    "github_project": "base-descriptor",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "base-descriptor"
}
        
Elapsed time: 1.90507s