MultiProxPy 0.1.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {multiproxpy-0.1.0 → multiproxpy-0.2.1}/PKG-INFO +3 -2
- {multiproxpy-0.1.0 → multiproxpy-0.2.1}/README.md +2 -1
- {multiproxpy-0.1.0 → multiproxpy-0.2.1}/pyproject.toml +1 -1
- multiproxpy-0.2.1/src/MultiProxPy/ModifyMultiProxy.py +175 -0
- {multiproxpy-0.1.0 → multiproxpy-0.2.1}/src/MultiProxPy/MultiProxyClass.py +21 -4
- multiproxpy-0.2.1/src/MultiProxPy/__init__.py +15 -0
- multiproxpy-0.1.0/src/MultiProxPy/__init__.py +0 -3
- {multiproxpy-0.1.0 → multiproxpy-0.2.1}/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MultiProxPy
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: An easy way to combine multiple objects into one
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -36,7 +36,8 @@ The grouping is very abstract and should work with any type of object.
|
|
|
36
36
|
|
|
37
37
|
The best part is that your IDE will treat the proxy-object like one of the contained objects.
|
|
38
38
|
It will suggest methods/attributes bound to that class:\
|
|
39
|
-

|
|
39
|
+
\
|
|
40
|
+
(The image might not show on PyPi. Here is the link: https://github.com/CheesecakeTV/MultiProxPy/blob/main/assets/images/SuggestionsOnProxyObject.png)
|
|
40
41
|
|
|
41
42
|
Other examples can be found in the github-repository: https://github.com/CheesecakeTV/MultiProxPy
|
|
42
43
|
|
|
@@ -21,7 +21,8 @@ The grouping is very abstract and should work with any type of object.
|
|
|
21
21
|
|
|
22
22
|
The best part is that your IDE will treat the proxy-object like one of the contained objects.
|
|
23
23
|
It will suggest methods/attributes bound to that class:\
|
|
24
|
-

|
|
24
|
+
\
|
|
25
|
+
(The image might not show on PyPi. Here is the link: https://github.com/CheesecakeTV/MultiProxPy/blob/main/assets/images/SuggestionsOnProxyObject.png)
|
|
25
26
|
|
|
26
27
|
Other examples can be found in the github-repository: https://github.com/CheesecakeTV/MultiProxPy
|
|
27
28
|
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
from typing import Any, Callable, Iterable, TypeVar
|
|
2
|
+
from MultiProxPy import MultiProxy
|
|
3
|
+
from functools import wraps
|
|
4
|
+
|
|
5
|
+
def _typecheck_multiprox(fct: Callable):
|
|
6
|
+
"""
|
|
7
|
+
Only allows an instance of Multiproxy as the first parameter
|
|
8
|
+
:param fct:
|
|
9
|
+
:return:
|
|
10
|
+
"""
|
|
11
|
+
@wraps(fct)
|
|
12
|
+
def inner(*args, **kwargs):
|
|
13
|
+
if not isinstance(args[0], MultiProxy):
|
|
14
|
+
raise TypeError("The passed object is not a MultiProxy.")
|
|
15
|
+
|
|
16
|
+
return fct(*args, **kwargs)
|
|
17
|
+
|
|
18
|
+
return inner
|
|
19
|
+
|
|
20
|
+
@_typecheck_multiprox
|
|
21
|
+
def get_object_list(multi_proxy: MultiProxy | Any) -> list[object]:
|
|
22
|
+
"""
|
|
23
|
+
Returns the inner list of the given multi-proxy.
|
|
24
|
+
You may use it to edit the contents of a MultiProxy.
|
|
25
|
+
|
|
26
|
+
Use at your own risk, there are no type-checks beyond this point!
|
|
27
|
+
|
|
28
|
+
:param multi_proxy:
|
|
29
|
+
:return:
|
|
30
|
+
"""
|
|
31
|
+
return object.__getattribute__(multi_proxy, "_objects")
|
|
32
|
+
|
|
33
|
+
@_typecheck_multiprox
|
|
34
|
+
def get_inner_type(multi_proxy: MultiProxy | Any) -> type:
|
|
35
|
+
"""
|
|
36
|
+
Return the assumed type of a multi-proxy.
|
|
37
|
+
:param multi_proxy:
|
|
38
|
+
:return:
|
|
39
|
+
"""
|
|
40
|
+
return object.__getattribute__(multi_proxy, "_type")
|
|
41
|
+
|
|
42
|
+
def _assert_type_match(multi_proxy: MultiProxy | Any, *objects: object, assert_match: bool = True) -> bool:
|
|
43
|
+
"""
|
|
44
|
+
Check if all objects
|
|
45
|
+
:param multi_proxy:
|
|
46
|
+
:param objects:
|
|
47
|
+
:return:
|
|
48
|
+
"""
|
|
49
|
+
main_type: type = get_inner_type(multi_proxy)
|
|
50
|
+
all_mismatching = tuple(filter(lambda a:not isinstance(a, main_type), objects))
|
|
51
|
+
is_matching = not all_mismatching
|
|
52
|
+
|
|
53
|
+
if not (is_matching or assert_match):
|
|
54
|
+
raise TypeError("The passed objects do not match with the multi-proxys inner type.\n"
|
|
55
|
+
f"Expected {main_type}, got some mismatching: {all_mismatching}\n"
|
|
56
|
+
f"You may turn off this check by passing assert_type=False to the function you called.")
|
|
57
|
+
|
|
58
|
+
return is_matching
|
|
59
|
+
|
|
60
|
+
T = TypeVar("T")
|
|
61
|
+
@_typecheck_multiprox
|
|
62
|
+
def append_object(multi_proxy: MultiProxy | Any, to_append: T, assert_type: bool = True) -> T:
|
|
63
|
+
"""
|
|
64
|
+
Add a single object to a multi-proxy.
|
|
65
|
+
The added object is returned, so you can call this function inline
|
|
66
|
+
|
|
67
|
+
:param multi_proxy:
|
|
68
|
+
:param to_append:
|
|
69
|
+
:param assert_type:
|
|
70
|
+
:return:
|
|
71
|
+
"""
|
|
72
|
+
_assert_type_match(multi_proxy, to_append, assert_match=assert_type)
|
|
73
|
+
|
|
74
|
+
inner_list = get_object_list(multi_proxy)
|
|
75
|
+
inner_list.append(to_append)
|
|
76
|
+
return to_append
|
|
77
|
+
|
|
78
|
+
def extend_proxy(multi_proxy: MultiProxy | Any, iter_to_extend: Iterable[T], assert_type: bool = True) -> Iterable[T]:
|
|
79
|
+
"""
|
|
80
|
+
Adds all elements from iter_to_extend to the passed multi_proxy.
|
|
81
|
+
The passed iterable is returned, so you can call this function inline.
|
|
82
|
+
|
|
83
|
+
Just remember that some iterables depleat. If the returned iterable is empty, convert it to a list first.
|
|
84
|
+
|
|
85
|
+
:param multi_proxy:
|
|
86
|
+
:param iter_to_extend:
|
|
87
|
+
:param assert_type:
|
|
88
|
+
:return:
|
|
89
|
+
"""
|
|
90
|
+
iter_tuple = tuple(iter_to_extend)
|
|
91
|
+
_assert_type_match(multi_proxy, *iter_tuple, assert_match=assert_type)
|
|
92
|
+
|
|
93
|
+
inner_list = get_object_list(multi_proxy)
|
|
94
|
+
inner_list.extend(iter_tuple)
|
|
95
|
+
|
|
96
|
+
return iter_to_extend
|
|
97
|
+
|
|
98
|
+
@_typecheck_multiprox
|
|
99
|
+
def append_objects(multi_proxy: MultiProxy | Any, *objects: object, assert_type: bool = True):
|
|
100
|
+
"""
|
|
101
|
+
Add objects to a multi-proxy
|
|
102
|
+
|
|
103
|
+
:param multi_proxy:
|
|
104
|
+
:param objects:
|
|
105
|
+
:param assert_type:
|
|
106
|
+
:return:
|
|
107
|
+
"""
|
|
108
|
+
_assert_type_match(multi_proxy, *objects, assert_match=assert_type)
|
|
109
|
+
|
|
110
|
+
inner_list = get_object_list(multi_proxy)
|
|
111
|
+
for obj in objects:
|
|
112
|
+
inner_list.append(obj)
|
|
113
|
+
|
|
114
|
+
@_typecheck_multiprox
|
|
115
|
+
def remove_index(multi_proxy: MultiProxy | Any, index: int) -> object:
|
|
116
|
+
"""
|
|
117
|
+
Remove the linked object at that index from the passed multi-proxy.
|
|
118
|
+
|
|
119
|
+
:param multi_proxy:
|
|
120
|
+
:param index:
|
|
121
|
+
:return:
|
|
122
|
+
"""
|
|
123
|
+
inner_list = get_object_list(multi_proxy)
|
|
124
|
+
return inner_list.pop(index)
|
|
125
|
+
|
|
126
|
+
@_typecheck_multiprox
|
|
127
|
+
def remove_object_by_value(multi_proxy: MultiProxy | Any, value_to_remove: object) -> object:
|
|
128
|
+
"""
|
|
129
|
+
Remove the passed object from the passed multi-proxy and return its object.
|
|
130
|
+
The object is identified by its value.
|
|
131
|
+
|
|
132
|
+
:param multi_proxy:
|
|
133
|
+
:param value_to_remove: Value of the object to unlink
|
|
134
|
+
:return:
|
|
135
|
+
"""
|
|
136
|
+
inner_list = get_object_list(multi_proxy)
|
|
137
|
+
index = inner_list.index(value_to_remove)
|
|
138
|
+
return inner_list.pop(index)
|
|
139
|
+
|
|
140
|
+
@_typecheck_multiprox
|
|
141
|
+
def remove_object(multi_proxy: MultiProxy | Any, object_to_remove: object, ignore_error: bool = False) -> object:
|
|
142
|
+
"""
|
|
143
|
+
Remove the passed object from the passed multi-proxy and return the object.
|
|
144
|
+
The object is defined by the memory-address, so the passed object must be actually the same one.
|
|
145
|
+
|
|
146
|
+
:param multi_proxy:
|
|
147
|
+
:param object_to_remove: Object to unlink
|
|
148
|
+
:param ignore_error: If the object is not found, do nothing
|
|
149
|
+
:return:
|
|
150
|
+
"""
|
|
151
|
+
inner_list = get_object_list(multi_proxy)
|
|
152
|
+
|
|
153
|
+
ids = tuple(map(id, inner_list))
|
|
154
|
+
try:
|
|
155
|
+
index = ids.index(id(object_to_remove))
|
|
156
|
+
except ValueError:
|
|
157
|
+
if ignore_error:
|
|
158
|
+
return object_to_remove
|
|
159
|
+
raise ValueError("The object to remove is not linked to this multi-proxy.\n"
|
|
160
|
+
"You may pass ignore_error=True to do nothing instead of raising an error.")
|
|
161
|
+
|
|
162
|
+
return inner_list.pop(index)
|
|
163
|
+
|
|
164
|
+
@_typecheck_multiprox
|
|
165
|
+
def remove_all(multi_proxy: MultiProxy | Any):
|
|
166
|
+
"""
|
|
167
|
+
Unlink all elements from a multi-proxy
|
|
168
|
+
:param multi_proxy:
|
|
169
|
+
:return:
|
|
170
|
+
"""
|
|
171
|
+
inner_list = get_object_list(multi_proxy)
|
|
172
|
+
inner_list.clear()
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
@@ -2,19 +2,24 @@ from typing import TypeVar
|
|
|
2
2
|
|
|
3
3
|
class MultiProxy:
|
|
4
4
|
|
|
5
|
-
_objects:
|
|
5
|
+
_objects: list[object] # Objects to call the methods from
|
|
6
|
+
_type: type # Type of object in this element
|
|
6
7
|
|
|
7
8
|
def __init__(
|
|
8
9
|
self,
|
|
9
10
|
*objects: object,
|
|
11
|
+
assume_type: type | None = None,
|
|
10
12
|
):
|
|
11
13
|
"""
|
|
12
14
|
Do not call directly!
|
|
13
15
|
Use group_objects instead!
|
|
14
16
|
"""
|
|
15
|
-
|
|
17
|
+
if assume_type is None:
|
|
18
|
+
assert objects, "At least one object or a specific type is required to create a MultiProxy!"
|
|
19
|
+
assume_type = type(objects[0])
|
|
16
20
|
|
|
17
|
-
super().__setattr__("
|
|
21
|
+
super().__setattr__("_type", assume_type)
|
|
22
|
+
super().__setattr__("_objects", list(objects))
|
|
18
23
|
|
|
19
24
|
def __getattribute__(self, item):
|
|
20
25
|
objects = super().__getattribute__("_objects")
|
|
@@ -111,7 +116,6 @@ def group_objects(
|
|
|
111
116
|
:param check_type_mismatch: False to go the dangerous route of mixing together types
|
|
112
117
|
:return:
|
|
113
118
|
"""
|
|
114
|
-
|
|
115
119
|
if check_type_mismatch:
|
|
116
120
|
main_type = type(primary)
|
|
117
121
|
all_mismatching = tuple(filter(lambda a:not isinstance(a, main_type), others))
|
|
@@ -128,5 +132,18 @@ def group_objects(
|
|
|
128
132
|
|
|
129
133
|
return my_caller
|
|
130
134
|
|
|
135
|
+
def create_empty_proxy(object_type: type[inner_type]) -> inner_type:
|
|
136
|
+
"""
|
|
137
|
+
Create an empty "group" of objects with the passed type.
|
|
138
|
+
This way, you may add the objects of that group later on.
|
|
139
|
+
|
|
140
|
+
:param object_type:
|
|
141
|
+
:return:
|
|
142
|
+
"""
|
|
143
|
+
my_caller = MultiProxy(
|
|
144
|
+
assume_type=object_type,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
return my_caller
|
|
131
148
|
|
|
132
149
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
from .MultiProxyClass import MultiProxy, group_objects, create_empty_proxy
|
|
3
|
+
from .ModifyMultiProxy import (
|
|
4
|
+
get_inner_type,
|
|
5
|
+
get_object_list,
|
|
6
|
+
append_objects,
|
|
7
|
+
remove_object_by_value,
|
|
8
|
+
remove_index,
|
|
9
|
+
remove_object,
|
|
10
|
+
remove_all,
|
|
11
|
+
append_object,
|
|
12
|
+
extend_proxy,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
create_proxy = group_objects # Just an alias that might be easier for some people
|
|
File without changes
|