memorymanagement 1.4.0__tar.gz → 1.4.2__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: memorymanagement
3
- Version: 1.4.0
3
+ Version: 1.4.2
4
4
  Summary: Adds support for memory management
5
5
  Home-page: https://github.com/Ricardo-Werner-Rivas/memorymanagement/tree/PyPI
6
6
  Author: Ricardo Werner Rivas
@@ -104,6 +104,18 @@ cleaner.exclude(<name_var_1>,<name_var_2>,...)
104
104
  ```py
105
105
  cleaner.include(<name_var_1>,<name_var_2>,...)
106
106
  ```
107
+ To flag all the excluded variables at once, you can use:
108
+ ```py
109
+ cleaner.include_all(exclude=[<var_1>,<var_2>,...]) # exclude: optional keyword argument, accepts strings and iterables of strings
110
+ ```
111
+ You can also exclude all the flagged variables like so:
112
+ ```py
113
+ cleaner.exclude_all(include=[<var_1>,<var_2>,...]) # include: optional keyword argument, accepts strings and iterables of strings
114
+ ```
115
+ And reset the cleaner's parameters like so:
116
+ ```py
117
+ cleaner.purge()
118
+ ```
107
119
  ### Class `Pointer`
108
120
  Example:
109
121
  ```py
@@ -88,6 +88,18 @@ cleaner.exclude(<name_var_1>,<name_var_2>,...)
88
88
  ```py
89
89
  cleaner.include(<name_var_1>,<name_var_2>,...)
90
90
  ```
91
+ To flag all the excluded variables at once, you can use:
92
+ ```py
93
+ cleaner.include_all(exclude=[<var_1>,<var_2>,...]) # exclude: optional keyword argument, accepts strings and iterables of strings
94
+ ```
95
+ You can also exclude all the flagged variables like so:
96
+ ```py
97
+ cleaner.exclude_all(include=[<var_1>,<var_2>,...]) # include: optional keyword argument, accepts strings and iterables of strings
98
+ ```
99
+ And reset the cleaner's parameters like so:
100
+ ```py
101
+ cleaner.purge()
102
+ ```
91
103
  ### Class `Pointer`
92
104
  Example:
93
105
  ```py
@@ -1,5 +1,4 @@
1
1
  """
2
- # `memorymanagement` package
3
2
  Provides memory management support.
4
3
 
5
4
  ---
@@ -1,6 +1,5 @@
1
1
  """
2
- # Module `cleaning`
3
- Implements the class `Cleaner` to keep track of the references and erase it easily.
2
+ Implements the class `Cleaner` to keep track of the references and erase them easily.
4
3
  ## Overview
5
4
  Initialize a `Cleaner` object:
6
5
  ```
@@ -36,6 +35,31 @@ Flagged: ["x","y","z"]
36
35
  Excluded: []
37
36
 
38
37
  Not delete: <list(vars(modules["main"]))> # Unchanged since initialization
38
+ ```
39
+ To delete these variables from memory, use the `clean()` method:
40
+ ```
41
+ # Cleans memory
42
+ cleaner.clean()
43
+
44
+ # Print again the `Cleaner` instance
45
+ print(cleaner)
46
+ ```
47
+ The output will now be:
48
+ ```
49
+ Flagged: []
50
+
51
+ Excluded: []
52
+
53
+ Not delete: <list(vars(modules["main"]))> # Unchanged since initialization
54
+ ```
55
+ And if we print the global variables:
56
+ ```
57
+ print(list(globals()))
58
+ ```
59
+ The output will be:
60
+ ```
61
+ ["Cleaner","cleaner"]
62
+ ```
39
63
  """
40
64
  # Imports
41
65
  from .core import Cleaner
@@ -19,7 +19,6 @@ from sys import modules
19
19
  #* MAIN CLASS
20
20
  # Class "Cleaner"
21
21
  class Cleaner:
22
- #& Code comments
23
22
  """
