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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MultiProxPy
3
- Version: 0.1.0
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
- ![img.png](assets/images/SuggestionsOnProxyObject.png)
39
+ ![img.png](https://github.com/CheesecakeTV/MultiProxPy/blob/main/assets/images/SuggestionsOnProxyObject.png)\
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
- ![img.png](assets/images/SuggestionsOnProxyObject.png)
24
+ ![img.png](https://github.com/CheesecakeTV/MultiProxPy/blob/main/assets/images/SuggestionsOnProxyObject.png)\
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
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "MultiProxPy"
3
- version = "0.1.0"
3
+ version = "0.2.1"
4
4
  packages = [
5
5
  { include = "MultiProxPy", from = "src" }
6
6
  ]
@@ -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: tuple[object, ...] # Objects to call the methods from
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
- assert objects, "At least one object is required to create a MultiProxy!"
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__("_objects", objects)
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
@@ -1,3 +0,0 @@
1
-
2
- from .MultiProxyClass import MultiProxy, group_objects
3
-
File without changes