Metadata-Version: 1.1
Name: class_property
Version: 1.0.0
Summary: Class property that shares the same value with the class and any instance.
Home-page: https://github.com/justengel/class_property
Author: Justin Engel
Author-email: jtengel08@gmail.com
License: Proprietary
Download-URL: https://github.com/justengel/class_property/archive/v1.0.0.tar.gz
Description: ==============
        class property
        ==============
        
        Install
        =======
        
        .. code-block:: bash
        
            pip install class_property
        
        
        Utilities
        =========
        
          * class_value - Hold a single value for a class and all instances.
          * class_property - Like a property, but works on `MyClass.class_prop = value`
          * metaclass - Create a metaclass that looks for class_value and class_property to register them.
          * decorate - Decorate a class to register any class_value and class_property.
        
        **A class must use the metaclass or decorate functions.** Subclasses do not need to use decorate or metaclass.
        The metaclass is how the class object works with the descriptor.
        
        
        Run
        ===
        
        Class value usage.
        
        Example:
        
        .. code-block :: python
        
            from class_property import class_value
        
            # doesn't matter if class_value.decorate, class_property.decorate, or decorate (same with metaclass)
            class MyClass(object, metaclass=class_value.metaclass()):
                value = class_value(1)
        
            mc = MyClass()
            assert mc.value == 1
            assert MyClass.value == 1
        
            MyClass.value = 3
            assert mc.value == 3
            assert MyClass.value == 3
        
            mc.value = 2
            assert mc.value == 2
            assert MyClass.value == 2
        
        
            class SubClass(MyClass):
                hello = class_value("World")
        
            sub = SubClass()
            SubClass.hello = 'name'
            assert sub.hello == 'name'
            assert SubClass.hello == 'name'
        
            sub.hello = 'John Doe'
            assert sub.hello == 'John Doe'
            assert SubClass.hello == 'John Doe'
        
            sub.value = 7
            assert SubClass.value == 7
            assert sub.value == 7
            assert mc.value == 7
            assert MyClass.value == 7
        
        
        Class property usage.
        
        Example:
        
        .. code-block :: python
        
            from class_property import class_value, class_property, decorate, metaclass
        
            global GLOB
            GLOB = 'Hello'
        
            def get_glob():
                """Return the global GLOB value"""
                global GLOB
                return GLOB
        
            def set_glob(value):
                global GLOB
                GLOB = value
        
            # doesn't matter if class_value.decorate, class_property.decorate, or decorate (same with metaclass)
            @decorate
            class MyClass(object):
                _VALUE = None
        
                @class_property
                def value(self):
                    return MyClass._VALUE
        
                @value.setter
                def value(self, value):
                    MyClass._VALUE = value
        
                # Also works with no arguments
                @class_property
                def value2():
                    return MyClass._VALUE
        
                @value2.setter
                def value2(value):
                    MyClass._VALUE = value
        
                glob = class_property(get_glob, set_glob)
        
            mc = MyClass()
            assert mc.value is None
            assert MyClass.value is None
            MyClass.value = 3
            assert mc.value == 3
            assert MyClass.value == 3
            mc.value = 2
            assert mc.value == 2
            assert MyClass.value == 2
        
            assert mc.value2 == 2
            assert MyClass.value2 == 2
            mc.value2 = 5
            assert mc.value == 5
            assert MyClass.value == 5
            assert mc.value2 == 5
            assert MyClass.value2 == 5
        
            assert MyClass.glob == 'Hello'
            assert mc.glob == 'Hello'
            MyClass.glob = 'Jack'
            assert MyClass.glob == 'Jack'
            assert mc.glob == 'Jack'
            mc.glob = 'Jill'
            assert MyClass.glob == 'Jill'
            assert mc.glob == 'Jill'
        
        
            class SubClass(MyClass):
                pass
        
            sub = SubClass()
            sub.glob = 'John'
            assert SubClass.glob == 'John'
            assert sub.glob == 'John'
            assert MyClass.glob == 'John'
            assert mc.glob == 'John'
        
        
        Inheritance
        ===========
        
        After using `decorate` or `metaclass` to create the class using a metaclass `class_value` and `class_property` work as expected.
        When you inherit from a `class_property` class new `class_value` and `class_property` attributes work as expected as well.
        If you try to override a `class_value` or `class_property` things get complicated.
        
        If you just want to change from `class_value` to a `class_property` set a new variable like normal.
        This will override the parent class attribute as well.
        
        Example:
        
        .. code-block:: python
        
            from class_property import class_value, class_property
        
        
            class MyClass(object, metaclass=class_value.metaclass()):
                value = class_value(1)
        
        
            class SubClass(MyClass):
                _VALUE = 2
        
                # This replaces "MyClass.value". class_value/class_property uses the metaclass, so we have to replace.
                # We can only change to a new object if we change the metaclass.
                @class_property
                def value(self):
                    return SubClass._VALUE
        
                @value.setter
                def value(self, val):
                    SubClass._VALUE = val
        
        
            class SetValueClass(MyClass):
                value = 3
        
        
            # Check that SetValueClass just changes the current value
            assert MyClass.value == 3
            assert SubClass.value == 3
            assert SetValueClass.value == 3
        
            mc = MyClass()
            mc.value = 4
        
            sub = SubClass()
            sub.value = 7
            assert sub.value == 7
            assert SubClass.value == 7
            assert SubClass._VALUE == 7
        
            # MyClass.value is the new class_property from SubClass, because of the shared metaclass
            assert mc.value == 7
            assert MyClass.value == 7
            assert SetValueClass.value == 7
        
        
        If you want a disconnected new `class_property` then you need a new metaclass.
        
        Example:
        
        .. code-block:: python
        
            from class_property import class_property
        
        
            class MyClass(object, metaclass=class_property.metaclass()):
                _VALUE1 = 1
        
                @class_property
                def value(self):
                    return MyClass._VALUE1
        
                @value.setter
                def value(self, val):
                    MyClass._VALUE1 = val
        
        
            class SubClass(MyClass, metaclass=class_property.metaclass(MyClass)):
                _VALUE2 = 2
        
                # Because we have a different metaclass `SubClass.value` is different from `MyClass.value`
                @class_property
                def value():
                    return SubClass._VALUE2
        
                @value.setter
                def value(val):
                    SubClass._VALUE2 = val
        
        
            mc = MyClass()
            mc.value = 4
        
            # SubClass.value is using a different metaclass and is disconnected from MyClass
            sub = SubClass()
            sub.value = 7
            assert sub.value == 7
            assert SubClass.value == 7
            assert SubClass._VALUE2 == 7
        
            # MyClass.value is using a different metaclass and is disconnected from SubClass
            assert mc.value == 4
            assert MyClass.value == 4
            assert MyClass._VALUE1 == 4
        
Keywords: class property class value class_property class_value classproperty classvalue
Platform: any
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