24
23
  Class for references management. It keeps track of the names of the global variables to be deleted and deletes them when ordered.
25
24
 
@@ -71,18 +70,23 @@ class Cleaner:
71
70
 
72
71
  Arguments
73
72
  ---------
74
- not_delete : `list[str]`, Optional
73
+ not_delete : `list[str]`|`None`, Optional
75
74
  List of variables to never be deleted. It takes the list of global variables of the main module by default.
76
75
  excluded : `list[str]`, Optional
77
76
  List of variables to be excluded from the memory cleaning process. Empty list by default.
78
77
  flagged : `list[str]`, Optional
79
78
  List of variables to be erased from memory. Empty list by default.
80
79
  """
80
+ # If a "not_delete" list is not passed
81
81
  if not not_delete:
82
+ # Take the list of global variables of the main module
82
83
  not_delete=list(vars(modules["__main__"]))
84
+ # Loop through the global variables' dictionary of the main module
83
85
  for key,value in vars(modules["__main__"]).copy().items():
86
+ # Delete every other "Cleaner" object
84
87
  if isinstance(value,Cleaner) and key in vars(modules["__main__"]).keys():
85
88
  del vars(modules["__main__"])[key]
89
+ # Declare the main attributes
86
90
  self._not_delete=not_delete.copy()
87
91
  self._excluded=excluded.copy()
88
92
  self._flagged=flagged.copy()
@@ -102,16 +106,26 @@ class Cleaner:
102
106
  include : `str`|`list[str]`|`tuple[str]`|`None`, Optional
103
107
  Allows you to include a single (`str`) or multiple (`list` or `tuple`) variables. `None` by default.
104
108
  """
109
+ # If there are variables to exclude
105
110
  if exclude:
111
+ # If "exclude" content is a string
106
112
  if isinstance(exclude,str):
113
+ # Make it a list
107
114
  exclude=[exclude]
115
+ # Introduce the excluded variables into the corresponding lists
108
116
  self._excluded.extend([var for var in exclude if var not in self._excluded])
117
+ # If the are excluded variables to include
109
118
  if include:
119
+ # If "include" content is a string
110
120
  if isinstance(include,str):
121
+ # Make it a list
111
122
  include=[include]
123
+ # Loop for "include"
112
124
  for var in include:
125
+ # Remove every occurrence of the variables to include from the "excluded" list
113
126
  while var in self._excluded:
114
127
  self._excluded.remove(var)
128
+ # Rebuild the "flagged" list
115
129
  self._flagged=[var for var in list(vars(modules["__main__"]))if var not in self.not_delete and var not in self.excluded]
116
130
 
117
131
  # Exclude
@@ -124,9 +138,12 @@ class Cleaner:
124
138
  exclude : `tuple[str]`
125
139
  Stream of references to be excluded.
126
140
  """
141
+ # Loop for the variables to exclude
127
142
  for var in exclude:
143
+ # Remove from the "flagged" list
128
144
  while var in self._flagged:
129
145
  self._flagged.remove(var)
146
+ # Introduce variable into the "excluded" list
130
147
  if var not in self._excluded:
131
148
  self._excluded.append(var)
132
149
 
@@ -140,35 +157,91 @@ class Cleaner:
140
157
  include : `tuple[str]`
141
158
  Stream of references to be included.
142
159
  """
160
+ # Loop for the variables to "include"
143
161
  for var in include:
162
+ # Introduce variable into the "flagged" list
144
163
  if var not in self._flagged:
145
164
  self._flagged.append(var)
165
+ # Remove from excluded list
146
166
  while var in self._excluded:
147
167
  self._excluded.remove(var)
148
168
 
149
169
  # Include all excluded variables
