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
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
class
AlreadyBoundError(builtins.Exception):
Common base class for all non-exit exceptions.
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback
- args
class
NotBoundYetError(builtins.Exception):
Common base class for all non-exit exceptions.
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback
- args