[![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"
}