150
- def include_all(self):
170
+ def include_all(self,*,exclude:str|list[str]|tuple[str]|None=None):
151
171
  """
152
172
  Flag all the excluded variables and clear the `excluded` list
173
+
174
+ Arguments
175
+ ---------
176
+ exclude : `str`|`list[str]`|`tuple[str]`|`None`, Optional
177
+ Variables not to be included into the `flagged` list
153
178
  """
179
+ # Introduce excluded variables into the "flagged" list
154
180
  self._flagged.extend(self.excluded)
181
+ # Clear the "excluded" list
155
182
  self._excluded.clear()
183
+
184
+ # If the are exceptions
185
+ if exclude:
186
+ # If "exclude" content is a string
187
+ if isinstance(exclude,str):
188
+ # Exclude variable
189
+ self.exclude(exclude)
190
+ # Else
191
+ else:
192
+ # Exclude variables (unpacking)
193
+ self.exclude(*exclude)
156
194
 
157
195
  # Exclude all flagged variables
158
- def exclude_all(self):
196
+ def exclude_all(self,*,include:str|list[str]|tuple[str]|None=None):
159
197
  """
160
198
  Exclude all the flagged variables and clear the `flagged` list
199
+
200
+ Arguments
201
+ ---------
202
+ include : `str`|`list[str]`|`tuple[str]`|`None`, Optional
203
+ Variables not to be excluded from the `flagged` list
161
204
  """
205
+ # Introduce excluded variables into the "excluded" list
162
206
  self._excluded.extend(self.flagged)
207
+ # Clear the "flagged" list
163
208
  self._flagged.clear()
209
+
210
+ # If there are exceptions
211
+ if include:
212
+ # If "include" content is a string
213
+ if isinstance(include,str):
214
+ # Include varianle
215
+ self.include(include)
216
+ # Else
217
+ else:
218
+ # Include variables (unpacking)
219
+ self.include(*include)
164
220
 
165
221
  # Purge flagged and excluded variables
166
- def purge(self):
222
+ def purge(self,*,flagged:bool=True,excluded:bool=True):
167
223
  """
168
224
  Clears both `flagged` and `excluded` lists from the `Cleaner` object.
225
+
226
+ Arguments
227
+ ---------
228
+ flagged : `bool`, Optional
229
+ Wether the `flagged` list should be purged (`True`) or not (`False`). `True` by default
230
+ excluded : `bool`, Optional
231
+ Wether the `excluded` list should be purged (`True`) or not (`False`). `True` by default
169
232
  """
170
- self._flagged.clear()
171
- self._excluded.clear()
233
+ # If there is no list to be purged
234
+ if not flagged and not excluded:
235
+ # Pass
236
+ pass
237
+ # If "flagged" is set to be purged
238
+ if flagged:
239
+ # Clear "flagged"
240
+ self._flagged.clear()
241
+ # If "excluded" is set to be purged
242
+ if excluded:
243
+ # Clear "excluded"
244
+ self._excluded.clear()
172
245
 
173
246
  # Clean
174
247
  def clean(self):
@@ -176,9 +249,13 @@ class Cleaner:
176
249
  Culminates the cleaning process.
177
250
  Erases all the flagged references.
