memorymanagement 1.0.0__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ricardo Werner Rivas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,162 @@
1
+ Metadata-Version: 2.4
2
+ Name: memorymanagement
3
+ Version: 1.0.0
4
+ Summary: Adds support for memory management
5
+ Home-page: https://github.com/Ricardo-Werner-Rivas/python-memory-management/tree/main
6
+ Author: Ricardo Werner Rivas
7
+ Author-email: ricardowernerrivas@gmail.com
8
+ License: MIT
9
+ Project-URL: Issues Page, https://github.com/Ricardo-Werner-Rivas/python-memory-management/issues
10
+ Project-URL: Repository, https://github.com/Ricardo-Werner-Rivas/python-memory-management
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Operating System :: Microsoft :: Windows
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Dynamic: license-file
16
+
17
+ # `memorymanagement`
18
+ Provides memory management support.
19
+ ## Modules
20
+ ### `cleaning`
21
+ Provides the class `Cleaner`, which allows you to flag references stored in memory to eventually erase them.
22
+ It is also possible to modify the list of flagged references through its methods.
23
+ ### `pointers`
24
+ Provides a safe implementation of pointers for Python.
25
+ #### Class `Pointer`
26
+ The pointer itself. Imitates the behaviour of C pointers. This pointer points to a reference, not to an object stored in memory.
27
+ #### Decorator `pointerize`
28
+ Allows functions to receive pointers instead of values.
29
+ ## Installation
30
+ You can install the `memorymanager` package from PyPI as follows:
31
+ ```bash
32
+ pip install memorymanagement
33
+ ```
34
+ You can also install the `memorymanager` package (Test PyPI versión of `memorymanager`) from TestPyPI as follows:
35
+ ```bash
36
+ pip install --index-url https://test.pypi.org/simple/ memorymanager
37
+ ```
38
+ For TestPyPI versión, `--no-deps` option is not needed because it has no dependencies.
39
+ ## How to use
40
+ ### Class `Cleaner`
41
+ ```py
42
+ # Imports
43
+ # Make your imports here
44
+ from memorymanagement import Cleaner # Importing class Cleaner
45
+ ```
46
+ Right after imports are done, I recommend to initialize an instance of class `Cleaner`, so no arguments are needed. This is the optimal use this class was designed for.
47
+ ```py
48
+ # Initialize cleaner object
49
+ cleaner=Cleaner()
50
+ ```
51
+ Create, for example, these global variables:
52
+ ```py
53
+ value_1=10
54
+ value_2=50
55
+ value_3=100
56
+ ```
57
+ Update the list of flagged references like one of the following:
58
+ * Including all new global variables:
59
+ ```py
60
+ cleaner.update()
61
+ print(cleaner.flagged)
62
+ ```
63
+ Output:
64
+ ```sh
65
+ ["value_1","value_2","value_3"]
66
+ ```
67
+ * Excluding some variables:
68
+ ```py
69
+ cleaner.update(exclude="value_2")
70
+ print(cleaner.flagged)
71
+ ```
72
+ Output:
73
+ ```sh
74
+ ["value_1","value_3"]
75
+ ```
76
+ ---
77
+ ```py
78
+ cleaner.update(exclude=["value_2","value_3"])
79
+ print(cleaner.flagged)
80
+ ```
81
+ Output:
82
+ ```sh
83
+ ["value_1"]
84
+ ```
85
+ * Include again some variables:
86
+
87
+ After having excluded some variables
88
+ ```py
89
+ cleaner.update(exclude=["value_2","value_3"])
90
+ ```
91
+ You can reintroduce them
92
+ ```py
93
+ # Create a new variable and update
94
+ value_4=150
95
+ cleaner.update(exclude="value_4",include="value_2") # "include" can also be a list of strings
96
+ print(cleaner.flagged)
97
+ ```
98
+ Output:
99
+ ```sh
100
+ ["value_1","value_2"]
101
+ ```
102
+ You can also directly include or exclude references like so:
103
+ ```py
104
+ cleaner.exclude(<name_var_1>,<name_var_2>,...)
105
+ ```
106
+ ```py
107
+ cleaner.include(<name_var_1>,<name_var_2>,...)
108
+ ```
109
+ ### Class `Pointer`
110
+ Example:
111
+ ```py
112
+ from memorymanagement import Pointer
113
+ a=10
114
+ x=Pointer(a)
115
+ print(f"a:\n{a}\n\nPointer:\n{x.value}\n\n")
116
+ a=20
117
+ print(f"a:\n{a}\n\nPointer:\n{x.value}\n\n")
118
+ a=10
119
+ x.value=20
120
+ print(f"a:\n{a}\n\nPointer:\n{x.value}")
121
+ ```
122
+ Output:
123
+ ```sh
124
+ a:
125
+ 10
126
+
127
+ Pointer:
128
+ 10
129
+
130
+
131
+ a:
132
+ 20
133
+
134
+ Pointer:
135
+ 20
136
+
137
+
138
+ a:
139
+ 20
140
+
141
+ Pointer:
142
+ 20
143
+ ```
144
+ ### Decorator `pointerize`
145
+ Example:
146
+ ```py
147
+ from memorymanagement import pointerize
148
+ @pointerize
149
+ def myFunction(value:int):
150
+ value=20
151
+ return
152
+ a=10
153
+ print(f"Value: {a}")
154
+ myFunction(Pointer(a))
155
+ print(f"Value: {a}")
156
+ ```
157
+ Output:
158
+ ```sh
159
+ Value: 10
160
+ Value: 20
161
+
162
+ ```
@@ -0,0 +1,146 @@
1
+ # `memorymanagement`
2
+ Provides memory management support.
3
+ ## Modules
4
+ ### `cleaning`
5
+ Provides the class `Cleaner`, which allows you to flag references stored in memory to eventually erase them.
6
+ It is also possible to modify the list of flagged references through its methods.
7
+ ### `pointers`
8
+ Provides a safe implementation of pointers for Python.
9
+ #### Class `Pointer`
10
+ The pointer itself. Imitates the behaviour of C pointers. This pointer points to a reference, not to an object stored in memory.
11
+ #### Decorator `pointerize`
12
+ Allows functions to receive pointers instead of values.
13
+ ## Installation
14
+ You can install the `memorymanager` package from PyPI as follows:
15
+ ```bash
16
+ pip install memorymanagement
17
+ ```
18
+ You can also install the `memorymanager` package (Test PyPI versión of `memorymanager`) from TestPyPI as follows:
19
+ ```bash
20
+ pip install --index-url https://test.pypi.org/simple/ memorymanager
21
+ ```
22
+ For TestPyPI versión, `--no-deps` option is not needed because it has no dependencies.
23
+ ## How to use
24
+ ### Class `Cleaner`
25
+ ```py
26
+ # Imports
27
+ # Make your imports here
28
+ from memorymanagement import Cleaner # Importing class Cleaner
29
+ ```
30
+ Right after imports are done, I recommend to initialize an instance of class `Cleaner`, so no arguments are needed. This is the optimal use this class was designed for.
31
+ ```py
32
+ # Initialize cleaner object
33
+ cleaner=Cleaner()
34
+ ```
35
+ Create, for example, these global variables:
36
+ ```py
37
+ value_1=10
38
+ value_2=50
39
+ value_3=100
40
+ ```
41
+ Update the list of flagged references like one of the following:
42
+ * Including all new global variables:
43
+ ```py
44
+ cleaner.update()
45
+ print(cleaner.flagged)
46
+ ```
47
+ Output:
48
+ ```sh
49
+ ["value_1","value_2","value_3"]
50
+ ```
51
+ * Excluding some variables:
52
+ ```py
53
+ cleaner.update(exclude="value_2")
54
+ print(cleaner.flagged)
55
+ ```
56
+ Output:
57
+ ```sh
58
+ ["value_1","value_3"]
59
+ ```
60
+ ---
61
+ ```py
62
+ cleaner.update(exclude=["value_2","value_3"])
63
+ print(cleaner.flagged)
64
+ ```
65
+ Output:
66
+ ```sh
67
+ ["value_1"]
68
+ ```
69
+ * Include again some variables:
70
+
71
+ After having excluded some variables
72
+ ```py
73
+ cleaner.update(exclude=["value_2","value_3"])
74
+ ```
75
+ You can reintroduce them
76
+ ```py
77
+ # Create a new variable and update
78
+ value_4=150
79
+ cleaner.update(exclude="value_4",include="value_2") # "include" can also be a list of strings
80
+ print(cleaner.flagged)
81
+ ```
82
+ Output:
83
+ ```sh
84
+ ["value_1","value_2"]
85
+ ```
86
+ You can also directly include or exclude references like so:
87
+ ```py
88
+ cleaner.exclude(<name_var_1>,<name_var_2>,...)
89
+ ```
90
+ ```py
91
+ cleaner.include(<name_var_1>,<name_var_2>,...)
92
+ ```
93
+ ### Class `Pointer`
94
+ Example:
95
+ ```py
96
+ from memorymanagement import Pointer
97
+ a=10
98
+ x=Pointer(a)
99
+ print(f"a:\n{a}\n\nPointer:\n{x.value}\n\n")
100
+ a=20
101
+ print(f"a:\n{a}\n\nPointer:\n{x.value}\n\n")
102
+ a=10
103
+ x.value=20
104
+ print(f"a:\n{a}\n\nPointer:\n{x.value}")
105
+ ```
106
+ Output:
107
+ ```sh
108
+ a:
109
+ 10
110
+
111
+ Pointer:
112
+ 10
113
+
114
+
115
+ a:
116
+ 20
117
+
118
+ Pointer:
119
+ 20
120
+
121
+
122
+ a:
123
+ 20
124
+
125
+ Pointer:
126
+ 20
127
+ ```
128
+ ### Decorator `pointerize`
129
+ Example:
130
+ ```py
131
+ from memorymanagement import pointerize
132
+ @pointerize
133
+ def myFunction(value:int):
134
+ value=20
135
+ return
136
+ a=10
137
+ print(f"Value: {a}")
138
+ myFunction(Pointer(a))
139
+ print(f"Value: {a}")
140
+ ```
141
+ Output:
142
+ ```sh
143
+ Value: 10
144
+ Value: 20
145
+
146
+ ```
@@ -0,0 +1,20 @@
1
+ """
2
+ Provides memory management support.
3
+
4
+ ---
5
+ ## Module `cleaning`
6
+ The class `Cleaner` flags the global references to erase them when commanded. References can be chosen to be excluded or included again in the process.
7
+ ## Module `pointers`
8
+ A safe implementation of pointers for Python. Written in pure Python, this module includes two things:
9
+ ### 1. Class `Pointer`
10
+ Creates a `Pointer` instance. These pointers point to a reference, not to an object in memory.
11
+ If value for the reference is changed, so is the pointer value and *viceversa*.
12
+ ### 2. Decorator `pointerize`
13
+ Allows a function to receive pointers instead of the normally expected values.
14
+ """
15
+ # Imports
16
+ from .cleaning import Cleaner
17
+ from .pointers import Pointer,pointerize
18
+
19
+ # Declare "__all__"
20
+ __all__=["Cleaner","Pointer","pointerize"]
@@ -0,0 +1,2 @@
1
+ # Imports
2
+ from .cleaning import Cleaner
@@ -0,0 +1,131 @@
1
+ # Imports
2
+ from sys import modules
3
+
4
+ # Define the class "Cleaner"
5
+ class Cleaner:
6
+ """
7
+ Class for references management. It keeps track of the names of the global variables to be deleted and deletes them when ordered.
8
+
9
+ The cleaning process only deletes the flagged references to objects, but doesn't directly force the garbage collector to destroy the objects they are pointing to.
10
+
11
+ ---
12
+ ## WARNING
13
+ THERE CAN ONLY BE **ONE** CLEANER OBJECT.\n
14
+ Initializing a new one will delete all global references to the previous one.
15
+
16
+ ---
17
+ Attributes:
18
+ _not_delete (`list[str]`, Hidden): List of variables to never delete from memory. These cannot be included in the process even if ordered so.\n
19
+ These mainly are variables needed for the system to work and imports.
20
+ _excluded (`list[str]`, Hidden): List of variables excluded from the memory cleaning that can be included again if desired.
21
+ _flagged (`list[str]`, Hidden): List of variables to erase from memory. Variables can be put in and/or taken out through methods.
22
+ ---
23
+
24
+ ## Methods
25
+ :update: *`MethodType`*
26
+ Updates the list of variables to erase from memory including all the new variables global variables not manually excluded.\n
27
+ It also allows to incorporate previously excluded variables.
28
+ :exclude: *`MethodType`*
29
+ Allows you to exclude variables from the cleaning process without need to use the `instance.update()` method.
30
+ :include: *`MethodType`*
31
+ Allows you to include variables in the cleaning process without need to use the `instance.update()` method.
32
+ :clean: *`MethodType`*
33
+ Erases all the flagged references from memory.
34
+ ---
35
+
36
+ ## Properties
37
+ :not_delete: *`MethodType`*, *Getter*
38
+ Returns the list of variables that shouldn't be deleted and can't be included in the cleaning process.
39
+ :excluded: *`MethodType`*, *Getter*
40
+ Returns the list of variables excluded from the cleaning process but can be included again if ordered.
41
+ :flagged: *`MethodType`*, *Getter*
42
+ Returns the list of variables to be erased from memory.
43
+ None of this properties has setter or deleter. Those lists can only be manipulated through the class methods.
44
+ """
45
+ def __init__(self,not_delete:list[str]=list(vars(modules["__main__"])),excluded:list[str]=[],flagged:list[str]=[]):
46
+ """
47
+ Initializes the class instance.\n
48
+ It is recommended to initialize the instance right after all global imports at the beggining of the program so no argument is needed.
49
+
50
+ ---
51
+ Arguments:
52
+ not_delete (`list[str]`, Optional): List of variables to never be deleted. It takes the list of global variables of the main module by default.
53
+ excluded (`list[str]`, Optional): List of variables to be excluded from the memory cleaning process. Empty list by default.
54
+ flagged (`list[str]`, Optional): List of variables to be erased from memory. Empty list by default.
55
+ """
56
+ for key,value in vars(modules["__main__"]).copy().items():
57
+ if isinstance(value,Cleaner) and key in vars(modules["__main__"]).keys():
58
+ del vars(modules["__main__"])[key]
59
+ self._not_delete=not_delete.copy()
60
+ self._excluded=excluded.copy()
61
+ self._flagged=flagged.copy()
62
+ return
63
+ def update(self,exclude:str|list[str]|tuple[str]|None=None,include:str|list[str]|tuple[str]|None=None):
64
+ """
65
+ Flags all the new global variables' references that were not manually excluded here or before. You can also include previously excluded references.
66
+
67
+ ---
68
+ Arguments:
69
+ exclude (`str`|`list[str]`|`tuple[str]`|`None`, Optional): Allows you to exclude a single (`str`) or multiple (`list` or `tuple`) variables.
70
+ `None` by default.
71
+ include (`str`|`list[str]`|`tuple[str]`|`None`, Optional): Allows you to include a single (`str`) or multiple (`list` or `tuple`) variables.
72
+ `None` by default.
73
+ """
74
+ if exclude:
75
+ if isinstance(exclude,str):
76
+ exclude=[exclude]
77
+ self._excluded.extend([var for var in exclude if var not in self._excluded])
78
+ if include:
79
+ if isinstance(include,str):
80
+ include=[include]
81
+ for var in include:
82
+ while var in self._excluded:
83
+ self._excluded.remove(var)
84
+ self._flagged=[var for var in list(vars(modules["__main__"])) if var not in self._not_delete and var not in self._excluded]
85
+ return
86
+ @property
87
+ def not_delete(self):
88
+ return self._not_delete
89
+ @property
90
+ def excluded(self):
91
+ return self._excluded
92
+ @property
93
+ def flagged(self):
94
+ return self._flagged
95
+ def exclude(self,*exclude:str):
96
+ """
97
+ Allows to exclude the desired references from the cleaning process.
98
+
99
+ ---
100
+ Arguments:
101
+ *exclude (`str`): Stream of references to be excluded.
102
+ """
103
+ for var in exclude:
104
+ while var in self._flagged:
105
+ self._flagged.remove(var)
106
+ if var not in self._excluded:
107
+ self._excluded.append(var)
108
+ return
109
+ def include(self,*include:str):
110
+ """
111
+ Allows to include the desired references (previously excluded) in the cleaning process.
112
+
113
+ ---
114
+ Arguments:
115
+ *include (`str`): Stream of references to be included.
116
+ """
117
+ for var in include:
118
+ if var not in self._flagged:
119
+ self._flagged.append(var)
120
+ while var in self._excluded:
121
+ self._excluded.remove(var)
122
+ return
123
+ def clean(self):
124
+ """
125
+ Culminates the cleaning process. Erases all the flagged references.
126
+ """
127
+ for var in self._flagged:
128
+ if var in list(vars(modules["__main__"])):
129
+ del vars(modules["__main__"])[var]
130
+ self._flagged.clear()
131
+ return
@@ -0,0 +1,3 @@
1
+ # Import from modules
2
+ from .core import Pointer # Class "Pointer"
3
+ from .decorators import pointerize # Decorator "pointerize"
@@ -0,0 +1,127 @@
1
+ # Import "TypeVar" and "Generic"
2
+ from typing import TypeVar,Generic
3
+ # Import "modules" from "sys" package
4
+ from sys import modules
5
+ # Import "currentframe" from "inspect" package
6
+ from inspect import currentframe
7
+
8
+ # Create new generic type
9
+ object_type=TypeVar("object_type")
10
+ # Define the class "Pointer"
11
+ class Pointer(Generic[object_type]):
12
+ """
13
+ Implements pointers in Python for both mutable (though unneded) and non-mutable objects.
14
+ These pointers are completely safe and do not work internally as C's pointers, they are just an imitation of their behaviour.
15
+
16
+ When a Pointer instance is created, though it stores a value, it "points" to an specific reference, not the value in a memory adress.
17
+ This way, all references pointing to the same non-mutable object don't change when the pointer is updated, avoiding a potential mess.
18
+
19
+ Non-mutable objects still change their memory adresses when re-referenced but the reference and the value stored in the pointer are forced to share memory adress.
20
+
21
+ Value and memory adress updates are not made in real-time, but the methods update the non-coincident values:
22
+ * **Getter**: it updates its own value to the variable's one (if variable was given instead of literal).
23
+ * **Setter**: it updates the value of the variable to its own (if variable was given instead of literal).
24
+ * **Deleter**: it also deletes the original variable (if variable was given instead of literal).
25
+ ---
26
+ Attributes:
27
+ value (`Any`, Hidden): Object to point to.
28
+ attr (`str`|`None`, Hidden): Attribute of class instance. Only if `value` is a class instance.
29
+ name (`str`, Hidden): Name of the global variable to which the pointer is pointing.
30
+ Could require an input from the user to introduce the name of the variable if more than one is found.
31
+ vars_dict (`dict[str,Any]`, Hidden): Dictionary of variables.
32
+ `vars(modules["__main__"])` if pointing to a global variable and `inspect.currentframe().f_back.f_locals` if pointing to a local variable.
33
+ ---
34
+
35
+ ## Methods
36
+ 1. **Getter**: Gets the value.
37
+ 2. **Setter**: Sets a new value.
38
+ 3. **Deleter**: Deletes the value.
39
+ All three methods are part of the same property.
40
+ ---
41
+ ## Properties
42
+ :value: *`MethodType`*
43
+ Points to `value` (or `value.attr`). Called through `<instance>.value`. All three possible objects (getter, setter and deleter) have been declared.
44
+
45
+ ---
46
+
47
+ ## Currently supported
48
+ Both global and local variables can be pointed at.
49
+
50
+ Literals are **not** supported because of it being useless. If you create a `Pointer` instance for a literal and works,
51
+ keep in mind that it is merely by accident and it is **not** the intended use it was designed for.
52
+ Currently, the only use for inserting a literal instead of a referenced value could be for the class code to display all the references pointing to that literal
53
+ and bind the instance to the desired reference.
54
+ """
55
+ def __init__(self,value=None,attr:str|None=None,*,local:bool=False):
56
+ """
57
+ Arguments:
58
+ value (`Any`,Optional): Object to point to. If want to point to a class instance atribute, introduce the class instance without the atribute.
59
+ attr (`str`|`None`, Optional): Atribute of the class instance to which you want to point. Leave empty if `value` is not a class instance.
60
+ local (`bool`, Optional): Indicates if the value to point to is a local variable (`True` for yes and `False` for no). `False` by default.
61
+ """
62
+ if local:
63
+ vars_dict=currentframe().f_back.f_locals
64
+ else:
65
+ vars_dict=vars(modules["__main__"])
66
+ self._value=value
67
+ self._vars_dict=vars_dict
68
+ self._attr=attr
69
+ name=None
70
+ name=[]
71
+ for key,v in vars_dict.items():
72
+ try:
73
+ if v is value:
74
+ name.append(key)
75
+ except ValueError:
76
+ pass
77
+ if len(name)>1:
78
+ print(f"{name}\nMultiple variable names found for the 'value' parameter, introduce the correct one:")
79
+ while True:
80
+ name_aux=input()
81
+ if name_aux in name:
82
+ break
83
+ else:
84
+ print("Error, introduce the correct variable name for the 'value' parameter:")
85
+ name=name_aux
86
+ del name_aux
87
+ elif len(name)==1:
88
+ name=name[0]
89
+ elif len(name)==0:
90
+ name=None
91
+ self._name=name
92
+ return
93
+ @property
94
+ def value(self):
95
+ if self._attr:
96
+ if self._name and self._name not in list(self._vars_dict):
97
+ del self._value,self._attr
98
+ raise KeyError("The class instance has already been deleted, so the pointer no longer has access to it.")
99
+ elif self._attr not in dir(self._value):
100
+ raise AttributeError(f"The atribute '{self._attr}' has already been deleted, so the pointer no longer has access to it.")
101
+ return getattr(self._value,self._attr)
102
+ else:
103
+ if self._name:
104
+ if self._name not in list(self._vars_dict):
105
+ del self._value
106
+ raise KeyError("The variable has already been deleted, so the pointer no longer has access to it.")
107
+ if self._value is not self._vars_dict[self._name]:
108
+ self._value=self._vars_dict[self._name]
109
+ return self._value
110
+ @value.setter
111
+ def value(self,value):
112
+ if self._attr:
113
+ setattr(self._value,self._attr,value)
114
+ else:
115
+ self._value=value
116
+ if self._name and value is not self._vars_dict[self._name]:
117
+ self._vars_dict[self._name]=value
118
+ return
119
+ @value.deleter
120
+ def value(self):
121
+ if self._attr:
122
+ delattr(self._value,self._attr)
123
+ else:
124
+ del self._value
125
+ if self._name:
126
+ del self._vars_dict[self._name]
127
+ return
@@ -0,0 +1,77 @@
1
+ # Imports
2
+ from sys import settrace
3
+ from inspect import signature
4
+ from functools import wraps
5
+ from .core import Pointer
6
+
7
+ # Define the decorator
8
+ def pointerize(func):
9
+ """
10
+ Allows the decorated function to receive pointers instead of the normally expected values.
11
+
12
+ The decorated function is still able to receive its normally expected parameters.
13
+
14
+ ---
15
+ Arguments:
16
+ func (`FunctionType`): Decorated function.
17
+ """
18
+ # Makes the decorating function to keep its identity
19
+ @wraps(func)
20
+ # Define the wrapper
21
+ def wrapper(*args,**kwargs):
22
+ # Obtain the signature (parameters and defaults) of the decorated function
23
+ sig=signature(func)
24
+ # Bind call arguments to the signature
25
+ bound=sig.bind(*args,**kwargs)
26
+ # Defaults all the arguments which haven't been passed
27
+ bound.apply_defaults()
28
+
29
+ # Dictionary containing all the parameters
30
+ param_map=bound.arguments
31
+
32
+ # Dictionary containing only the parameters that are pointers
33
+ pointer_map={
34
+ name:val for name,val in param_map.items()
35
+ if isinstance(val,Pointer)
36
+ }
37
+
38
+ # List containing all the positional arguments to be passed to the decorated function
39
+ exec_args=[
40
+ val.value if isinstance(val,Pointer) else val
41
+ for val in bound.args
42
+ ]
43
+ # Dictionary containing all the keyword arguments to be passed to the decorated function
44
+ exec_kwargs={
45
+ k:v.value if isinstance(v,Pointer) else v
46
+ for k,v in bound.kwargs.items()
47
+ }
48
+
49
+ # Empty dict, future source to update pointers' values
50
+ frame_data={}
51
+
52
+ # Tracer function compatible with the sys.settrace API
53
+ def tracer(frame,event,arg):
54
+ if event=="return" and frame.f_code is func.__code__:
55
+ frame_data.update(frame.f_locals)
56
+ return tracer
57
+ # Activate tracing
58
+ settrace(tracer)
59
+ # We try to execute the function
60
+ try:
61
+ result=func(*exec_args,**exec_kwargs)
62
+ # Even if the program meets an error
63
+ finally:
64
+ # It deactivates tracing
65
+ settrace(None)
66
+ # If no exception or error is raised, the program continues from here
67
+
68
+ # Iterates through the pointers
69
+ for name,ptr in pointer_map.items():
70
+ # Checks if the parameter name is in the traced frame (of local variables of the decorated function)
71
+ if name in frame_data:
72
+ # In which case, the pointer's value is updated
73
+ ptr.value=frame_data[name]
74
+ # Return the result of the decorated function
75
+ return result
76
+ # Return the wrapper
77
+ return wrapper
@@ -0,0 +1,162 @@
1
+ Metadata-Version: 2.4
2
+ Name: memorymanagement
3
+ Version: 1.0.0
4
+ Summary: Adds support for memory management
5
+ Home-page: https://github.com/Ricardo-Werner-Rivas/python-memory-management/tree/main
6
+ Author: Ricardo Werner Rivas
7
+ Author-email: ricardowernerrivas@gmail.com
8
+ License: MIT
9
+ Project-URL: Issues Page, https://github.com/Ricardo-Werner-Rivas/python-memory-management/issues
10
+ Project-URL: Repository, https://github.com/Ricardo-Werner-Rivas/python-memory-management
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Operating System :: Microsoft :: Windows
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Dynamic: license-file
16
+
17
+ # `memorymanagement`
18
+ Provides memory management support.
19
+ ## Modules
20
+ ### `cleaning`
21
+ Provides the class `Cleaner`, which allows you to flag references stored in memory to eventually erase them.
22
+ It is also possible to modify the list of flagged references through its methods.
23
+ ### `pointers`
24
+ Provides a safe implementation of pointers for Python.
25
+ #### Class `Pointer`
26
+ The pointer itself. Imitates the behaviour of C pointers. This pointer points to a reference, not to an object stored in memory.
27
+ #### Decorator `pointerize`
28
+ Allows functions to receive pointers instead of values.
29
+ ## Installation
30
+ You can install the `memorymanager` package from PyPI as follows:
31
+ ```bash
32
+ pip install memorymanagement
33
+ ```
34
+ You can also install the `memorymanager` package (Test PyPI versión of `memorymanager`) from TestPyPI as follows:
35
+ ```bash
36
+ pip install --index-url https://test.pypi.org/simple/ memorymanager
37
+ ```
38
+ For TestPyPI versión, `--no-deps` option is not needed because it has no dependencies.
39
+ ## How to use
40
+ ### Class `Cleaner`
41
+ ```py
42
+ # Imports
43
+ # Make your imports here
44
+ from memorymanagement import Cleaner # Importing class Cleaner
45
+ ```
46
+ Right after imports are done, I recommend to initialize an instance of class `Cleaner`, so no arguments are needed. This is the optimal use this class was designed for.
47
+ ```py
48
+ # Initialize cleaner object
49
+ cleaner=Cleaner()
50
+ ```
51
+ Create, for example, these global variables:
52
+ ```py
53
+ value_1=10
54
+ value_2=50
55
+ value_3=100
56
+ ```
57
+ Update the list of flagged references like one of the following:
58
+ * Including all new global variables:
59
+ ```py
60
+ cleaner.update()
61
+ print(cleaner.flagged)
62
+ ```
63
+ Output:
64
+ ```sh
65
+ ["value_1","value_2","value_3"]
66
+ ```
67
+ * Excluding some variables:
68
+ ```py
69
+ cleaner.update(exclude="value_2")
70
+ print(cleaner.flagged)
71
+ ```
72
+ Output:
73
+ ```sh
74
+ ["value_1","value_3"]
75
+ ```
76
+ ---
77
+ ```py
78
+ cleaner.update(exclude=["value_2","value_3"])
79
+ print(cleaner.flagged)
80
+ ```
81
+ Output:
82
+ ```sh
83
+ ["value_1"]
84
+ ```
85
+ * Include again some variables:
86
+
87
+ After having excluded some variables
88
+ ```py
89
+ cleaner.update(exclude=["value_2","value_3"])
90
+ ```
91
+ You can reintroduce them
92
+ ```py
93
+ # Create a new variable and update
94
+ value_4=150
95
+ cleaner.update(exclude="value_4",include="value_2") # "include" can also be a list of strings
96
+ print(cleaner.flagged)
97
+ ```
98
+ Output:
99
+ ```sh
100
+ ["value_1","value_2"]
101
+ ```
102
+ You can also directly include or exclude references like so:
103
+ ```py
104
+ cleaner.exclude(<name_var_1>,<name_var_2>,...)
105
+ ```
106
+ ```py
107
+ cleaner.include(<name_var_1>,<name_var_2>,...)
108
+ ```
109
+ ### Class `Pointer`
110
+ Example:
111
+ ```py
112
+ from memorymanagement import Pointer
113
+ a=10
114
+ x=Pointer(a)
115
+ print(f"a:\n{a}\n\nPointer:\n{x.value}\n\n")
116
+ a=20
117
+ print(f"a:\n{a}\n\nPointer:\n{x.value}\n\n")
118
+ a=10
119
+ x.value=20
120
+ print(f"a:\n{a}\n\nPointer:\n{x.value}")
121
+ ```
122
+ Output:
123
+ ```sh
124
+ a:
125
+ 10
126
+
127
+ Pointer:
128
+ 10
129
+
130
+
131
+ a:
132
+ 20
133
+
134
+ Pointer:
135
+ 20
136
+
137
+
138
+ a:
139
+ 20
140
+
141
+ Pointer:
142
+ 20
143
+ ```
144
+ ### Decorator `pointerize`
145
+ Example:
146
+ ```py
147
+ from memorymanagement import pointerize
148
+ @pointerize
149
+ def myFunction(value:int):
150
+ value=20
151
+ return
152
+ a=10
153
+ print(f"Value: {a}")
154
+ myFunction(Pointer(a))
155
+ print(f"Value: {a}")
156
+ ```
157
+ Output:
158
+ ```sh
159
+ Value: 10
160
+ Value: 20
161
+
162
+ ```
@@ -0,0 +1,14 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ setup.cfg
5
+ memorymanagement/__init__.py
6
+ memorymanagement.egg-info/PKG-INFO
7
+ memorymanagement.egg-info/SOURCES.txt
8
+ memorymanagement.egg-info/dependency_links.txt
9
+ memorymanagement.egg-info/top_level.txt
10
+ memorymanagement/cleaning/__init__.py
11
+ memorymanagement/cleaning/cleaning.py
12
+ memorymanagement/pointers/__init__.py
13
+ memorymanagement/pointers/core.py
14
+ memorymanagement/pointers/decorators.py
@@ -0,0 +1 @@
1
+ memorymanagement
@@ -0,0 +1,3 @@
1
+ [build-system]
2
+ requires=["setuptools"]
3
+ build-backend="setuptools.build_meta"
@@ -0,0 +1,25 @@
1
+ [metadata]
2
+ name = memorymanagement
3
+ version = 1.0.0
4
+ author = Ricardo Werner Rivas
5
+ author_email = ricardowernerrivas@gmail.com
6
+ description = Adds support for memory management
7
+ long_description = file:README.md
8
+ long_description_content_type = text/markdown
9
+ license = MIT
10
+ license_files = LICENSE
11
+ url = https://github.com/Ricardo-Werner-Rivas/python-memory-management/tree/main
12
+ project_urls =
13
+ Issues Page=https://github.com/Ricardo-Werner-Rivas/python-memory-management/issues
14
+ Repository=https://github.com/Ricardo-Werner-Rivas/python-memory-management
15
+ classifiers =
16
+ Programming Language :: Python
17
+ Operating System :: Microsoft :: Windows
18
+
19
+ [options]
20
+ packages = find:
21
+
22
+ [egg_info]
23
+ tag_build =
24
+ tag_date = 0
25
+