cengal.entities.bindable_to_type.versions.v_0.bindable_to_type

  1#!/usr/bin/env python
  2# coding=utf-8
  3
  4# Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>
  5# 
  6# Licensed under the Apache License, Version 2.0 (the "License");
  7# you may not use this file except in compliance with the License.
  8# You may obtain a copy of the License at
  9# 
 10#     http://www.apache.org/licenses/LICENSE-2.0
 11# 
 12# Unless required by applicable law or agreed to in writing, software
 13# distributed under the License is distributed on an "AS IS" BASIS,
 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15# See the License for the specific language governing permissions and
 16# limitations under the License.
 17
 18
 19__all__ = ['BindableToType', 'AlreadyBoundError', 'NotBoundYetError']
 20
 21
 22"""
 23Module Docstring
 24Docstrings: http://www.python.org/dev/peps/pep-0257/
 25"""
 26
 27__author__ = "ButenkoMS <gtalk@butenkoms.space>"
 28__copyright__ = "Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>"
 29__credits__ = ["ButenkoMS <gtalk@butenkoms.space>", ]
 30__license__ = "Apache License, Version 2.0"
 31__version__ = "4.4.1"
 32__maintainer__ = "ButenkoMS <gtalk@butenkoms.space>"
 33__email__ = "gtalk@butenkoms.space"
 34# __status__ = "Prototype"
 35__status__ = "Development"
 36# __status__ = "Production"
 37
 38
 39from typing import Tuple, Any, Optional
 40from inspect import isclass
 41
 42
 43class AlreadyBoundError(Exception):
 44    pass
 45
 46
 47class NotBoundYetError(Exception):
 48    pass
 49
 50
 51class BindableToType:
 52    """ Bindable to type or to type of given object
 53
 54    Example:
 55
 56        class MyGlobalData(BindableToType):
 57            def __init__(self) -> None:
 58                super().__init__()
 59                self.data = 2
 60
 61
 62        class MyStructure:
 63            global_data = MyGlobalData()
 64            def __init__(self):
 65                self.index = 3
 66
 67
 68        print(f'{MyStructure.global_data.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data')
 69
 70        ms = MyStructure()
 71
 72        print(f'{ms.global_data.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data')
 73
 74        MyGlobalData().bind(MyStructure, 'global_data_2')
 75
 76        print(f'{ms.global_data_2.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data')
 77        print(f'{MyStructure.global_data_2.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data')
 78
 79        MyGlobalData().bind(ms, 'global_data_3')
 80
 81        print(f'{ms.global_data_3.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data_2')
 82        print(f'{MyStructure.global_data_3.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data_2')
 83    """    
 84    def __init__(self) -> None:
 85        self._bound_to_owner_type = None
 86        self._bound_to_name = None
 87    
 88    def on_bind(self, owner_type, name):
 89        pass
 90    
 91    def on_unbind(self, owner_type, name):
 92        pass
 93
 94    def __set_name__(self, owner_type, name):
 95        self._bound_to_owner_type = owner_type
 96        self._bound_to_name = name
 97        self.on_bind(owner_type, name)
 98    
 99    def bind(self, owner_type_or_obj, name):
100        if self._bound_to_owner_type is not None:
101            raise AlreadyBoundError
102        
103        if isclass(owner_type_or_obj):
104            owner_class = owner_type_or_obj
105        else:
106            owner_class = type(owner_type_or_obj)
107        
108        setattr(owner_class, name, self)
109        self.__set_name__(owner_class, name)
110    
111    def unbind(self) -> Tuple[Any, str]:
112        if self._bound_to_owner_type is None:
113            raise NotBoundYetError
114        
115        delattr(self._bound_to_owner_type, self._bound_to_name)
116        result = (self._bound_to_owner_type, self._bound_to_name)
117        self._bound_to_owner_type = None
118        self._bound_to_name = None
119        self.on_unbind(self._bound_to_owner_type, self._bound_to_name)
120        return result
121    
122    def bound(self) -> bool:
123        return self._bound_to_owner_type is not None
124    
125    def bound_to(self) -> Optional[Tuple[Any, str]]:
126        result = None
127        if self.bound():
128            result = (self._bound_to_owner_type, self._bound_to_name)
129        
130        return result
131    
132    def force_bind(self, owner_type_or_obj, name) -> Optional[Tuple[Any, str]]:
133        result = None
134        if self.bound():
135            result = self.unbind()
136        
137        self.bind(owner_type_or_obj, name)
138        return result
class BindableToType:
 52class BindableToType:
 53    """ Bindable to type or to type of given object
 54
 55    Example:
 56
 57        class MyGlobalData(BindableToType):
 58            def __init__(self) -> None:
 59                super().__init__()
 60                self.data = 2
 61
 62
 63        class MyStructure:
 64            global_data = MyGlobalData()
 65            def __init__(self):
 66                self.index = 3
 67
 68
 69        print(f'{MyStructure.global_data.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data')
 70
 71        ms = MyStructure()
 72
 73        print(f'{ms.global_data.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data')
 74
 75        MyGlobalData().bind(MyStructure, 'global_data_2')
 76
 77        print(f'{ms.global_data_2.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data')
 78        print(f'{MyStructure.global_data_2.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data')
 79
 80        MyGlobalData().bind(ms, 'global_data_3')
 81
 82        print(f'{ms.global_data_3.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data_2')
 83        print(f'{MyStructure.global_data_3.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data_2')
 84    """    
 85    def __init__(self) -> None:
 86        self._bound_to_owner_type = None
 87        self._bound_to_name = None
 88    
 89    def on_bind(self, owner_type, name):
 90        pass
 91    
 92    def on_unbind(self, owner_type, name):
 93        pass
 94
 95    def __set_name__(self, owner_type, name):
 96        self._bound_to_owner_type = owner_type
 97        self._bound_to_name = name
 98        self.on_bind(owner_type, name)
 99    