178
251
  """
252
+ # Loop for "flagged" list
179
253
  for var in self._flagged:
254
+ # If current variable name is between the global variables of "__main__"
180
255
  if var in list(vars(modules["__main__"])):
256
+ # Delete variable
181
257
  del vars(modules["__main__"])[var]
258
+ # Clear "flagged" list
182
259
  self._flagged.clear()
183
260
 
184
261
  #* PROPERTIES
@@ -186,19 +263,32 @@ class Cleaner:
186
263
  @property
187
264
  # Getter
188
265
  def not_delete(self):
266
+ # If reference is not set or it doesn't point to the "Cleaner" object
189
267
  if not self._name or vars(modules["__main__"])[self._name] is not self:
268
+ # Loop for variables dictionary
190
269
  for key,value in vars(modules["__main__"]).items():
270
+ # If current value is the "Cleaner" object
191
271
  if value is self:
272
+ # Store the reference
192
273
  self._name=key
274
+ # Add it to the "not_delete" list
193
275
  self._not_delete.append(self._name)
276
+ # Break
194
277
  break
278
+ # Else
195
279
  else:
280
+ # Reference is still empty
196
281
  self._name=None
282
+ # If reference remains empty
197
283
  if not self._name:
198
- raise ReferenceError("'Cleaner' object is not referenced")
284
+ # Raise a "ReferenceError"
285
+ raise ReferenceError("\"Cleaner\" object is not referenced")
286
+ # Else, if reference is not in the "not_delete" list
199
287
  elif self._name not in self._not_delete:
288
+ # Add reference to the "not_delete" list
200
289
  self._not_delete.append(self._name)
201
- return self._not_delete
290
+ # Return a shallow copy of the "not_delete" list
291
+ return self._not_delete.copy()
202
292
  #^ No setter
203
293
  #^ No deleter
204
294
 
@@ -206,7 +296,8 @@ class Cleaner:
206
296
  @property
207
297
  # Getter
208
298
  def excluded(self):
209
- return self._excluded
299
+ # Return a shallow copy of the "excluded" list
300
+ return self._excluded.copy()
210
301
  #^ No setter
211
302
  #^ No deleter
212
303
 
@@ -214,13 +305,15 @@ class Cleaner:
214
305
  @property
215
306
  # Getter
216
307
  def flagged(self):
217
- return self._flagged
308
+ # Return a shallow copy of the "flagged" list
309
+ return self._flagged.copy()
218
310
  #^ No setter
219
311
  #^ No deleter
220
312
 
221
313
  #* SCREEN DUNDER METHODS
222
314
  # __str__
223
315
  def __str__(self):
316
+ # Return a string with the instance's components
224
317
  return f"""
225
318
  Flagged: {self.flagged}
226
319
 
@@ -231,4 +324,5 @@ class Cleaner:
231
324
 
232
325
  # __repr__
233
326
  def __repr__(self):
327
+ # Return a string able to rebuild the instance if needed
234
328
  return f"{self.__class__.__name__}(not_delete={self.not_delete},excluded={self.excluded},flagged={self.flagged})"
@@ -1,5 +1,4 @@
1
1
  """
2
- # Module `pointers`
3
2
  A safe implementation of pointers written in pure Python.
4
3
 
5
4
  It is safe beacause it doesn't imitate the internal behaviour of C pointers because it could break the memory.
@@ -25,7 +25,6 @@ PT=TypeVar("PT")
25
25
  #* MAIN CLASS
26
26
  # Define the class "Pointer" with generic type
27
27
  class Pointer(Generic[PT]):
28
- #& Missing code comments
29
28
  """
30
29
  Implements pointers in Python for both mutable (though unneded) and non-mutable objects.
31
30
  These pointers are completely safe and do not work internally as C's pointers, they are just an imitation of their behaviour.
@@ -102,31 +101,53 @@ class Pointer(Generic[PT]):
102
101
  local : `bool`, Optional
103
102
  Indicates if the value to point to is a local variable (`True` for yes and `False` for no). `False` by default.
104
103
  """
104
+ # If pointing to local variable
105
105
  if local:
106
+ # Take the local frame
106
107
  vars_dict=currentframe().f_back.f_locals
108
+ # Else
107
109
  else:
110
+ # Take the global frame
108
111
  vars_dict=vars(modules["__main__"])
109
- self._value=value
110
- self._vars_dict=vars_dict
111
- self._attr=attr
112
+
113
+ # Store hidden attributes
114
+ self._value=value # Pointer's value
115
+ self._vars_dict=vars_dict # Variables' frame
116
+ self._attr=attr # Instance attribute to point to
117
+
118
+ # If there is an instance's attribute to point to and it doesn't belong to the given value
112
119
  if self._attr and self._attr not in dir(self._value):
120
+ # Raise an "AttributeError"
113
121
  raise AttributeError(f"\"{attr}\" is not an attribute of \"{self._value}\"")
122
+ # If a reference is given
114
123
  if reference:
124
+ # If the reference is in the variables' frame and points to the given value
115
125
  if reference in vars_dict and vars_dict[reference] is value:
126
+ # Store the reference in "name" local variable
116
127
  name=reference
128
+ # Else, if the reference isn't in the variables' frame
117
129
  elif reference not in vars_dict:
130
+ # Raise a "NameError"
118
131
  raise NameError(f"Name \"{reference}\" is not defined")
132
+ # Else, if the reference doesn't point to the given value
119
133
  elif vars_dict[reference] is not value:
134
+ # Raise a "ValueError"
120
135
  raise ValueError(f"Name \"{reference}\" doesn't point to given value ({value})")
136
+ # Else
121
137
  else:
138
+ # Store every reference pointing to the given value
122
139
  name=[key for key,v in vars_dict.items() if v is value]
123
- name=name if len(name)!=0 else [None]
140
+ # Set to "None" if no reference was found
141
+ name=name[0] if len(name)!=0 else None
142
+ # Store the reference in the hidden attribute "_name"
124
143
  self._name=name
144
+ # If there is no reference
125
145
  if self._name==None:
146
+ # Raise a "NameError"
126
147
  raise NameError(f"No reference is pointing to given value \"{self._value}\"")
127
148
 
128
149
  # Point to
129
- def point_to(self,reference:str|None=None,value=None,*,attr:str|None=None):
150
+ def point_to(self,value=None,reference:str|None=None,*,attr:str|None=None):
130
151
  """
131
152
  Changes the address which the `Pointer` object points to.
132
153
 
@@ -139,48 +160,103 @@ class Pointer(Generic[PT]):
139
160
  attr : `str`|`None`, Optional
140
161
  Attribute of the class if class object was passed through `reference` or `value`.