100    def bind(self, owner_type_or_obj, name):
101        if self._bound_to_owner_type is not None:
102            raise AlreadyBoundError
103        
104        if isclass(owner_type_or_obj):
105            owner_class = owner_type_or_obj
106        else:
107            owner_class = type(owner_type_or_obj)
108        
109        setattr(owner_class, name, self)
110        self.__set_name__(owner_class, name)
111    
112    def unbind(self) -> Tuple[Any, str]:
113        if self._bound_to_owner_type is None:
114            raise NotBoundYetError
115        
116        delattr(self._bound_to_owner_type, self._bound_to_name)
117        result = (self._bound_to_owner_type, self._bound_to_name)
118        self._bound_to_owner_type = None
119        self._bound_to_name = None
120        self.on_unbind(self._bound_to_owner_type, self._bound_to_name)
121        return result
122    
123    def bound(self) -> bool:
124        return self._bound_to_owner_type is not None
125    
126    def bound_to(self) -> Optional[Tuple[Any, str]]:
127        result = None
128        if self.bound():
129            result = (self._bound_to_owner_type, self._bound_to_name)
130        
131        return result
132    
133    def force_bind(self, owner_type_or_obj, name) -> Optional[Tuple[Any, str]]:
134        result = None
135        if self.bound():
136            result = self.unbind()
137        
138        self.bind(owner_type_or_obj, name)
139        return result

Bindable to type or to type of given object

Example:

class MyGlobalData(BindableToType):
    def __init__(self) -> None:
        super().__init__()
        self.data = 2


class MyStructure:
    global_data = MyGlobalData()
    def __init__(self):
        self.index = 3


print(f'{MyStructure.global_data.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data')

ms = MyStructure()

print(f'{ms.global_data.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data')

MyGlobalData().bind(MyStructure, 'global_data_2')

print(f'{ms.global_data_2.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data')
print(f'{MyStructure.global_data_2.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data')

MyGlobalData().bind(ms, 'global_data_3')

print(f'{ms.global_data_3.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data_2')
print(f'{MyStructure.global_data_3.bound_to() = }')  # (<class '__main__.MyStructure'>, 'global_data_2')
def on_bind(self, owner_type, name):
89    def on_bind(self, owner_type, name):
90        pass
def on_unbind(self, owner_type, name):
92    def on_unbind(self, owner_type, name):
93        pass
def bind(self, owner_type_or_obj, name):
100    def bind(self, owner_type_or_obj, name):
101        if self._bound_to_owner_type is not None:
102            raise AlreadyBoundError
103        
104        if isclass(owner_type_or_obj):
105            owner_class = owner_type_or_obj
106        else:
107            owner_class = type(owner_type_or_obj)
108        
109        setattr(owner_class, name, self)
110        self.__set_name__(owner_class, name)
def unbind(self) -> Tuple[Any, str]:
112    def unbind(self) -> Tuple[Any, str]:
113        if self._bound_to_owner_type is None:
114            raise NotBoundYetError
115        
116        delattr(self._bound_to_owner_type, self._bound_to_name)
117        result = (self._bound_to_owner_type, self._bound_to_name)
118        self._bound_to_owner_type = None
119        self._bound_to_name = None
120        self.on_unbind(self._bound_to_owner_type, self._bound_to_name)
121        return result
def bound(self) -> bool:
123    def bound(self) -> bool:
124        return self._bound_to_owner_type is not None
def bound_to(self) -> Union[Tuple[Any, str], NoneType]:
126    def bound_to(self) -> Optional[Tuple[Any, str]]:
127        result = None
128        if self.bound():
129            result = (self._bound_to_owner_type, self._bound_to_name)
130        
131        return result
def force_bind(self, owner_type_or_obj, name) -> Union[Tuple[Any, str], NoneType]:
133    def force_bind(self, owner_type_or_obj, name) -> Optional[Tuple[Any, str]]:
134        result = None
135        if self.bound():
136            result = self.unbind()
137        
138        self.bind(owner_type_or_obj, name)
139        return result
class AlreadyBoundError(builtins.Exception):
44class AlreadyBoundError(Exception):
45    pass

Common base class for all non-exit exceptions.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
class NotBoundYetError(builtins.Exception):
48class NotBoundYetError(Exception):
49    pass

Common base class for all non-exit exceptions.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args