141
162
  """
163
+ # If no reference or value is given
142
164
  if not reference and not value:
143
- pass
165
+ # If an instance's attribute name is given
166
+ if attr:
167
+ # If the attribute belongs to the pointer's value
168
+ if attr in dir(self._value):
169
+ # Store the attribute name into its corresponding hidden attribute
170
+ self._attr=attr
171
+ # Else
172
+ else:
173
+ # Raise an "AttributeError"
174
+ raise AttributeError(f"\"{attr}\" isn't an attribute of the variable \"{self._name}\" with value \"{self._value}\" (\"{self._value.__class__.__name__}\")")
175
+ # Else
176
+ else:
177
+ # Raise a "ValueError"
178
+ raise ValueError("No argument was given")
179
+ # Else, if both reference and value are given
144
180
  elif reference and value:
181
+ # If the reference is in the variables' frame and it points to the given value
145
182
  if reference in self._vars_dict and self._vars_dict[reference] is value:
183
+ # Store both into their corresponding hidden attributes
146
184
  self._name,self._value=reference,value
185
+ # If an attribute name is given
147
186
  if attr:
187
+ # If the attribute belongs to the given value
148
188
  if attr in dir(self._value):
189
+ # Store attribute name into its corresponding hidden attribute
149
190
  self._attr=attr
191
+ # Else
150
192
  else:
193
+ # Raise an "AttributeError"
151
194
  raise AttributeError(f"\"{attr}\" is not an attribute of \"{self._value}\"")
195
+ # Else, if the reference isn't in the variables' frame
152
196
  elif reference not in self._vars_dict:
197
+ # Raise a "NameError"
153
198
  raise NameError(f"Name \"{reference}\" is not defined")
199
+ # Else, if the reference doesn't point to the given value
154
200
  elif self._vars_dict[reference] is not value:
201
+ # Raise a "ValueError"
155
202
  raise ValueError(f"Name \"{reference}\" doesn't point to given value \"{value}\"")
203
+ # Else, if only a reference is given
156
204
  elif reference:
205
+ # If the reference is in the variables' frame
157
206
  if reference in self._vars_dict:
207
+ # Store the reference and the value it is pointing to into their corresponding hidden attributes
158
208
  self._name,self._value=reference,self._vars_dict[reference]
209
+ # If an instance's attribute name is given
159
210
  if attr:
211
+ # If the attribute belongs to the new value
160
212
  if attr in dir(self._value):
213
+ # Store the attribute name into its corresponding hidden attribute
161
214
  self._attr=attr
215
+ # Else
162
216
  else:
217
+ # Raise an "AttributeError"
163
218
  raise AttributeError(f"\"{attr}\" is not an attribute of \"{self._value}\"")
219
+ # Else
164
220
  else:
221
+ # Raise a "NameError"
165
222
  raise NameError(f"Name \"{reference}\" is not defined")
223
+ # Else, if only a value is given
166
224
  elif value:
225
+ # Store the given value and its references into their corresponding hidden attributes
167
226
  self._name,self._value=[key for key,v in self._vars_dict.items() if v is value],value
168
- self._name=self._name if len(self._name)!=0 else [None]
227
+ # Modify the "_name" hidden attribute to be a string or "None"
228
+ self._name=self._name[0] if len(self._name)!=0 else None
229
+ # If no reference was found
169
230
  if self._name==None:
231
+ # Raise a "NameError"
170
232
  raise NameError(f"No reference is pointing to given value \"{self._value}\"")
233
+ # If an instance's attribute name is given
171
234
  if attr:
235
+ # If the attribute belongs to the new value
172
236
  if attr in dir(self._value):
237
+ # Store the attribute name into its corresponding hidden attribute
173
238
  self._attr=attr
239
+ # Else
174
240
  else:
241
+ # Raise an "AttributeError"
175
242
  raise AttributeError(f"\"{attr}\" is not an attribute of \"{self._value}\"")
176
243
 
177
244
  # Get references
178
- def get_refs(self):
245
+ def get_refs(self)->tuple[str]:
179
246
  """
180
247
  Gets all the references pointing to the same current value of the `Pointer` object.
181
248
  """
249
+ # Find and return all the references pointing to the pointer's value
182
250
  return tuple(key for key,v in self._vars_dict.items() if v is self._value)
183
251
 
252
+ # Print references
253
+ def print_refs(self):
254
+ """
255
+ Prints all the references pointing to the same current value of the pointer.
256
+ """
257
+ # Print all the references pointing to the pointer's value
258
+ print(tuple(key for key,v in self._vars_dict.items() if v is self._value))
259
+
184
260
  # Switch reference
185
261
  def switch_ref(self,reference:str):
186
262
  """
@@ -191,65 +267,90 @@ class Pointer(Generic[PT]):
191
267
  reference : `str`
192
268
  Reference to switch the pointer to.
193
269
  """
270
+ # If the given reference is in the variables' frame but it doesn' point to current the pointer's value
194
271
  if reference in self._vars_dict and self._vars_dict[reference] is not self.value:
272
+ # Raise a "ValueError"
195
273
  raise ValueError(f"Name \"{reference}\" doesn't point to pointer's value \"{self.value}\"")
274
+ # Else, if the given reference is not in the variables' frame
196
275
  elif reference not in self._vars_dict:
276
+ # Raise a "NameError"
197
277
  raise NameError(f"Name \"{reference}\" is not defined")
278
+ # Store the reference into its corresponding hidden attribute
198
279
  self._name=reference
199
280
 
200
- # Print references
201
- def print_refs(self):
202
- """
203
- Prints all the references pointing to the same current value of the pointer.
204
- """
205
- print(tuple(key for key,v in self._vars_dict.items() if v is self._value))
206
-
207
281
  #* PROPERTIES
208
282
  # Value
209
283
  @property
210
284
  # Getter
211
285
  def value(self):
286
+ # If an instance's attribute name is stored
212
287
  if self.attr:
288
+ # If the stored reference is not in the variables' frame
213
289
  if self.reference not in self._vars_dict:
290
+ # Delete the pointer's value and the stored attribute name
214
291
  del self._value,self.attr
292
+ # Raise a "NameError"
215
293
  raise NameError("The class instance has already been deleted, so the pointer no longer has access to it.")
294
+ # Else, if the stored attribute name doesn't belong to the pointer's value
216
295
  elif self.attr not in dir(self._value):
296
+ # Raise an "AttributeError"
217
297
  raise AttributeError(f"The atribute \"{self._attr}\" has already been deleted, so the pointer no longer has access to it.")
298
+ # Return the instance attribute's value
218
299
  return getattr(self._value,self.attr)
300
+ # Else
219
301
  else:
302
+ # If the stored reference is not in the variables' frame
220
303
  if self.reference not in self._vars_dict:
304
+ # Delete the pointer's hidden attribute "_value"
221
305
  del self._value
306
+ # Raise a "NameError"
222
307
  raise NameError("The variable has already been deleted, so the pointer no longer has access to it.")
308
+ # If the original value differs from the stored one (because it was changed)
223
309
  if self._value is not self._vars_dict[self.reference]:
310
+ # Update the pointer's value
224
311
  self._value=self._vars_dict[self.reference]
312
+ # Return the pointer's value
225
313
  return self._value
226
314
  # Setter
227
315
  @value.setter
228
316
  def value(self,value):
317
+ # If an attribute name is stored
229
318
  if self.attr:
319
+ # Set the instance' attribute to the new value
230
320
  setattr(self._value,self.attr,value)
321
+ # Else
231
322
  else:
323
+ # Set the pointers value to the new value
232
324
  self._value=value
325
+ # If the new pointer's value differs from the original variable
233
326
  if value is not self._vars_dict[self.reference]:
327
+ # Update the original variable setting it to the new value
234
328
  self._vars_dict[self.reference]=value
235
329
  # Deleter
236
330
  @value.deleter
237
331
  def value(self):
332
+ # If an attribute name is stored
238
333
  if self.attr:
334
+ # Delete the attribute from the stored instance
239
335
  delattr(self._value,self.attr)
336
+ # Else
240
337
  else:
338
+ # Delete the "_value" pointer's hidden attribute
241
339
  del self._value
340
+ # Delete the corresponding variable
242
341
  del self._vars_dict[self.reference]
243
342
 
244
343
  # Reference
245
344
  @property
246
345
  # Getter
247
346
  def reference(self):
347
+ # Return the stored reference
248
348
  return self._name
249
349
 
250
350
  # Attribute
251
351
  @property
252
352
  def attr(self):
353
+ # Return the stored attribute name
253
354
  return self._attr
254
355
 
255
356
  #* INDEXATION
@@ -259,11 +360,9 @@ class Pointer(Generic[PT]):
259
360
  # Setter
260
361
  def __setitem__(self,index,value):
261
362
  self.value[index]=value
262
- return
263
363
  # Deleter
264
364
  def __delitem__(self,index):
265
365
  del self.value[index]
266
- return
267
366
 
268
367
  #* ARITHMETIC OPERATIONS
269
368
  # Addition
@@ -35,10 +35,14 @@ def pointerize(func):
35
35
  func : `FunctionType`
36
36
  Decorated function.
37
37
  """
38
+ #* IDENTITY MANAGEMENT
38
39
  # Makes the decorating function to keep its identity
39
40
  @wraps(func)
41
+
42
+ #* WRAPPER
40
43
  # Define the wrapper
41
44
  def wrapper(*args,**kwargs):
45
+ #* SIGNATURE
42
46
  # Obtain the signature (parameters and defaults) of the decorated function
43
47
  sig=signature(func)
44
48
  # Bind call arguments to the signature
@@ -46,6 +50,7 @@ def pointerize(func):
46
50
  # Defaults all the arguments which haven't been passed
47
51
  bound.apply_defaults()
48
52
 
53
+ #* ARGUMENTS' MAPPING
49
54
  # Dictionary containing all the parameters
50
55
  param_map=bound.arguments
51
56
 
@@ -55,6 +60,7 @@ def pointerize(func):
55
60
  if isinstance(val,Pointer)
56
61
  }
57
62
 
63
+ #* EXECUTION ARGUMENTS
58
64
  # List containing all the positional arguments to be passed to the decorated function
59
65
  exec_args=[
60
66
  val.value if isinstance(val,Pointer) else val
@@ -66,7 +72,8 @@ def pointerize(func):
66
72
  for k,v in bound.kwargs.items()
67
73
  }
68
74
 
69
- # Empty dict, future source to update pointers' values
75
+ #* TRACKING
76
+ # Empty dictionary, future source to update pointers' values
70
77
  frame_data={}
71
78
 
72
79
  # Tracer function compatible with the sys.settrace API
@@ -74,10 +81,12 @@ def pointerize(func):
74
81
  if event=="return" and frame.f_code is func.__code__:
75
82
  frame_data.update(frame.f_locals)
76
83
  return tracer
84
+
77
85
  # Activate tracing
78
86
  settrace(tracer)
79
- # We try to execute the function
87
+ # Try to execute the function
80
88
  try:
89
+ # Storing its result
81
90
  result=func(*exec_args,**exec_kwargs)
82
91
  # Even if the program meets an error
83
92
  finally:
@@ -85,13 +94,16 @@ def pointerize(func):
85
94
  settrace(None)
86
95
  # If no exception or error is raised, the program continues from here
87
96
 
97
+ #* POINTERS' UPDATING
88
98
  # Iterates through the pointers
89
99
  for name,ptr in pointer_map.items():
90
- # Checks if the parameter name is in the traced frame (of local variables of the decorated function)
100
+ # Check if the parameter name is in the traced frame (of local variables of the decorated function)
91
101
  if name in frame_data:
92
102
  # In which case, the pointer's value is updated
93
103
  ptr.value=frame_data[name]
104
+ #* RETURNS
94
105
  # Return the result of the decorated function
95
106
  return result
107
+ #* RETURNS
96
108
  # Return the wrapper
97
109
  return wrapper
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memorymanagement
3
- Version: 1.4.0
3
+ Version: 1.4.2
4
4
  Summary: Adds support for memory management
5
5
  Home-page: https://github.com/Ricardo-Werner-Rivas/memorymanagement/tree/PyPI
6
6
  Author: Ricardo Werner Rivas
@@ -104,6 +104,18 @@ cleaner.exclude(<name_var_1>,<name_var_2>,...)
104
104
  ```py
105
105
  cleaner.include(<name_var_1>,<name_var_2>,...)
106
106
  ```
107
+ To flag all the excluded variables at once, you can use:
108
+ ```py
109
+ cleaner.include_all(exclude=[<var_1>,<var_2>,...]) # exclude: optional keyword argument, accepts strings and iterables of strings
110
+ ```
111
+ You can also exclude all the flagged variables like so:
112
+ ```py
113
+ cleaner.exclude_all(include=[<var_1>,<var_2>,...]) # include: optional keyword argument, accepts strings and iterables of strings
114
+ ```
115
+ And reset the cleaner's parameters like so:
116
+ ```py
117
+ cleaner.purge()
118
+ ```
107
119
  ### Class `Pointer`
108
120
  Example:
109
121
  ```py
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = memorymanagement
3
- version = 1.4.0
3
+ version = 1.4.2
4
4
  author = Ricardo Werner Rivas
5
5
  author_email = ricardowernerrivas@gmail.com
6
6
  description = Adds support for memory management